rediscluster lua使用

redis中文网官方案例

redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

这在在单个redis中是可以成功的,在rediscluster中执行情况如下

redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
(error) CROSSSLOT Keys in request don't hash to the same slot

会出现 CROSSSLOT Keys in request don’t hash to the same slot。
原因是因为:Redis cluster对多key操作有限,要求命令中所有的key都属于一个slot,才可以被执行。
想看jediscluster.eval()方法中获取getSlot()的实现

public T run(int keyCount, String... keys) {
    if (keys == null || keys.length == 0) {
      throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
    }

    // For multiple keys, only execute if they all share the
    // same connection slot.
    if (keys.length > 1) {
      int slot = JedisClusterCRC16.getSlot(keys[0]);
      for (int i = 1; i < keyCount; i++) {
        int nextSlot = JedisClusterCRC16.getSlot(keys[i]);
        if (slot != nextSlot) {
          throw new JedisClusterException("No way to dispatch this command to Redis Cluster "
              + "because keys have different slots.");
        }
      }
    }

如果solt不一样会跑出异常,看获取getSolt()实现

public static int getSlot(String key) {  
  int s = key.indexOf("{");  
  if (s > -1) {  
    int e = key.indexOf("}", s + 1);  
    if (e > -1 && e != s + 1) {  
      key = key.substring(s + 1, e);  
    }  
  }  
  // optimization with modulo operator with power of 2  
  // equivalent to getCRC16(key) % 16384  
  return getCRC16(key) & (16384 - 1);  
}

可以看出,keySlot算法中,如果key包含{},就会使用第一个{}内部的字符串作为hash key,这样就可以保证拥有同样{}内部字符串的key就会拥有相同slot。

综上所述脚本改成

redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 {key}1 {key}2 first second
1) "{key}1"
2) "{key}2"
3) "first"
4) "second"

执行成功。

lua使用:> http://www.oschina.net/translate/intro-to-lua-for-redis-programmers

没有更多推荐了,返回首页