Redis的Lua脚本是如何保证原子性的

前两天正在写一个类似与抢购的功能,决定使用Redis来存储一些信息。又因为有一个刷新的周期,为了保证操作的原子性,最后觉得使用在Redis中调用Lua脚本实现。

但是在实现的过程中,总觉得如果在Lua脚本内,获取了KeyA,那么KeyA如果在脚本执行的过程中过期了怎么办?Redis有做这个保证吗?当时问了劲哥,虽然劲哥说Redis会保证这个的原子性,
但总觉得不搞清楚不安心,所以就查了查源码。

在Redis中,大部分操作都会调用expireIfNeeded(redisDb *db, robj *key)来判断键是否已经过期。然而这段代码中有如下一段:

1
2
3
4
5
6
7
8
9
10
11
12
13
// db.c
int expireIfNeeded(redisDb *db, robj *key) {
......

/* If we are in the context of a Lua script, we pretend that time is
* blocked to when the Lua script started. This way a key can expire
* only the first time it is accessed and not in the middle of the
* script execution, making propagation to slaves / AOF consistent.
* See issue #1525 on Github for more information. */
now = server.lua_caller ? server.lua_time_start : mstime();

......
}

这段代码的意思很明显,当进入lua脚本后,所有的键过期时间,都会使用进入脚本瞬间的时间来判断,那么就不会存在我所担心,键在脚本执行的途中过期了。