Redis Client for Crystal
A Redis client for the Crystal programming language.
Features
- Performance (> 680,000 commands per second using pipeline on a MacBook Air with a single client thread)
- Pipelining
- Transactions
- LUA Scripting
- All string commands
- All hash commands
- All list commands
- All set commands
- All hyperloglog commands
- All commands for bit operations
- All sorted set commands
- All geo commands
- Publish/subscribe
Installation
Add it to your shard.yml
:
dependencies:
redis:
github: stefanwille/crystal-redis
version: ~> 2.4.1
and then install the library into your project:
$ shards install
Installation on MacOS X
On MacOS X you may get this error:
ld: library not found for -lssl (this usually means you need to install the development package for libssl)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
...
Or this warning:
Package libssl was not found in the pkg-config search path.
Perhaps you should add the directory containing `libssl.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libssl' found
Package libcrypto was not found in the pkg-config search path.
Perhaps you should add the directory containing `libcrypto.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libcrypto' found
The problem is that Crystal can't find openssl, because it is not installed by default on MacOS X.
The fix:
- Install openssl via Homebrew:
$ brew install openssl
- Set the environment variable
PKG_CONFIG_PATH
:
$ export PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig
Note: Please write me if you know a better way!
Required Crystal Version
This library needs Crystal version >= 0.25.0
I haven't tested older Crystal versions.
Usage
Require the package:
require "redis"
then
redis = Redis.new
Then you can call Redis commands on the redis
object:
redis.set("foo", "bar")
redis.get("foo")
Connection Pooling
Since version 2.0.0, a connection pool is built in. It is used implicitly through Redis::PooledClient
:
redis = Redis::PooledClient.new
10.times do |i|
spawn do
redis.set("foo#{i}", "bar")
redis.get("foo#{i}") # => "bar"
end
end
This redis
instance can be shared across fibers, and accepts the same Redis commands as the Redis
class.
It automatically allocates and frees connections from/to the pool, per command.
Examples
To get started, see the examples:
- There is a separate git repository crystal-redis-examples with examples.
- start with this basic example
- look at the other examples
- the spec contains even more usage examples
Documentation
- API documentation -
start reading it at the class
Redis
. - Redis commands documentation - the original Redis documentation is necessary, as the API documentation above is just a quick reference
- Redis documentation page - general information about Redis and its concepts
Performance
I have benchmarked Crystal-Redis against several other client libraries in various programming languages in this blog article.
Here are some results:
-
Crystal: With this library I get > 680,000 commands per second using pipeline on a MacBook Air with a single client thread.
-
C: The equivalent program written in C with Hiredis gets me 340,000 commands per second.
-
Ruby: Ruby 2.2.1 with the redis-rb and Hiredis driver handles 150,000 commands per second.
Read more results for Go, Java, Node.js.
Status
I have exercised every API method in the spec and built some example programs. Some people report production usage.
I took great care to make this library very usable with respect to API, reliability and documentation.
Development
This project requires a locally running redis server running on port 6379 and with a Unix socket located at /tmp/redis.sock. In Homebrew's default redis.config the Unix domain socket option is disabled. To enable, edit /usr/local/etc/redis.conf
or whatever your redis.conf
is and uncomment this line:
# unixsocket /tmp/redis.sock
so that it reads
unixsocket /tmp/redis.sock
Then you can run the specs via
$ crystal spec
WARNING
Running the spec will delete database number 0!
Questions, Bugs & Support
If you have questions or need help, please open a ticket in the GitHub issue tracker. This way others can benefit from the discussion.