-
Notifications
You must be signed in to change notification settings - Fork 1k
Refactor and enhance Redis::Distributed #817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
60cb738 to
827a999
Compare
| attr_reader :nodes | ||
|
|
||
| # Find the closest index in HashRing with value <= the given value | ||
| def self.binary_search(ary, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that this is subtly different from Array#bsearch_index.
| end | ||
|
|
||
| def db=(_db) | ||
| raise CannotDistribute, 'select' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error handling is on purpose because HashRing is broken by SELECT command. The checksum calculation depends on the client id. It includes the db number if the id option isn't specified.
0805783 to
a42ab18
Compare
| def test_brpop_raises | ||
| assert_raises(Redis::Distributed::CannotDistribute) do | ||
| r.brpop(%w[foo bar]) | ||
| target_version('3.2.0') do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
I wonder if the client side sharding feature is still used by someone. I think it is alone not high available. So it seems that it should be combined replication with Sentinel or Keepalived and so on in production environment. But now, we're able to use Redis Cluster. There might be demands as a cache store. |
cd2b24f to
fc5cac9
Compare
| rd.set('foo', '1') | ||
| assert_equal '1', rd.get('foo') | ||
|
|
||
| hr = Redis::HashRing.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used by some gems. e.g. redis-store
fc5cac9 to
0fb5ef1
Compare
|
|
||
| assert_raise Redis::Distributed::CannotDistribute do | ||
| r.migrate("foo", {}) | ||
| r.migrate('foo', host: '127.0.0.1', port: PORT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| include Lint::ValueTypes | ||
|
|
||
| def test_move | ||
| assert_raise(Redis::Distributed::CannotDistribute) { super } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is raised from SELECT.
| def test_info_commandstats | ||
| target_version "2.5.7" do | ||
| r.nodes.each { |n| n.config(:resetstat) } | ||
| r.nodes.each { |n| n.call(%i[config resetstat]) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a compatibility-breaking change. The return value's instance type is changed Redis into Redis::Client.
|
|
||
| assert_raise Redis::Distributed::CannotDistribute do | ||
| r.multi { @foo = 1 } | ||
| r.multi { :dummy } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
I realize I should have said that months ago, but I'm afraid Is there any way this could be split in more reasonable chunks ? e.g ~300 line max changes. That would make my life much much easier. |
|
Sure. Thank you for your response. I will try to split this PR. 😄 |
Hi,
Redis::Distributedgive us partitioning feature by client side consistent hashing.There are some gems which depend on the above feature. e.g. redis-store, ActiveSupport, resque
I'd say that we might be felt pain or exhausting by simultaneous maintaining both
RedisandRedis::Distributedas public interfaces. So I refactored theRedis::Distributedalong with several additional Redis API supports (e.g. Streams) and several compatibility-breaking minor changes.Before the changes
After the changes
But we leave
Redis::Distributed's old interface for backward compatibility.About several commands that can operate on multiple keys
The current implementation doesn't allow multiple keys without tag. After refactoring, the multiple keys are allowed only if they effect single node.
Compatibility-breaking changes
Redis::Distributed#[]has been removed.Redis::Distributed#[]=has been removed.Redis::HashRing#ringhas been removed.Redis::HashRing#sorted_keyshas been removed.Redis::HashRing#replicashas been removed.Redis::Distributed#on_each_nodehas been removed in protected scope.Redis::Distributed#node_index_forhas been removed in protected scope.Redis::Distributed#key_taghas been removed in protected scope.Redis::Distributed#ensure_same_nodehas been removed in protected scope.Redis::Distributed#selecthas been become raisingRedis::Distributed::CannotDistributeerror.Redis::Distributed#nodes's return value has been changedArray<Redis>intoArray<Redis::Client>.Redis::Distributed#script(:exists)'s return value has been become 1 from 2.NotImplementedErrorintoRedis::Distributed::CannotDistributewhenRedis::Distributed#monitoris called.NoMethodErrorintoRedis::CommandErrorwhen anyRedis::Distributed#not_yet_implemented_commandsare called.ref: #219
ref: rails/rails#31134
ref: redis-store/redis-store#277
ref: #687
ref: redis-store/redis-store#282
ref: #653 (comment)
ref: #716