-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Refactor and enhance Redis::Distributed #817
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
end | ||
end | ||
|
||
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
end | ||
|
||
def test_migrate | ||
r.set("foo", "s1") | ||
|
||
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.
@@ -6,6 +6,14 @@ class TestDistributedCommandsOnValueTypes < Test::Unit::TestCase | |||
include Helper::Distributed | |||
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.
@@ -27,7 +27,7 @@ def test_info | |||
|
|||
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::Distributed
give 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
Redis
andRedis::Distributed
as public interfaces. So I refactored theRedis::Distributed
along 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#ring
has been removed.Redis::HashRing#sorted_keys
has been removed.Redis::HashRing#replicas
has been removed.Redis::Distributed#on_each_node
has been removed in protected scope.Redis::Distributed#node_index_for
has been removed in protected scope.Redis::Distributed#key_tag
has been removed in protected scope.Redis::Distributed#ensure_same_node
has been removed in protected scope.Redis::Distributed#select
has been become raisingRedis::Distributed::CannotDistribute
error.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.NotImplementedError
intoRedis::Distributed::CannotDistribute
whenRedis::Distributed#monitor
is called.NoMethodError
intoRedis::CommandError
when anyRedis::Distributed#not_yet_implemented_commands
are 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