一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
java项目利用lua脚本实现redis操作原子性
前文
前文曾通过对于理论基础的叙述,对于redis操作原子性尤其在分布式高并发系统中的必要性进行过阐述。本文则主要结合一个实际需求,根据需求对于具体的操作进行实现。
实现方案
现在首先有这样的一个场景,我们在系统中预置了100个可处理单号,而此时有并发10000个客户端同时抢购。要求做到有且只有100人能够抢购到具体的单号。对于这个操作该怎么处理呢?这里便采用了lua脚本进行redis操作原子性束缚。通过lua脚本操作redis代替实际的redis。首先我们把需要操作的redis的键值,在java程序中传递给目标的lua脚本,以此在脚本中能够直接对于该键进行处理。每个请求到来后,在lua脚本中进行扣减1的操作,为了方便查看处理结果,我们同时将处理成功的数据存储到另一个redis键值之中。随后,为了模拟该并发请求,使用jmeter进行压测。在其中设置了10000个并发线程,每个线程同时对我们的测试接口进行访问。在执行结束后,到redis中查看实际剩余的数量以及成功操作的数量。
操作代码
--- 基础key值,用于标注剩余可获取数量
local key = KEYS[1]
--- 获取key2值,用于处理当前已操作的数量
local key2 = KEYS[2]
--- 获取一个参数 == 并不需要的参数
local val = ARGV[1]
--- 获取key值,如果找不到则
if redis.call("exists", key) == 1 then
--- 如果插入成功,就去设置过期值
if tonumber(redis.call("get", key)) > 0 then
redis.call("set",key,tonumber(redis.call("get", key)) - 1)
--- 处理当前操作的数目记录
if redis.call("exists", key2) == 0 then
redis.call("set",key2,1)
else
redis.call("set",key2,tonumber(redis.call("get", key2)) + 1)
end
return true
else
return false
end
return true
else
return false
end
操作结果
经过上述方案的处理,可以看到最终的结果剩余订单数量为0,而记录的已操作数量为100,也就达到了目标的有且仅有100条订单信息可用。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。