我尝试创建了一个可用于在 Ruby 中使用 Redis 集群的 gem
这篇文章的概要是什么?
大约半年前,ElastiCache开始支持Redis 3.2系列,并且可以使用Redis Cluster(详情请见:https://aws.amazon.com/jp/blogs/news/amazon-elasticache-for-redis-update-sharded-clusters-engine-improvements-and-more/)。通过这样的更新,即使在大规模写入的情况下,也可以进行扩展,并且可以将数据存储在最大3.5TiB的内存中。
早点儿在Ruby上尝试使用时,发现找不到适用于Ruby的好用的Redis集群gem,于是便自己动手开发了一个。在本篇文章中,将简单介绍如何使用。
莫奈
由于 redis-cluster 这个宝石(gem)的名称已经被占用,所以在对相当有名的 memcached gem – dalli 有些微的参考下,我决定将其命名为 renoir。
宝石: https://rubygems.org/gems/renoir
GitHub仓库: https://github.com/saidie/renoir
奥斯卡·雷诺阿能做到的事情
举个例子,安装完 renoir 后,可以像这样使用。
require 'renoir'
rc = Renoir::Client.new(cluster_nodes: ['127.0.0.1:30001'])
p rc.set('hoge', 123, nx: true)
p rc.zrange('fuga', 0, -1, with_scores: true)
127.0.0.1:30001 是集群中一台节点的地址。你可以通过使用例如该网址 http://qiita.com/uryyyyyyy/items/fc767f7f41144e5f10a1 上的 create-cluster 脚本来轻松启动集群。
在上述的代码中,我们将值设置到名为”hoge”的键上,并从名为”fuga”的有序集合中获取所有元素和分数。当将这些命令发送到单个实例的Redis中时,它通常会处理命令并返回响应。但是,在Redis Cluster的情况下,由于每个键由不同的Redis实例(节点)负责处理,所以需要确定要发送命令的节点。如果向错误的节点发送命令,则会收到正确节点的重定向指示(MOVED响应)。此外,在节点添加过程中进行重新分配等操作时,可能需要在源节点和目标节点上查询来找到某个键。
所以,Renoir 是这些的
-
- キー (正確にはキースロット) とノードの割当情報の管理
-
- リダイレクトのハンドリング
- 移行中のキーのハンドリング
这意味着请你好好帮我办理。
Redis gem 与 Redis 的兼容性
我个人在使用Ruby时经常使用redis gem来使用Redis,并且希望能够以相同的方式来使用。因此,Renoir::Client的设计方针是提供与::Redis “尽可能”兼容的接口。此外,我们还将::Redis实例用作内部连接。因此,您也可以像redis一样使用hiredis作为驱动程序。我认为redis gem相当受欢迎,因此几乎没有学习成本可供使用。
顺便说一下,这个方面是由适配器 (Renoir::ConnectionAdapters::系列) 来处理的,所以我们还可以提供适用于 redic 的适配器 (可能会在将来实现)。
请注意,Redis 的所有方法并不都可以以相同的方式使用。换句话说,如果无法从命令的键中确定节点,则命令的目标节点就是不确定的,因此 Renoir::Client 会返回错误。例如,
MSET, MGET などで複数キーを指定して、それらのキースロットが異なる場合
全部同一キースロットなら OK なので、キーハッシュタグ を使って下さい
KEYS, INFO などそもそもキーがないコマンド
ただし、KEYS に関してはパターンにキーハッシュタグが明示的に含まれてたら良しとするかもしれないです
后一种情况下,可以使用Renoir::Client#each_node返回所有节点的::Redis实例来替代。
当真要使用的时候 de
考虑到在测试gem时遇到的一些异常情况,写代码的方式可能如下所示。
rc = Renoir::Client.new(cluster_nodes: ['127.0.0.1:30001'])
begin
rc.set('hoge', 123, nx: true)
rescue Redis::CannotConnectError
# そもそもノードに繋がらないケース。そのうち直るかもしれないのでリトライしてみるといいかも
rescue Redis::ConnectionError, Redis::TimeoutError
# 繋がったんだけど途中で切れたケース。コマンドが既に届いてる可能性があるからリトライしない方がいいかも
rescue Redis::CommandError => e
if /CLUSTERDOWN/.match(e.message)
# failover 中などクラスタの状態が不完全な時に返ってくる。そのうち直るはずなのでリトライすると良さげ
end
raise
rescue Renoir::RedirectionError
# ノード間のクラスタ情報の差異が大きいと起こる可能性があるけど低確率だと思う
# クラスタに存在しなかったキーのスロットが移行中で起きる(たぶん)ケースが多いはず
# 数回リトライしてもいいかも
end
概括
这是一个介绍可以像使用redis gem一样使用Redis Cluster的gem。如果您想了解更多信息,请查看文档http://www.rubydoc.info/gems/renoir。
顺便提一下,这段代码是基于 Redis 的作者 antirez 的参考实现 https://github.com/antirez/redis-rb-cluster 进行整理并集成到 gem 中的。