写在前面的话
本文不是对redis-lua运行环境的优化,而是针对日常开发过程中,具体的业务而进行的优化。
redis lua 脚本优化场景
- 优点:redis-lua 是对redis 指令的扩充,同时保证脚本执行的原子性。
- 缺点:在集群环境下需要hashtag的方式,将访问的数据放在同一个节点上,
至于hashtag的设置简单来说就是在原始key上使用{}
结合一个具体的案例,我们来分析下:
案例
首先
,将业务抽象,要保存一棵目录树到redis,比如说人员组织架构(我们不是搞用户中心的),
一种做法是将数据打平,放到redis中 eg:
XX集团/YY分公司/ZZ子公司,一种是使用hash结构 eg:XX集团:{YY分公司:ZZ子公司}
其次
,我们现在要获取每个层级的所有子节点,表面上看使用hash结构更加快捷,但如果在集群环境下
,这个结构就保存到了一个实例上了,必然会引起
hotkey和bigkey 问题。反观使用打平的方式,因为数据分散到多个节点上,性能反而会提高很多。
接着
,今天主要跟大家聊下lua来查询子节点的方案,我们的要求是如何能随便拿出来某一层,当然我们最后选择使用hash结构存储(历史原因吧,客户端每次发送的请求都是某一层级的值,而不是完整路径,所以用模糊匹配查找起来难度较大)
那lua查询获得所有子节点的脚本如下:
1 | local treeKey = KEYS[1] |
以上代码出自 https://my.oschina.net/u/1469495/blog/1504818#comments
做了些调整,但是性能存在问题,未在生产上使用。
但是
,我们发现业务中查询节点是一个高频的操作,追踪代码发现一个for循环4万次调用,里面又有4次hget操作,合下来就是16w,于是又开始尝试使用lua,将这4次hget合并,当然有同学会问
为什么不使用mget,或者pipeline,因为我们for 循环里的get操作还有业务逻辑,key之间有依赖关系,需要拿到上一个key对应的value,做截取然后在加工,作为下一次的key,所以单纯使用mget解决不了我们的问题
尝试过后,性能提升了好几倍
调试
redis-lua 的调试,推荐使用参数 --ldb-sync-mode
因为该参数,再调试的过程不会被打断,直接使用 –ldb 会被打断
,或者hang住到那,这都不是我们期待的,所以条件允许,请使用 --ldb-sync-mode
参数
调试过程中,常用命令如下:
- n(ext) 单步下一步
- b(reakpoint) 设置断点 b 13
- p(rint) 打印当前context的所有变量