• twemproxy(nutcraker) 对lua 中的key的路由策略


    线上的hash策略配置为 fnv1a_64

    路由策略简述:对key hash取值后,比上主分片数量取余,即model=key_hash%master_sharding_nums,

    model数值就是既要路由到的主分片的下标

    对于lua脚本中key,是按脚本的第一个参数作为key来路由的,所以如果第一个参数一直不变,则通过lua创建的key都会被路由

    到同一个分片中

    lua 测试脚本

    脚本中的key1是hash类型,key2是string类型,测试key2通过lua和不通过lua路由到的分片是否相同

    if redis.call("hsetnx", KEYS[1], ARGV[1], 1) == 0 then
      local h1= redis.call("hget", KEYS[1], ARGV[1])
    else
      local h2="hset ok"
    end
    if redis.call("setnx", KEYS[2], ARGV[2]) == 0 then
      local s1= redis.call("get", KEYS[2])
      return s1
    else
      local s2="set ok"
      return s2
    end

    方法1 load

    脚本是通过load进行路由的,所以想要成功调用lua脚本,有两种方法

    • 每个redis分片都load一遍脚本
    • lua脚本的第一个参数为load

    以下是测试命令

    $  redis-cli -p 9999

    > SCRIPT load 'if redis.call("hsetnx", KEYS[1], ARGV[1], 1) == 0 then local h1= redis.call("hget", KEYS[1], ARGV[1]);else local h2="hset ok";end;if redis.call("setnx", KEYS[2], ARGV[2]) == 0 then local s1= redis.call("get", KEYS[2]);return s1;end;if redis.call("setnx", KEYS[2], ARGV[2]) == 0 then local s1= redis.call("get", KEYS[2]);return s1;else local s2="set ok";return s2;end'
    "08edfd298870dc70d4a407d9fe50820b5c95b06a"

    > EVALSHA 08edfd298870dc70d4a407d9fe50820b5c95b06a 2 load "sk1" , "hv1" "sv1"
    "hv1"

    # 若第一个参数不为load,则找不到脚本
    > EVALSHA 08edfd298870dc70d4a407d9fe50820b5c95b06a 2 load1 "sk1" , "hv1" "sv1"
    (error) NOSCRIPT No matching script. Please use EVAL.

    方法2 命令行调用eval

    $ redis-cli  -p 9999 --eval test.lua hlist s1 , "k1" "bb"
    "set ok"
    $ redis-cli -p 9999 --eval test.lua hlist s1 , "k1" "bb"
    "bb"

    第二个key(k1)随第一个key(hlist)都被路由到了7号分片

    $ for i in {7004..7007};do echo "/redis_${i}/data/appendonly_${i}.aof";tail -n 1000 /redis_${i}/data/appendonly_${i}.aof|grep -C 30 s1;done/redis_7004/data/appendonly_7004.aof
    /redis_7005/data/appendonly_7005.aof
    /redis_7006/data/appendonly_7006.aof
    /redis_7007/data/appendonly_7007.aof
    ...匹配到了日志

    证明lua是根据第一个key路由的

    $ redis-cli -p 9999 hkeys hlist
    1) "k1"
    $ redis-cli  -p 9999 get s1
    (nil)
    # 直接生成s1
    $redis-cli  -p 9999 setnx s1 testbcc
    (integer) 1
    $ redis-cli  -p 9999 get s1
    "testbcc"
    # 写入了5号分片
    $ for i in {7004..7007};do echo "/redis_${i}/data/appendonly_${i}.aof";tail -n 10000 /redis_${i}/data/appendonly_${i}.aof|grep -C 30 testbcc;done
    
    *3
    $5
    setnx
    $2
    s1
    $7
    testbcc

    aof中记录的日志

    • 只记录调用lua的命令,不记录lua脚本中的操作指令
    • 如果没有走到lua脚本中写数据的分支则不会打印aof日志
    • 第一个参数(2)为key的个数,是默认会生成的,无需在命令行中指定,如果在命令行传入2则会导致2成为第一个key
    *7
    $4
    EVAL
    $260
    if redis.call("hsetnx", KEYS[1], ARGV[1], 1) == 0 then
      local h1= redis.call("hget", KEYS[1], ARGV[1])
    else
      local h2="hset ok"
    end
    if redis.call("setnx", KEYS[2], ARGV[2]) == 0 then
      local s1= redis.call("get", KEYS[2])
      return s1
    else
      local s2="set ok"
      return s2
    end
    $1
    2
    $5
    hlist
    $2
    s1
    $2
    k1
    $2
    bb
  • 相关阅读:
    NXOpen 创建方体block代码
    Mysql---2 DDL DML DQL DCL
    Mysql数据库--1数据库操作
    FFmpeg
    Servlet Web
    Java web Springboot
    Java 网络
    Java 注解 反射
    Java 线程状态
    Java Lambda
  • 原文地址:https://www.cnblogs.com/Bccd/p/12786203.html
Copyright © 2020-2023  润新知