Computer Science is hard, but let's make it funnier. In this article, I want to explore technologies and play with them without always having a structure to it.
This article is one of these. I will share my thoughts and idea, playing along with Redis and Ruby, Like I said less structured and maybe comments or deep dive, but I had a lot of fun writing and playing with this.
Delete key by pattern Redis
Recently, I encountered the issue of deleting keys in a Redis instance that is used as a cache. At this moment, I had not used the ruby/redis API.
Unfortunately, I had to retrieve all the keys manually and delete them since Redis itself does not have a pattern matching on delete. So you have to delete your keys one by one.
redis-cli
127.0.0.1:6379> keys myk*
1) "myked"
2) "mykey"
127.0.0.1:6379> del myk* // not working
(integer) 0
127.0.0.1:6379> del mykey
(integer) 1
If you use ruby, the ruby/redis API solves this issue. You have several ways to do it :
- Use
redis.keys(pattern)
, which is strongly discouraged because of poor performance, and then do a map against your list of keys and delete them. - Use
redis.scan_each(match: pattern)
, that does not exists in Redis itself. And as we the precedent method, you map against your list and do whatever you want.
require "redis"
redis = Redis.new(host: 'localhost')
## discouraged because of poor performance
redis.keys("myk*").map do |s|
p redis.get(s)
end
## Use this instead
redis.scan_each(match: 'myk*') do |name| ## encourage
p redis.get(name)
end
Use transactions in Redis
If you have used a database, you will likely have heard of a transaction. These are used to ensure the ACID principles.
The transaction ensures that when you run it, all the changement you did occur or none of them. This ensures that you are always in a consistent state in your database.
You can run them in Redis too in multiple ways:
https://redis.io/docs/manual/transactions/
TOCHANGE
redis.multi do |multi|
multi.set("key", "value")
multi.incr("counter")
end # => ["OK", 6]
Create a simple queueing jobs
This was the funniest part for me. You may know Sidekiq, an asynchronous job queuing system.
To run Sidekiq, you need Redis to queue all your jobs and then retrieve and run them.
This is not using the Pub/Sub mechanism of Redis.
So I created a queuing system and asynchronous job runner with this mechanism.
Let's do it!
First, I create a rails app only; I will call it frontkiq!
rails new frontkiq
Once done, I decided to do something simple, create a model.
rails g model User name:string
And then the fun begins:
I went to the lib directory and created two files. In the first one, we will call it queue_subs.rb
. I have made a subscriber to my queue on two different channels.
The first is created, where you create a User, and the other is found, where you find a user.
##lib/queue.rb
require "redis"
redis = Redis.new(host: 'localhost')
redis.subscribe(["create","find"]) do |on|
on.message do |channel,message|
if channel == "create"
User.create!(name: message)
end
if channel == "find"
p User.find_by(name: message)
end
User.create!(name: message)
end
end
Then you run your queueing system with the:
rails runner ./queue.rb
And now, if you pop up an irb console, for example, you can play along with :
rails c
Loading development environment (Rails 7.0.6)
irb(main):001:0> require 'redis'
=> false
irb(main):002:0> redis = Redis.new
=> #<Redis client v4.8.1 for redis://127.0.0.1:6379/0>
irb(main):004:0> redis.publish('create','lucas')
=> 1
irb(main):005:0> redis.publish('find','lucas')
=> 1
irb(main):006:0>
You have in your rails runner terminal :
#<User id: 6, name: "lucas", created_at: "2023-07-06 16:23:08.066413000 +0000", updated_at: "2023-07-06 16:23:08.066413000 +0000">
Of course this will not replace Sidekiq or any queuing system. No retry mechanisms, never ensure that you job is ran. But it is funny to discover technologies and
Conclusion
I had a lot of fun writing this article. I hope you have learned some stuff. Not much to say except, keep learning and enjoy programming.
See you for next article ! :D
Top comments (0)