redis-cluster-client 0.4.17 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac7d6ca1474a42ad2d4027de72dbd087f6d248b3678ad2e360ed55b56dc60790
|
4
|
+
data.tar.gz: ce4de83f3f601772df8c95381a65172245967bd9568ff7959aec5858e55fb7af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cb2167fb97c6ab7ccba66e888521a1a119e2f17a0c373829bce0abb41518ead4005c0a7c176373c45942e9cd9fca71355b9898e7cc2b67db22d6291a76b324e
|
7
|
+
data.tar.gz: 1da6192fcb6f33359b508ff4e3445ec029373ff9606f78170051a682a29371524d6f08864f4a0887b3cbc298e462d13fe8cc9080eb29bd9cf8d965c7a766409e
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'redis_client/cluster/node/replica_mixin'
|
4
|
+
|
5
|
+
class RedisClient
|
6
|
+
class Cluster
|
7
|
+
class Node
|
8
|
+
class RandomReplicaOrPrimary
|
9
|
+
include ::RedisClient::Cluster::Node::ReplicaMixin
|
10
|
+
|
11
|
+
def replica_clients
|
12
|
+
keys = @replications.values.filter_map(&:sample)
|
13
|
+
@clients.select { |k, _| keys.include?(k) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def clients_for_scanning(seed: nil)
|
17
|
+
random = seed.nil? ? Random : Random.new(seed)
|
18
|
+
keys = @replications.map do |primary_node_key, replica_node_keys|
|
19
|
+
decide_use_primary?(random, replica_node_keys.size) ? primary_node_key : replica_node_keys.sample(random: random)
|
20
|
+
end
|
21
|
+
|
22
|
+
clients.select { |k, _| keys.include?(k) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_node_key_of_replica(primary_node_key, seed: nil)
|
26
|
+
random = seed.nil? ? Random : Random.new(seed)
|
27
|
+
|
28
|
+
replica_node_keys = @replications.fetch(primary_node_key, EMPTY_ARRAY)
|
29
|
+
if decide_use_primary?(random, replica_node_keys.size)
|
30
|
+
primary_node_key
|
31
|
+
else
|
32
|
+
replica_node_keys.sample(random: random) || primary_node_key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def any_replica_node_key(seed: nil)
|
37
|
+
random = seed.nil? ? Random : Random.new(seed)
|
38
|
+
@replica_node_keys.sample(random: random) || any_primary_node_key(seed: seed)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Randomly equally likely choose node to read between primary and all replicas
|
44
|
+
# e.g. 1 primary + 1 replica = 50% probability to read from primary
|
45
|
+
# e.g. 1 primary + 2 replica = 33% probability to read from primary
|
46
|
+
# e.g. 1 primary + 0 replica = 100% probability to read from primary
|
47
|
+
def decide_use_primary?(random, replica_nodes)
|
48
|
+
primary_nodes = 1.0
|
49
|
+
total = primary_nodes + replica_nodes
|
50
|
+
random.rand < primary_nodes / total
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -5,6 +5,7 @@ require 'redis_client/config'
|
|
5
5
|
require 'redis_client/cluster/errors'
|
6
6
|
require 'redis_client/cluster/node/primary_only'
|
7
7
|
require 'redis_client/cluster/node/random_replica'
|
8
|
+
require 'redis_client/cluster/node/random_replica_or_primary'
|
8
9
|
require 'redis_client/cluster/node/latency_replica'
|
9
10
|
|
10
11
|
class RedisClient
|
@@ -284,6 +285,8 @@ class RedisClient
|
|
284
285
|
def make_topology_class(with_replica, replica_affinity)
|
285
286
|
if with_replica && replica_affinity == :random
|
286
287
|
::RedisClient::Cluster::Node::RandomReplica
|
288
|
+
elsif with_replica && replica_affinity == :random_with_primary
|
289
|
+
::RedisClient::Cluster::Node::RandomReplicaOrPrimary
|
287
290
|
elsif with_replica && replica_affinity == :latency
|
288
291
|
::RedisClient::Cluster::Node::LatencyReplica
|
289
292
|
else
|
@@ -149,7 +149,7 @@ class RedisClient
|
|
149
149
|
all_replies = errors = nil
|
150
150
|
@pipelines&.each_slice(MAX_THREADS) do |chuncked_pipelines|
|
151
151
|
chuncked_pipelines
|
152
|
-
.map { |node_key, pipeline| [node_key, build_thread_for_pipeline(@router
|
152
|
+
.map { |node_key, pipeline| [node_key, build_thread_for_pipeline(@router.find_node(node_key), pipeline)] }
|
153
153
|
.each do |node_key, thread|
|
154
154
|
case v = thread.value
|
155
155
|
when ::RedisClient::Cluster::Pipeline::RedirectionNeeded
|
@@ -182,9 +182,9 @@ class RedisClient
|
|
182
182
|
@pipelines[node_key]
|
183
183
|
end
|
184
184
|
|
185
|
-
def build_thread_for_pipeline(
|
186
|
-
Thread.new(
|
187
|
-
replies = do_pipelining(
|
185
|
+
def build_thread_for_pipeline(client, pipeline)
|
186
|
+
Thread.new(client, pipeline) do |cli, pl|
|
187
|
+
replies = do_pipelining(cli, pl)
|
188
188
|
raise ReplySizeError, "commands: #{pl._size}, replies: #{replies.size}" if pl._size != replies.size
|
189
189
|
|
190
190
|
replies
|
@@ -6,44 +6,44 @@ class RedisClient
|
|
6
6
|
class Cluster
|
7
7
|
class PubSub
|
8
8
|
class State
|
9
|
-
def initialize(client)
|
9
|
+
def initialize(client, queue)
|
10
10
|
@client = client
|
11
11
|
@worker = nil
|
12
|
+
@queue = queue
|
12
13
|
end
|
13
14
|
|
14
15
|
def call(command)
|
15
16
|
@client.call_v(command)
|
16
17
|
end
|
17
18
|
|
19
|
+
def ensure_worker
|
20
|
+
@worker = spawn_worker(@client, @queue) unless @worker&.alive?
|
21
|
+
end
|
22
|
+
|
18
23
|
def close
|
19
24
|
@worker.exit if @worker&.alive?
|
20
25
|
@client.close
|
21
26
|
end
|
22
27
|
|
23
|
-
def take_message(timeout)
|
24
|
-
@worker = subscribe(@client, timeout) if @worker.nil?
|
25
|
-
return if @worker.alive?
|
26
|
-
|
27
|
-
message = @worker.value
|
28
|
-
@worker = nil
|
29
|
-
message
|
30
|
-
end
|
31
|
-
|
32
28
|
private
|
33
29
|
|
34
|
-
def
|
35
|
-
Thread.new(client,
|
36
|
-
|
37
|
-
|
38
|
-
e
|
30
|
+
def spawn_worker(client, queue)
|
31
|
+
Thread.new(client, queue) do |pubsub, q|
|
32
|
+
loop do
|
33
|
+
q << pubsub.next_event
|
34
|
+
rescue StandardError => e
|
35
|
+
q << e
|
36
|
+
end
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
41
|
+
BUF_SIZE = Integer(ENV.fetch('REDIS_CLIENT_PUBSUB_BUF_SIZE', 1024))
|
42
|
+
|
43
43
|
def initialize(router, command_builder)
|
44
44
|
@router = router
|
45
45
|
@command_builder = command_builder
|
46
|
-
@
|
46
|
+
@queue = SizedQueue.new(BUF_SIZE)
|
47
47
|
@state_dict = {}
|
48
48
|
end
|
49
49
|
|
@@ -56,26 +56,25 @@ class RedisClient
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def close
|
59
|
-
@
|
60
|
-
@state_list.clear
|
59
|
+
@state_dict.each_value(&:close)
|
61
60
|
@state_dict.clear
|
61
|
+
@queue.clear
|
62
62
|
end
|
63
63
|
|
64
64
|
def next_event(timeout = nil)
|
65
|
-
|
66
|
-
|
67
|
-
@state_list.shuffle!
|
65
|
+
@state_dict.each_value(&:ensure_worker)
|
68
66
|
max_duration = calc_max_duration(timeout)
|
69
67
|
starting = obtain_current_time
|
68
|
+
|
70
69
|
loop do
|
71
70
|
break if max_duration > 0 && obtain_current_time - starting > max_duration
|
72
71
|
|
73
|
-
@
|
74
|
-
|
75
|
-
|
72
|
+
case event = @queue.pop(true)
|
73
|
+
when StandardError then raise event
|
74
|
+
when Array then break event
|
76
75
|
end
|
77
|
-
|
78
|
-
sleep 0.
|
76
|
+
rescue ThreadError
|
77
|
+
sleep 0.005
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
@@ -100,8 +99,7 @@ class RedisClient
|
|
100
99
|
def add_state(node_key)
|
101
100
|
return @state_dict[node_key] if @state_dict.key?(node_key)
|
102
101
|
|
103
|
-
state = State.new(@router.find_node(node_key).pubsub)
|
104
|
-
@state_list << state
|
102
|
+
state = State.new(@router.find_node(node_key).pubsub, @queue)
|
105
103
|
@state_dict[node_key] = state
|
106
104
|
end
|
107
105
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-cluster-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taishi Kasuga
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- lib/redis_client/cluster/node/latency_replica.rb
|
41
41
|
- lib/redis_client/cluster/node/primary_only.rb
|
42
42
|
- lib/redis_client/cluster/node/random_replica.rb
|
43
|
+
- lib/redis_client/cluster/node/random_replica_or_primary.rb
|
43
44
|
- lib/redis_client/cluster/node/replica_mixin.rb
|
44
45
|
- lib/redis_client/cluster/node_key.rb
|
45
46
|
- lib/redis_client/cluster/normalized_cmd_name.rb
|