Module: Redis::KeyHash::ClassMethods
- Defined in:
- lib/redis/key_hash.rb
Instance Method Summary collapse
-
#all_in_one_slot!(*keys, namespace: nil, styles: DEFAULT_STYLES) ⇒ Object
Like all_in_one_slot?, mismatch raises Redis::ImpendingCrossSlotError.
-
#all_in_one_slot?(*keys, namespace: nil, styles: DEFAULT_STYLES) ⇒ Boolean
Tests whether all of keys will hash to the same slot in all specified sharding styles.
-
#crc16(key) ⇒ Object
Computes the Redis crc16 for a given key, as per the reference implementation provided in redis.io/topics/cluster-spec.
-
#hash_slot(key, style: DEFAULT_STYLE) ⇒ Object
Computes the Redis hash_slot for a given key.
-
#hash_tag(key, style: DEFAULT_STYLE) ⇒ Object
Computes the hash tag for a given key under a given Redis clustering algorithm.
Instance Method Details
#all_in_one_slot!(*keys, namespace: nil, styles: DEFAULT_STYLES) ⇒ Object
Like all_in_one_slot?, mismatch raises Redis::ImpendingCrossSlotError.
all keys as per the redis-namespace gem before testing.
the styles, false if there is any doubt.
under all styles by virtue of having a single hash_tag.
keys have a different hash_tag hence will not provably have the same hash_slot
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/redis/key_hash.rb', line 98 def all_in_one_slot!(*keys, namespace: nil, styles: DEFAULT_STYLES) nkeys = namespace ? keys.map { |key| "#{namespace}:#{key}" } : keys style2slot = Hash.new problems = [] styles.each do |style| = nkeys.map { |nkey| hash_tag(nkey,style: style) }.uniq next if .size <= 1 problems << "style #{style} sees tags #{.join(',')}" end if 0 != problems.size err = "CROSSSLOT" err += " namespace=#{namespace}" err += " keys=#{keys}" err += " problems=#{problems}" raise Redis::ImpendingCrossSlotError, err end true end |
#all_in_one_slot?(*keys, namespace: nil, styles: DEFAULT_STYLES) ⇒ Boolean
Tests whether all of keys will hash to the same slot in all specified sharding styles.
all keys as per the redis-namespace gem before testing.
all styles by virtue of having a single hash_tag, false otherwise.
69 70 71 72 73 74 75 76 77 |
# File 'lib/redis/key_hash.rb', line 69 def all_in_one_slot?(*keys, namespace: nil, styles: DEFAULT_STYLES) begin all_in_one_slot!(*keys, namespace: namespace, styles: styles) rescue Redis::ImpendingCrossSlotError return false else return true end end |
#crc16(key) ⇒ Object
Computes the Redis crc16 for a given key, as per the reference implementation provided in redis.io/topics/cluster-spec.
This implementation is taken largely from that reference document, changed only slightly to port to Ruby.
compute a hash_key.
172 173 174 175 176 177 178 |
# File 'lib/redis/key_hash.rb', line 172 def crc16(key) crc = 0 key.each_char do |char| crc = ((crc << 8) & 0xFFFF) ^ CRC16TAB[((crc >> 8) ^ char.ord) & 0x00FF] end crc end |
#hash_slot(key, style: DEFAULT_STYLE) ⇒ Object
Computes the Redis hash_slot for a given key.
Uses :style as per hash_tag, but performs hashing as per RC only. We know through documentation and experimentation that RC uses crc16() and modulo 16384. We do not know what RLEC does, but until we have a better model we assume it is the same. This is probably a false assumption since the RLEC docs state that the number of shards can vary from cluster to cluster. But for many analyses, using the same hash as RC is still useful.
156 157 158 159 |
# File 'lib/redis/key_hash.rb', line 156 def hash_slot(key, style: DEFAULT_STYLE) tag = hash_tag(key, style: style) crc16(tag) % 16384 end |
#hash_tag(key, style: DEFAULT_STYLE) ⇒ Object
Computes the hash tag for a given key under a given Redis clustering algorithm.
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/redis/key_hash.rb', line 126 def hash_tag(key, style: DEFAULT_STYLE) regexp = nil if KNOWN_STYLES.has_key?(style) regexp = KNOWN_STYLES[style] # some are predefined elsif style.is_a?(Regexp) regexp = style # you can define your own end if !regexp raise ArgumentError, "bogus style #{style}" end match = regexp.match(key) return match ? match[1] : key end |