Redis 的 INCR
和 DECR
命令用于对存储在键中的数字值进行原子性的递增或递减操作。这两个命令的实现主要关注点在于保证操作的原子性和数值类型的处理。下面是基于源码的学习概览:
源码位置
- 这些命令的实现可以在Redis源代码的
t_string.c
文件中找到,具体函数为incrCommand
和decrCommand
。
实现逻辑
-
命令处理:
incrCommand
和decrCommand
函数首先通过lookupKeyWrite
函数尝试获取键关联的值对象。如果键不存在,Redis会创建一个新的值对象并初始化为0(对于INCR
)或-1(对于DECR
)。 -
类型检查:获取到值对象后,Redis会检查它的类型。这些命令只能应用于字符串类型,并且要求字符串能够被解释为一个整数。如果不是整数或者类型不匹配,Redis会返回一个错误。
-
数值操作:对于类型正确的字符串,Redis会调用
incrDecrCommand
辅助函数来进行实际的加减操作。这个函数会根据命令的不同(增加或减少)调整值,并且确保操作不会超出64位有符号整数的范围。 -
原子性保证:由于Redis是单线程的,所以
INCR
和DECR
操作天然具有原子性,这意味着在同一时间不会有其他操作干扰到这个过程。 -
结果返回:操作完成后,新的数值会作为命令的响应返回给客户端。
特殊情况处理
- 如果数值达到64位有符号整数的最大值或最小值,Redis不会溢出而是让值保持在最大值或最小值不变。
代码示例
void incrCommand(redisClient *c) {
incrDecrCommand(c, 1); // 传入1表示递增
}
void decrCommand(redisClient *c) {
incrDecrCommand(c, -1); // 传入-1表示递减
}
void incrDecrCommand(redisClient *c, int incr) {
// 实现递增或递减的具体逻辑,包括类型检查、数值调整等
}
通过阅读这些源码部分,可以理解Redis是如何保证INCR
和DECR
命令操作的高效性和原子性的,以及它如何处理边界条件和类型不匹配的情况。