redis 与 lua 的结合

一、前言:

redis 为我们提供了很多的命令,但是很多时候我们需要组合这些命令,但是有设计到一个问题:命令组合起来之后,在高并发的情况下,怎么保证原子性呢?此时lua为我们提供了解决的方案。lua 还是比较好入门的,但是我今天在玩这个玩意儿的时候还是遇到了很多问题,因为分享出来希望大家不会遇到这个问题。

二、还是言明环境:

  • redis 3.2.100 for windows
    因为最近 windows10 for docker 的网络没有整明白不得已在windows安装了redis,这种东西最好是在linux下面玩

三、lua 与 reids 的简单入门:

这里只是做一个简单的介绍,因为在这里详细的介绍一门语言不现实,还是以使用为主,

3.1 实现一个简单的需求:

  • 获取以天为自增的唯一序列
    • 这个里面首先需要自增,肯定是要使用到 incr 这个命令的
    • 其实需要以天为单位,说明这个序列是需要有过期时间的
    • 需要批量的生成,因为是进行批量的请求,但是总不能每一条记录都请求一次这个太不划算,io交互太多
      ps:在新版的 RedisTemplate 里面提供了这个方法,自增的同时是可以设置过期时间的,但是项目中配置的是 jedis,所以很无奈的只能自己造。这个通过事务也能实现,但是没有必要,lua可以是一个更好的选择

3.2 lua 的简单入门:

  • 接受外面传入的参数key
    local key = KYES[1]
    local 表明这个是局部变量,建议能用局部变量就用局部变量
  • 接受值,例如过期时间或者key对应的值
    local tll = ARGV[1]
  • 在 lua 中的一些结构,对于if for 这样的语句块需要使用 end 来作为结尾,例如:
if    true then
  todo
end
for i=0,len do
  todo
end
  • lua 中的注释是以 — 来标示的
  • lua 中的调用redis 命令:redis.call(‘commond’,key,val……)
  • lua 中字符串拼接使用 .. 即可拼接

3.3 开始实战:

新建文件以 .lua 结尾

-- 接受key
local key = KEYS[1]
-- 接受过期时间
local ttl = ARGV[1]
-- 需要生成的个数
local len = ARGV[2] 
-- 定义一个接受的数组,来接受批量生成的序列号
local codeArr = {}
-- 判断,如果key不存在,则先初始化key,且设置过期时间
if redis.call('EXISTS',key) == 0 then 
-- 插入一条记录
    redis.call('SET',key,0)
-- 设置过期时间
    redis.call('EXPIRE',key,ttl)
end
for i = 0 , len do
-- 循环产生序列号,并放置到数组当中,
    codeArr[i] = redis.call('INCR',key)
end 
-- 返回给客户端
return codeArr  

3.4 redis 客户端调用 lua 脚本

ps:注意下面演示的是在 windows 的环境下

  • 进入到 redis 的安装的bin目录
  • 在cmd命令窗口中执行下列命令:
redis-cli.exe --eval ExistAndIncre.lua RESERVE_CODE , 100000 10

需要注意的是:

  • 我们不能进入到redis的客户端里面去了,要在外面的环境中执行,否则会报错
  • –eval lua文件位置 后面的第一个参数不需要知名有多少个key,否则这个就会作为 KEYS[1] 的值,目前不知道原因,测试出来的是这样的结果,这个和大多博客上的描述的不一样,切记

    《redis 与 lua 的结合》 image.png
    《redis 与 lua 的结合》 image.png

  • 中间的 ‘,’ 注意前后都有一个空格,同时后面多个值的时候使用空格隔开即可

四、lua 的好处:

lua 主要是类似于批处理的功能,把众多的命令组合起来进行执行,但是这些在 lua 脚本中组合的命令是原子的,在高并发的情况下很多时候判断和执行如果不是原子的话,由于先后顺序的原因很有可能发生数据不一致的情况,所以我们要避免在判断和执行之间不能有时间窗口,lua就是为了解决这个问题的

很多复杂的场景中,需要组合众多的 redis 的命令的时候就可以考虑 lua ,在 redisson 的框架中的实现也是大量的采用了lua脚本的

由于工作需要来学习的,所以不是很深入,以后有机会再使用到在慢慢的补。

博客首发地址csdn:https://blog.csdn.net/weixin_42849915
简书地址:https://www.jianshu.com/u/4b48be4cf59f
希望结识更多的乐于分享的伙伴一起前行

    原文作者:fkxuexi
    原文地址: https://www.jianshu.com/p/ca859b9c7e5f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞