PHP使用Redis+Lua脚本操作的注意事项

以前只是简单的用下 Reids 存点数据而已,最近尝试优化性能,做了些测试才发现很多以前完全忽略的问题,总结在下面:

一、Redis的一般新手注意事项:

  1. 连接本地Reids时,host 要填写 127.0.0.1 而不要用 localhost
  2. 最好设置密码,配置文件中,找到 requirepass 参数,设置一个复杂点的密码
$redis = new Redis();
$redis->pconnect('127.0.0.1');
// 验证设置的密码
$redis->auth('Gfafs9g0SjgvbfbhjfklgfZbPah5a6dg');
$redis->select(2);

二、Redis 中使用 Lua 脚本时注意:

  1. Redis 会把所有执行过的脚本都缓存在内存中
  2. Redis 在重启的时候会释放掉之前保存的脚本
  3. Lua 脚本中所需要用到的键名以及参数一定要使用 KEYS 和 ARGV 来替换,千万不要写死在代码中,除非你百分百确定每次请求时他们是固定不变的值,特别是涉及到 时间,随机数的,一定要用参数代入,因为 Redis 每次使用 script 都会校验脚本缓存中是否已存在相同脚本,否则就会存储到缓存中,如果你的脚本很长,且每次请求存在不同的变量值,则会生成无数多个脚本缓存,你将会发现Redis占用的内存会唰唰唰的往上涨,我一开始因为key 和 参数太多,分开写太麻烦了,就图省事方便,直接把变量拼接到脚本里面,结果发现内存不停的涨,很是抓狂,找了好久才发现是这么个原因。
  4. Lua 脚本中的变量一定是本地变量,即变量前面加上 local 前缀:local var = 1;
  5. 如果Lua脚本写的比较长,非本地或局域网的情况下,建议使用 SHA 签名的方法来调用,这样节省带宽,但对性能似乎没什么直接的提升。这里对小白普及下我理解的原理就是 Redis 会把每个脚本都生成唯一签名,把脚本作为函数体,并使用该签名作为脚本的函数名放到缓存中,所以后面调用就只需要传一个 SHA 签名就可以调用该函数了,精简很多了。同一个脚本生成的签名都是相同的,所以SHA签名可以先在本地生成,然后在服务器上 script load 一次脚本,程序中只需保存和使用该签名即可。另外需要注意的是,脚本如果被改动哪怕一个换行或一个空格(这些容易被忽略或误操作)都必须重新 load 来获取新的 SHA 哦
  6. 通过 eval 带入的 ARGV 参数如果原来是数字的,会被转换为字符串,如果你的逻辑中需要判断该变量 > 0 或 < 0 之类的数字判断则必须进行字符串到数字的转换,使用 tonumber() 方法 if (tonumber(ARGV[1]) > 0) then return 1; end;
  7. 我测试了几个 lua script 与 PIPELINE 处理对比,发现 script 的效率一般比 PIPELINE 高 30% ~ 40% 左右

Reids 的 LUA 脚本中的键、参数要使用 KEYS/ARGV 来带入,不要直接拼接在代码中,除非是绝对不变的可以写死在代码中(但对于键名应该始终使用 KEYS 来操作)。
PHP使用Redis+Lua脚本操作的注意事项_第1张图片
查看大图


PHP 中使用脚本的 SHA 签名来操作示例(配合上图的 $script 脚本)

PHP使用Redis+Lua脚本操作的注意事项_第2张图片
查看大图

注意:获取 SHA 签名是单独的功能,不要放在你的正常流程中,当本地开发时就可以生成SHA,把字符串写死在流程中。同样的脚本,Reids是始终生成相同的签名的。


PHP使用 PIPELINE 的示例

PHP使用Redis+Lua脚本操作的注意事项_第3张图片


一些参考网址:
http://www.redis.cn/commands/eval.html

先写到这里,以后再慢慢补充啦~

你可能感兴趣的:(php,redis)