前言
我们知道redis是单线程模型,其对所有CRUD操作命令都是串行执行,除非是RDB或者是主从同步的时候采用多线程模式,但本身其单个实例的数据操作都是单线程。redis这种特性使其设计非常简单,不必处理多并发下的问题。
lua脚本可以将多个redis操作整合到一起,利用redis的单线程模式,确保脚本执行的原子性。举个例子,假设lua脚本里有,A、B和C,3条命令,那么可以保证ABC命令的顺序执行,同时保证期间没有其他任何命令插进来。
下面我们从一个实际的业务场景出发,看看lua脚本操作时需要注意的问题。
业务场景
lua脚本在单实例redis下虽然可以正常运行,但是在分布式模式(redis-cluster模式)下则会出问题。这里举一个真实碰到的业务例子来说明。
假设某个韩剧里面正在举办一个打榜活动(对应有一个,活动ID),每个活动有个n个赛道(赛道ID),每个赛道有m个角色(角色ID)可以被投票,每个用户(用户ID)每天仅仅可以在该活动下的某个赛道下的某个角色打一分。
看到这里有经验的开发者可以很快想出直接用:INCR 用户ID_活动ID_赛道ID_角色ID , 就完事了。
但仔细想想,用户是贪婪的,他想多支持某个“爱豆”角色,想帮他冲上榜首,因此即使前端做了单日限制,依然当不了他走后门,多发了几个这样的请求,导致“爱豆”角色被野蛮增分。
防止这种情况的一种做法就是用lua脚本,下面是一个实例,其中:
# KEYS[1] = 用户ID_活动ID_赛道ID_角色ID_TODAY
# KEYS[2] = 活动ID_赛道ID_角色ID
# Step 1: