Redis GETSET , 原来这么好用

740 阅读2分钟

今天在阅读 redis 官方文档的时候,发现了一个之前从没认真注意过的 command: GETSET。

API 文档里给的说明是:

Atomically sets key to value and returns the old value stored at key. Returns an error when key exists but does not hold a string value.

可以用于实现以下模式:

GETSET can be used together with INCR for counting with atomic reset. For example: a process may call INCR against the key mycounter every time some event occurs, but from time to time we need to get the value of the counter and reset it to zero atomically. This can be done using GETSET mycounter "0":

和 INCR 结合起来使用,实现计数器归零。上述描述中一个词很重要:atomically,这意味着这是原子化的操作。常见的应用场景如下:记录每小时的网站访问数(每小时需要清零)

You can use this command, for example, if you have a system that increments a Redis key usingINCRevery time your web site receives a new visitor. You may want to collect this information once every hour, without losing a single increment. You can GETSET the key, assigning it the new value of "0" and reading the old value back.

恰好目前自己的项目中也有类似的业务场景:我们有一个记录用户调用接口次数的功能,之前是实时写入数据库的,性能很慢。现在加了一层 redis 缓存,把每分钟内的调用次数先缓存至 redis counter(每调用一次 INCR 一下)。然后有一个类似 cron 进程,会每隔一分钟读取这个技术值,一次性将次数记录到数据库中。

之前的 cron 进程是这样的:GET 读取 counter 值 -> SET 将 counter 置 0 -> 更新数据库。在流量小的情况下还很难发现问题,但是一旦流量一大,在读取 counter 和 counter 置零的之间的计数就被丢失掉了。现在只需要调用一次 GETSET 操作,确保不会有遗漏。