# em-hiredis
## What
A Redis client for EventMachine designed to be fast and simple.
## Why
I wanted a client which:
* used the C hiredis library to parse redis replies
* had a convenient API for pubsub
* exposed the state of the underlying redis connections so that custom failover logic could be written outside the library
Also, <https://github.com/madsimian/em-redis> is no longer maintained.
## Getting started
Connect to redis:
require 'em-hiredis'
redis = EM::Hiredis.connect
Or, connect to redis with a redis URL (for a different host, port, password, DB)
redis = EM::Hiredis.connect("redis://:secretpassword@example.com:9000/4")
Commands may be sent immediately. Any commands sent while connecting to redis will be queued.
All redis commands are available without any remapping of names, and return a deferrable
redis.set('foo', 'bar').callback {
redis.get('foo').callback { |value|
p [:returned, value]
}
}
If redis replies with an error (for example you called a hash operation against a set or the database is full), or if the redis connection disconnects before the command returns, the deferrable will fail.
redis.sadd('aset', 'member').callback {
response_deferrable = redis.hget('aset', 'member')
response_deferrable.errback { |e|
p e # => #<EventMachine::Hiredis::RedisError: Error reply from redis (wrapped in redis_error)>
p e.redis_error # => #<RuntimeError: ERR Operation against a key holding the wrong kind of value>
}
}
As a shortcut, if you're only interested in binding to the success case you can simply provide a block to any command
redis.get('foo') { |value|
p [:returned, value]
}
## Understanding the state of the connection
When a connection to redis server closes, a `:disconnected` event will be emitted and the connection will be immediately reconnect. If the connection reconnects a `:connected` event will be emitted.
If a reconnect fails to connect, a `:reconnect_failed` event will be emitted (rather than `:disconnected`) with the number of consecutive failures, and the connection will be retried after a timeout (defaults to 0.5s, can be set via `EM::Hiredis.reconnect_timeout=`).
If a client fails to reconnect 4 consecutive times then a `:failed` event will be emitted, and any queued redis commands will be failed (otherwise they would be queued forever waiting for a reconnect).
## Pubsub
The way pubsub works in redis is that once a subscribe has been made on a connection, it's only possible to send (p)subscribe or (p)unsubscribe commands on that connection. The connection will also receive messages which are not replies to commands.
The regular `EM::Hiredis::Client` no longer understands pubsub messages - this logic has been moved to `EM::Hiredis::PubsubClient`. The pubsub client can either be initialized directly (see code) or you can get one connected to the same redis server by calling `#pubsub` on an existing `EM::Hiredis::Client` instance.
Pubsub can either be used in em-hiredis in a close-to-the-metal fashion, or you can use the convenience functionality for binding blocks to subscriptions if you prefer (recommended).
### Close to the metal pubsub interface
Basically just bind to `:message` and `:pmessage` events:
# Create two connections, one will be used for subscribing
redis = EM::Hiredis.connect
pubsub = redis.pubsub
pubsub.subscribe('bar.0').callback { puts "Subscribed" }
pubsub.psubscribe('bar.*')
pubsub.on(:message) { |channel, message|
p [:message, channel, message]
}
pubsub.on(:pmessage) { |key, channel, message|
p [:pmessage, key, channel, message]
}
EM.add_periodic_timer(1) {
redis.publish("bar.#{rand(2)}", "hello").errback { |e|
p [:publisherror, e]
}
}
### Richer pubsub interface
If you pass a block to `subscribe` or `psubscribe`, the passed block will be called whenever a message arrives on that subscription:
redis = EM::Hiredis.connect
puts "Subscribing"
redis.pubsub.subscribe("foo") { |msg|
p [:sub1, msg]
}
redis.pubsub.psubscribe("f*") { |channel, msg|
p [:sub2, msg]
}
EM.add_periodic_timer(1) {
redis.publish("foo", "Hello")
}
EM.add_timer(5) {
puts "Unsubscribing sub1"
redis.pubsub.unsubscribe("foo")
}
It's possible to subscribe to the same channel multiple time and just unsubscribe a single callback using `unsubscribe_proc` or `punsubscribe_proc`.
## Lua
You can of course call EVAL or EVALSHA directly; the following is a higher-level API.
Registering a named command on a redis client defines a ruby method with the given name on the client:
redis.register_script(:multiply, <<-END)
return redis.call('get', KEYS[1]) * ARGV[1]
END
The method can be called in a very similar way to any other redis command; the only difference is that the first argument must be an array of keys, and the second (optional) an array of values.
# Multiplies the value at key foo by 2
redis.multiply(['foo'], [2]).callback { ... }
Lua commands are submitted to redis using EVALSHA for efficiency. If redis replies with a NOSCRIPT error, the command is automatically re-submitted with EVAL; this is totally transparent to your code and the intermediate 'failure' will not be passed to your errback.
You may register scripts globally, in which case they will be available to all clients:
EM::Hiredis::Client.register_script(:multiply, <<-END)
return redis.call('get', KEYS[1]) * ARGV[1]
END
As a final convenience, it is possible to load all lua scripts from a directory automatically. All `.lua` files in the directory will be registered, and named according to filename (so a file called `sum.lua` becomes available as `redis.sum(...)`).
EM::Hiredis::Client.load_scripts_from('./lua_scripts')
For examples see `examples/lua.rb` or `lib/em-hiredis/lock_lua`.
## Inactivity checks
Sometimes a network connection may hang in ways which are difficult to detect or involve very long timeouts before they can be detected from the application layer. This is especially true of Redis Pubsub connections, as they are not request-response driven. It is very difficult for a listening client to descern between a hung connection and a server with nothing to say.
To start an application layer ping-pong mechanism for testing connection liveness, call the following at any time on a client:
redis.configure_inactivity_check(5, 3)
This configures a `PING` command to be sent if 5 seconds elapse without receiving any data from the server, and a reconnection to be triggered if a futher 3 seconds elapse after the `PING` is submitted.
This configuration is per client, you may choose different value for clients with different expected traffic patterns, or activate it on some and not at all on others.
### PING and Pubsub
Because the Redis Pubsub protocol limits the set of valid commands on a connection once it is in "Pubsub" mode, `PING` is not supported in this case (though it may be in future, see https://github.com/antirez/redis/issues/420). In order to create some valid request-response traffic on the connection, a Pubsub connection will issue `SUBSCRIBE "__em-hiredis-ping"`, followed by a corresponding `UNSUBSCRIBE` immediately on success of the subscribe.
While less than ideal, this is the case where an application layer inactivity check is most valuable, and so the trade off is reasonable until `PING` is supported correctly on Pubsub connections.
## Developing
You need bundler and a local redis server running on port 6379 to run the test suite.
# WARNING: The tests call flushdb on db 9 - this clears all keys!
bundle exec rake
Run an individual spec:
bundle exec rspec spec/redis_commands_spec.rb
Many thanks to the em-redis gem for getting this gem bootstrapped with some tests.
没有合适的资源?快使用搜索试试~ 我知道了~
Eventmachine redis 客户端.zip
共39个文件
rb:26个
lua:3个
txt:2个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 2 浏览量
2024-12-03
09:21:56
上传
评论
收藏 33KB ZIP 举报
温馨提示
Eventmachine redis 客户端埃姆希雷迪斯什么EventMachine 的 Redis 客户端设计得快速而简单。为什么我想要一个这样的客户使用 C hiredis 库来解析 redis 回复有一个方便的 pubsub API公开底层 redis 连接的状态,以便可以在库外部编写自定义故障转移逻辑此外,https://github.com/madsimian/em-redis不再维护。入门连接redisrequire 'em-hiredis'redis = EM::Hiredis.connect或者,使用 redis URL 连接到 redis(针对不同的主机、端口、密码、数据库)redis = EM::Hiredis.connect("redis://:secretpassword@example.com:9000/4")命令可以立即发送。连接到 redis 时发送的任何命令都将排队。所有 redis 命令都无需重新映射名称即可使用,并返回可延迟的redis.set('foo', 'bar').callba
资源推荐
资源详情
资源评论
收起资源包目录
Eventmachine redis 客户端.zip (39个子文件)
lib
em-hiredis.rb 2KB
em-hiredis
lock_lua
lock_acquire.lua 500B
lock_release.lua 199B
pubsub_client.rb 6KB
client.rb 3KB
event_emitter.rb 539B
lock.rb 3KB
base_client.rb 8KB
persistent_lock.rb 2KB
version.rb 69B
connection.rb 1KB
Rakefile 189B
.rspec 9B
标签.txt 5B
LICENCE 1KB
examples
lua_example.rb 868B
getting_started.rb 377B
pubsub_more.rb 1KB
pubsub_raw.rb 593B
pubsub_basics.rb 431B
lua
sum.lua 88B
spec
url_param_spec.rb 1KB
lock_spec.rb 3KB
live_redis_protocol_spec.rb 10KB
redis_commands_spec.rb 26KB
support
connection_helper.rb 342B
redis_mock.rb 1KB
inprocess_redis_mock.rb 2KB
inactivity_check_spec.rb 2KB
connection_spec.rb 1KB
pubsub_spec.rb 10KB
base_client_spec.rb 3KB
spec_helper.rb 425B
CHANGELOG.md 1KB
资源内容.txt 871B
Gemfile 38B
.gitignore 49B
em-hiredis.gemspec 985B
README.md 8KB
共 39 条
- 1
资源评论
赵闪闪168
- 粉丝: 1677
- 资源: 5392
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于Vue.js快速构建python桌面应用程序的模板项目源码+运行教程(支持打包为可执行文件).zip
- 防护具检测57-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 视频下载-b站视频下载器
- CSV数据操作的工具包-含合并CSV文件、Excel转CSV、CSV转XLSX、统计CSV行数、重命名表头、选择和重排CSV列等功能.zip
- App商店优化(ASO)权威指南:提高App可见度与转化率的技术策略
- TomVPN_3.0.7.apk
- AEC论文解读 - ACOUSTIC ECHO CANCELLATION WITH THE DUAL-SIGNAL TRANSFORMATION LSTM NETWORK
- Vegetation Studio 1.5.3
- 阀门检测49-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 非常好的SqlServer大量源代码和教程资料100%好用.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功