mini_redis
MiniRedis
A light-weight Redis client for Crystal.
About
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
Benchmarks code can be found at https://github.com/vladfaust/mini_redis-benchmarks. These are recent results of comparison MiniRedis with crystal-redis.
send
benchmarks
> 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.
Pipeline mode benchmarks
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
.
Installation
- 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.
Usage
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)
Pipelining
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")]
Transactions
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")])
Connection pool
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!
Development
env REDIS_URL=redis://localhost:6379 crystal spec
and you're good to go.
Contributing
- 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
Contributors
- Vlad Faust - creator and maintainer