我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈Redis如何应对并发访问

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈Redis如何应对并发访问

前言

项目中经常会遇到这种场景,我们需要先将Redis数据读取到本地,然后进行修改,修改完成后在将数据写回Redis,这种读取-修改-写回操作,我们称之为RMW操作。当有多个客户端对同一份数据执行RMW操作的话,Redis如何保证RMW操作涉及的代码以原子性方式执行?

原子性操作

Redis的原子性操作是一种无锁操作,即可以保证并发控制,还能减少系统对并发性能的影响,

单命令模式

把Redis多个操作实现成一个操作,即为单命令模式。

Redis提供了INCR/DECR命令,可以对数据进行增值/减值操作,而且它们本身就是单个命令操作,Redis单线程模式,执行命令时具有互斥性。

示例说明

 public Long getIncrNumber(String key,long alive) 
    {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long incrNum = entityIdCounter.getAndIncrement();
        if (null == incrNum || incrNum.longValue()==0) 
        {
            entityIdCounter.expire(alive,TimeUnit.MILLISECONDS);
            incrNum = entityIdCounter.getAndIncrement();
        }
        return incrNum;
    }

说明:采用Reids的INCR命令,如果不存在的key则设置过期时间,如果key存在则进行递增操作返回。所以如果我们执行RMW操作进行相关的递增或者递减操作时,Redis提供的INCR和DECY命令可以保证并发控制。

多命令模式

当我们不是执行简单的加加减减操作,而是更加复杂的逻辑判断或者其他操作时,Redis是无法保证原子性,所以需要将多个操作写到一个Lua脚本中,Redis会把Lua脚本作为一个整体执行,在执行过程中不会被其他命令打断,从而保证了操作的原子性。

lua简介

Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

示例说明

接口进行限流操作,同一用户3秒内不能重复访问,我们可以通过lua脚本来实现。

local key = KEYS[1]
local count = tonumber(ARGV[1])
local time = tonumber(ARGV[2])
local current = redis.call('get', key)
if current and tonumber(current) > count then
    return tonumber(current)
end
current = redis.call('incr', key)
if tonumber(current) == 1 then
    redis.call('expire', key, time)
end
return tonumber(current)

说明:key、count、time为三个传入参数,分别代表Redis的key、次数和过期时间。通过get获取key对应的值,获取的值为时间内访问接口的次数,如果为第一次访问则返回的为null,此时需要对当前key进行自增1操作,如果返回为数字,则需要判断返回的数字是否已经超过了cout值,如果超过说明已经超过限流了,直接返回。

建议

  • 1.编写lua脚本不要进行复杂耗时的计算逻辑,否则执行lua时间过长,会导致Redis主线程阻塞。
  • 2.lua脚本尽量简单,不要把所有的操作都放入到lua脚本中执行,这样会导致Redis执行脚本的时间增加,同时也会降低Redis的并发性能。

事务

关于事务保证原子性,采用的watch命令其原理和乐观锁的实现原理类似,详情可以参考juejin.cn/post/712582… 文章,本文就不在具体阐述。

加锁

关于Redis的分布式锁的实现,后续的章节进行详情说明。高并发环境下加锁虽然能够保证正确性,但是也会带来其他的问题:

  • 加锁操作过多会降低系统的并发访问性能
  • Redis客户端要加锁,需要使用分布式锁,而分布式锁实现复杂,增加复杂度。

总结

本文讲解了针对并发访问Redis如何保证原子性操作,针对不同的业务场景,选择合适的方案,更多相关Redis 并发访问内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈Redis如何应对并发访问

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

浅谈Redis如何应对并发访问

本文主要介绍了Redis如何应对并发访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

Redis如何处理并发访问

Redis本身是单线程的,因此在处理并发访问时,Redis采取了以下几种策略:使用单线程处理请求:Redis采用单线程模型来处理请求,通过事件驱动的方式来处理并发请求,确保不会出现并发访问的竞争条件。基于内存的操作:Redis是基于内存的数
Redis如何处理并发访问
2024-04-09

Oracle中如何处理并发访问

在Oracle数据库中处理并发访问通常可以通过以下几种方式来实现:使用事务:通过使用事务来保证并发访问的一致性。事务可以确保一组操作要么全部成功提交,要么全部回滚。通过使用事务,可以避免在并发访问时出现数据不一致的情况。使用锁机制:Orac
Oracle中如何处理并发访问
2024-04-09

SQLite中如何处理并发访问

SQLite是一种轻量级的数据库管理系统,通常用于嵌入式设备或小型应用程序中。在SQLite中处理并发访问的主要方法包括:使用事务:在SQLite中,可以使用事务来处理并发访问。通过使用BEGIN、COMMIT 和 ROLLBACK 命令来
SQLite中如何处理并发访问
2024-04-09

C#开发中如何处理并发访问问题

C#开发中如何处理并发访问问题在C#开发中,处理并发访问问题是非常重要的,尤其是在多线程环境下。如果不正确处理并发访问,可能会导致数据不一致或者程序崩溃等问题。本文将介绍一些在C#开发中处理并发访问问题的常用方法,并提供具体的代码示例。使用
2023-10-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录