最佳实践有点大了,其实就是几个使用建议。
背景知识
redis 的单条命令可保证原子性,但多条命令无法保证。
甚至分布式场景下, mget 这种会被分拆的命令也无法保证原子性。
而如何保证多条命令的原子性呢?此时可以使用 lua。
典型使用场景有rate limit等。
使用建议
先说结论,后续详细解释:
- 正确的使用方法
- lua 脚本维护在代码中
- 找个测试服务器,
SCRIPT LOAD
此lua脚本,拿到sha值 - 执行脚本时,先
EVALSHA
,如果报找不到脚本错误,再执行EVAL
+lua脚本内容(可以提前预热) - 随着所有节点都执行过
EVAL
,之后只需要执行EVALSHA
就可以
- lua 脚本尽量简单,负责可能会影响其它请求
- 参数一定要通过
KEYS
和ARGV
传入,而且一定要区分二者区别 - 不要在代码里面动态修改lua脚本,那样每次请求都是一个新的lua脚本,消耗大量内存
基本命令
redis 下 lua 脚本相关的命令有:
- EVAL:执行lua脚本,需要原始lua脚本作为输入
- EVALSHA:使用sha值执行lua脚本,sha值需要通过
SCRIPT LOAD
获得 - SCRIPT DEBUG:调试
- SCRIPT EXISTS:通过sha值检查脚本是否存在
- SCRIPT FLUSH:情况lua脚本,可同步、异步执行
- SCRIPT KILL:杀死lua脚本
- SCRIPT LOAD:加载lua脚本,这是目前获取sha值得唯一手段
需要注意的几点:
redis命令相关
无法直接拿到sha值
sha值生成算法相同
redis 的单线程机制
lua脚本的正确使用方式
提前拿到sha值
为什么不提前load
KEYS 和 ARGV
lua 脚本不要过大
不要动态生成lua脚本
其它
分布式场景
codis:使用第一个key路由,因此可用hash tag。旧版本迁移bug。而且会导致不均衡。
redis-cluster:会进行校验,必须在一个hash slot内。否则会报错。
exec/multi
只适用于单机