一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
使用lua脚本实现redis原子性的理论基础
前文
按照我们已知的特性,在redis中的许多操作不具备原子性。而在高并发系统中,对于redis数据的操作又会有原子性的要求。因此,也就引出了本文通过lua脚本来保证redis操作原子性的方式。
lua如何保证原子性
lua是一种轻量的脚本化语言,广泛的被独立应用于各系统外。目前在游戏引擎方面、服务方面等诸多方面均有广泛的应用。而谈到lua进行原子性保证,则主要通过redis服务对于lua脚本的支持实现。redis众所周知是一种单线程的内存数据库,而由于它对于lua脚本的支持,可以保证在执行过程中脚本内的操作不会被打断,也就实现了lua操作redis的原子性需求,保证一个处理中不会进行其他处理的操作。
并发系统对于原子性操作需求的原理
下面再来看一下为什么并发系统中存在对于redis原子性。首先我们现在假设一个场景,多人现在正在进行抢购,库存数目暂时为100,库存余额暂时被保存在redis数据中。由于并发系统的特性,此时同时有两个请求到达服务中,我们称之为请求1和请求2。请求1先到redis中进行库存查询,得知目前库存剩余了量为1,也就进行了下单处理,并进行了redis数据的更新,更新为0。同时到达的请求2首先也需要进行库存查询,由于在请求2查询redis数据时,请求1的数据尚未写入redis中,因此请求2查到的结果同样为库存是1,可下单扣减库存为0。聪明的读者应该已经发现,由于并发请求操作redis时未保证原子性,可能导致同一份数据被反复处理两次,造成数据异常。简单了解一下该请求发生的流程:
请求1查询redis得到1->请求2查询redis得到1->请求1更新redis为0->请求2更新redis为0
通过原子性的操作能使得请求1与请求2对于redis的操作集中化,也就可以避免上述问题。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。