我是靠谱客的博主 优秀棒球,最近开发中收集的这篇文章主要介绍redis之如何应对并发访问问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

写在前面

在这里插入图片描述
本文一起看下Redis的并发访问控制。

1:单线程的Redis为什么会有并发问题

我们知道,Redis是单线程的,为什么还是会有并发问题呢?没错,如果是单命令操作的话肯定没有并发问题,但考虑事务的场景,比如库存量,我们会按照如下的步骤进行修改:

1:读取库存量
2:减少库存量
3:写回库存量

我们把这个流程叫做读取-修改-写回,Read-Modify-Write,简称RMW操作。以上的3个步骤,对应到Redis其实是3个命令,当存在并发时,就可能导致库存量错误了,如下图,库存量最终应该是8,但由于并发导致库存量最终是9:

在这里插入图片描述

2:如何解决并发问题

解决并发问题的核心点就是,让操作以原子性的方式执行,首先单命令Redis是天然支持的,另外还有就是lua脚本,对于lua脚本Redis会以原子性的方式执行,分别来看下。

2.1:单命令

对于RMW操作,正常伪代码可能如下:

在这里插入图片描述

这类代码,也有专门的名称,叫做临界代码块,即同时只能被一个线程执行的代码块,因为这类问题比较常见,所以Redis提供了incr和desc单命令来代替以上代码,如下:

127.0.0.1:6379> set age 99
OK
127.0.0.1:6379> incr age
(integer) 100
127.0.0.1:6379> decr age
(integer) 99
127.0.0.1:6379> decr age
(integer) 98

但是对于具有逻辑判断的场景,就无法简单的使用一个命令来完成了,此时我们就需要使用lua脚本。

2.2:lua脚本

考虑限流场景,比如点赞,每小时来自同一个IP的点赞数不能超过100个,此时代码可能如下:

if (containsKey(ip)) {
    int 点赞数 = get(ip);
    if (赞点数 > 100) {
        sout("点赞数超过100");
    } else {
        set(ip, 点赞数+1);
    }
} else {
    // 点赞数设置为1,并设置过期时间为3600秒
    set(ip, 1, 3600);
}

此时如果有来自同一IP的大量并发的话,最终的点赞数肯定会大于100,这不是我们想要的结果,此时,我们就可以将这块代码定义在lua脚本中,如rateLimitLua.script,可能如下:

IF containsKey(ip)) THEN
    点赞数 = get(ip);
    IF (赞点数 > 100) THEN
        sout("点赞数超过100");
    ELSE
        set(ip, 点赞数+1);
    END
ELSE 
    // 点赞数设置为1,并设置过期时间为3600秒
    set(ip, 1, 3600);
END

然后就可以通过eval来执行了redis.cli --eval rateLimitLua.script keys,args,并且以原子的方式执行。

写在后面

参考文章列表:

Redis 单线程 为何却需要事务处理并发问题 。

Redis事务、MULTI 命令和EXEC 命令 。

最后

以上就是优秀棒球为你收集整理的redis之如何应对并发访问问题的全部内容,希望文章能够帮你解决redis之如何应对并发访问问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(174)

评论列表共有 0 条评论

立即
投稿
返回
顶部