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