Redis整合Lua
Redis的消息模式
Redis实现分布式锁
常见的缓存问题
减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行。
原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件。
复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑。
Redis整合Lua脚本
通过执行redis的eval命令,可以运行一段lua脚本。EVAL script numkeys key [key ...] arg [arg ...]
命令的具体说明如下:script参数:是一段Lua脚本程序,它会被运行在Redis服务器上下文中,这段脚本不必(也不应该)定义为一个Lua函数。
numkeys参数:用于指定键名参数的个数。
key [key ...]参数:从EVAL的第三个参数开始算起,使用了numkeys个键(key),表示在脚本中所用到的那些Redis键(key),这些键名参数可以在Lua中通过全局变量KEYS数组,用1为基址的形 式访问( KEYS[1], KEYS[2],以此类推)。
arg [arg ...]参数:可以在Lua中通过全局变量ARGV数组访问,访问的形式和KEYS变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
eval "return {KEYS[1], KEYS[2], ARGV[1],ARGV[2]} 2 key1 key2 first second"
Lua脚本中调用Redis命令
我们可以在Lua脚本中调用Redis命令:redis.call()
redis.pcall()
eval "return redis.call('set', KEYS[1], ARGV[1])" 1 n1 eleven
SCRIPT命令
另外一方面在Redis中有一些管理Lua脚本的命令:SCRIPT FLUSH:清除所有脚本缓存
SCRIPT EXISTS:根据给定的脚本校验和,检查指定的脚本是否存在于脚本缓存
SCRIPT LOAD:将一个脚本装入脚本缓存,返回SHA1摘要,但并不立即运行它
SCRIPT KILL:杀死当前正在运行的脚本
192.168.24.131:6380> script load "return redis.call('set',KEYS[1],ARGV[1])""c686f316aaf1eb01d5a4de1b0b63cd233010e63d"192.168.24.131:6380> evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 n2elevenOK192.168.24.131:6380> get n2
EVALSHA
EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。Redis 有一个内部的缓存机制,因此它不会每次都重新编译脚本,不过在很多场合,付出无谓的带宽来传送脚本主体并不是最佳选择。为了减少带宽的消耗, Redis 实现了 EVALSHA 命令,它的作用和 EVAL 一样,都用于对脚本求值,但它接受的第一个参数不是脚本,而是脚本的 SHA1 校验和(sum)。下面我们举两个使用Lua脚本的例子:return redis.call('set', KEYS[1], ARGV[1])
上面是一个set脚本,在redis中我们可以这样使用:redis-cli -h 192.168.24.131 -p 6380 --eval test.lua n3, 'eleven'
总结一下利用Redis整合Lua,主要是为了性能以及事务的原子性。因为redis帮我们提供的事务功能太差。