A light-weight Redis client for Crystal.
MiniRedis is a light-weight low-level alternative to existing Redis client implementations.
In comparison with crystal-redis, MiniRedis has lesser memory consumption, built-in logging and first-class support for raw bytes. It also doesn't need to be updated with every Redis release.
On the other hand, MiniRedis doesn't have commands API (i.e. instead of redis.ping
you should write redis.send("PING")
). However, such a low-level interface terminates the dependency on the third-party client maintainer (i.e. me), which makes it a perfect fit to use within a shard.
You can always find the actual Redis commands API at https://redis.io/commands.
Benchmarks code can be found at https://github.com/vladfaust/mini_redis-benchmarks. These are recent results of comparison MiniRedis with crystal-redis.
> env REDIS_URL=redis://localhost:6379/1 crystal src/send.cr --release
mini_redis 13.4k ( 74.62µs) (± 2.50%) 32 B/op fastest
crystal-redis 13.36k ( 74.83µs) (± 2.97%) 144 B/op 1.00× slower
Conclusion: mini_redis
is more memory-efficient.
1 million pipelined send
s, average from 30 times repeats:
> env REDIS_URL=redis://localhost:6379/1 crystal src/pipeline.cr --release
mini_redis 914.569ms 1.093M ops/s
crystal-redis 908.182ms 1.101M ops/s
Conclusion: mini_redis
has almost the same speed as crystal-redis
.
- Add the dependency to your
shard.yml
:
dependencies:
mini_redis:
github: vladfaust/mini_redis
version: ~> 0.2.0
- Run
shards install
This shard follows Semantic Versioning v2.0.0, so check releases and change the version
accordingly. Note that until Crystal is officially released, this shard would be in beta state (0.*.*
), with every minor release considered breaking. For example, 0.1.0
→ 0.2.0
is breaking and 0.1.0
→ 0.1.1
is not.
require "mini_redis"
redis = MiniRedis.new
# MiniRedis responses wrap `Int64 | String | Bytes | Nil | Array(Value)` values,
# which map to `Integer`, `Simple String`, `Bulk String`, `Nil` and `Array` Redis values
# SET command returns `Simple String`, which is `String` in Crystal
pp redis.send("SET", "foo", "bar").raw.as(String) # => "OK"
# GET command returns `Bulk String`, which is `Bytes` in Crystal
bytes = redis.send("GET", "foo").raw.as(Bytes)
pp String.new(bytes) # => "bar"
# Bytes command payloads are also supported
redis.send("set", "foo".to_slice, "bar".to_slice)
response = redis.pipeline do |pipe|
# WARNING: Accessing the `.send` return value
# within the pipe block would crash the program!
pipe.send("SET", "foo", "bar")
end
pp typeof(response) # => [MiniRedis::Value(@raw="OK")]
response = redis.transaction do |tx|
pp tx.send("SET", "foo", "bar").raw.as(String) # => "QUEUED"
end
pp typeof(response) # => MiniRedis::Value(@raw=[MiniRedis::Value(@raw="OK")])
pool = MiniRedis::Pool.new
response = pool.get do |redis|
# Redis is MiniRedis instance, can do anything
redis.send("PING")
end
# Return value equals to the block's
pp response.raw.as(String) # => "PONG"
conn = pool.get
pp conn.send("PING").raw.as(String) # => "PONG"
pool.release(conn) # Do not forget to put it back!
env REDIS_URL=redis://localhost:6379 crystal spec
and you're good to go.
- Fork it (https://github.com/vladfaust/mini_redis/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'feat: new feature'
) using angular-style commits - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
- Vlad Faust - creator and maintainer