iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >Redis并发访问问题详细讲解
  • 866
分享到

Redis并发访问问题详细讲解

Redis并发访问Redis控制并发访问 2022-12-02 11:12:06 866人浏览 泡泡鱼
摘要

目录前言什么场景需要控制并发访问并发访问的控制方法1、加入锁机制2、操作原子化小结前言 我们在使用Redis的过程中,难免会遇到并发访问及数据更新的问题。但很多场景对数据的并发修改是很敏感的,比如库存数据如果没有做好并发

前言

我们在使用Redis的过程中,难免会遇到并发访问及数据更新的问题。但很多场景对数据的并发修改是很敏感的,比如库存数据如果没有做好并发读取和更新的版本控制,就会导致严重的业务问题。今天就来说说应该如何做好并发访问及数据更新问题。

什么场景需要控制并发访问

需要控制并发访问,说明这些并发的访问可能会对其他的访问造成影响。比如上面提到的库存问题,若同一时期有多个客户端访问商品A的库存数据,并且可能要更更新库存数据,这时候就需要对并发访问进行控制了。

说到底,并发访问需要控制的就是对数据的更新动作。 一般来说,客户端要进行数据更新时可分为2个步骤:

  • 客户端读取Redis数据到本地。
  • 确认数据后,修改Redis的数据。

单个访问来看,这个过程并没什么问题。但是并发多了,一分为二的过程就会造成数据错误的问题。这里还是用库存的例子来说:

Redis并发访问问题详细讲解

  • 时间a::客户端1读取到库存=10,我们需要对库存+1=11的操作。
  • 时间b:客户端2读取到的库存也是10,这次要对库存-1=9的操作。
  • 时间c:客户端1将+1后的值11写回到Redis中。
  • 时间d:客户端2将-1后的值9写回到Redis中。

这样下来,很明显能发现库存数据错了。10+1-1 = 10,正确库存是10,而上述场景最后为9。

由此可见,这个一分为二的操作不具有原子性,从而产生了错误的结果。类型这种场景很多,因此我们需要对这些并发访问的场景加以控制。

并发访问的控制方法

Redis并发访问的控制,总的来说有2种方式。分别是加入锁机制和让一系列操作原子化。

1、加入锁机制

首先第一点,加入锁机制是很常见的解决方案。简单来说就是一个客户端访问数据之前,先要获取锁,等数据操作完之后再解锁。而在这个客户端拥有锁的过程中,其他客户端如果也想访问修改该数据,必须得等锁释放了之后,获取到了锁才行。

加锁这个方案是可以解决并发访问的数据准确问题,但放在redis这个场景中并不是很好。首先,Redis作为缓存本身并发访问就很多,频繁的加锁解锁,会大大降低redis的访问性能;然后,Redis的客户端在要加锁时,需要用到分布式锁。我们又得用额外的精力去维护这个分布式锁。

2、操作原子化

操作原子化,也就是让要执行的一系列动作都保持原子性操作。它的优点就是不需要加入额外的锁机制。并发的数据准确性达到了,对Redis的性能也不会有太大的影响。

Redis要实现原子操作,总结有2种方式:

  • 单命令操作:也就是Redis中的INCR、HINCRBY等命令,直接将简单的加减操作合成一个命令执行;
  • lua脚本:借助Lua脚本,让多个操作在Lua脚本上实现原子性操作。

1.单命令操作

首先,单命令操作,将数值的加减直接用Redis命令来执行。像string的加减可用INCR、DECR操作,hash列表field的加减可用HINCRBY操作。

比如下面截图,两个客户端在不同时刻读取的linux_pids a值为4,各自+1、-1后a值为4。结果是正确的。

Redis并发访问问题详细讲解

由此可见,用Redis的INCR、DECR等命令可以解决数值简单增减的并发场景。但如果我们对数据的更新不仅仅是简单的加减操作时,Redis的这些命令就无能为力了。此时我们可以考虑另一种方案:Lua脚本。

2.Lua脚本

Lua语言是由C写的,因此支持多平台和系统。从Redis2.6开始,Redis就内置了Lua解释器,我们能直接用Redis客户端来执行lua脚本。

我们可以将需要执行的一系列操作用Lua脚本写好,然后用Redis执行它。Lua脚本的方法能保证原子性操作的原因是:Redis会将Lua脚本一次性执行,也就是说执行Lua脚本是0-1的操作,要么成功,要么失败。可以理解成Mysql事务特性。

Redis使用lua脚本有2种方式:

  • 客户端中使用:用到script load脚本内容、evalsha等命令
  • 执行直接执行lua脚本

我们一般用第二种方式来执行。

客户端使用方法:

先用script load加载脚本命令,再用evalsha执行加载得到的sha1值。

127.0.0.1:6379> script load "return 'hello'"
"1b936e3fe509bcbc9cd0664897bbe8fd0cac101b"
127.0.0.1:6379> evalsha "1b936e3fe509bcbc9cd0664897bbe8fd0cac101b" 0
"hello"

再来看看Redis使用Lua脚本的语法:

redis-cli --eval {lua_path} KEYS[1] KEYS[2]... , ARGV[1] ARGV[2]...
 
--eval:          执行lua脚本的命令
{lua_path}:         lua脚本的路径
KEYS[1] KEYS[2]:       lua脚本中要操作的redis键,我们可以在lua脚本中用KEYS[1],KEYS[2],KEYS[3]指定多个
ARGV[1] ARGV[2]:    传入到lua脚本的参数,在脚本中用ARGV[1],ARGV[2]...来获取。

Redis使用lua脚本的场景很多,最经典的案例当属利用lua来控制某个IP的访问频率了。比如说需要防止恶意访问网站的行为,我们规定1分钟内访问次数不能超过30次,实现的方法有很多,比如说漏桶方案、令牌桶方案,但使用最多的还是Redis+lua的分布式限流方案。

我们用lua脚本(test_lua.script)来简单实现一下上述功能,就是1分钟内若访问次数超过30,直接拦截,否则访问次数+1:

-- 限流的key
local limit_key = KEYS[1]
-- 限流次数
local limit_nums = 30
-- 当前访问次数
local current_num = tonumber(redis.call('get', limit_key) or 0)
-- 超出限流次数
if current_num + 1 > limit_num
    then
    return '超出访问次数'
-- 没有超出限流数,访问次数+1
else
  redis.call("INCRBY", limit_key, "1")
  -- 第一次访问,设置过期时间
  if current_num == 0 then
    redis.call("expire", limit_key, "60")
  return current + 1
end

用Redis执行,命令如下:

redis-cli --eval test_lua.script limit_key

小结

本文介绍了Redis并发访问的控制问题,以及如何保证并发操作的原子化。原子化操作可通过单命令操作和Lua脚本的方式实现。我们在应对相关问题时,可根据需要选择对应方案解决之。

到此这篇关于Redis并发访问问题详细讲解的文章就介绍到这了,更多相关Redis并发访问内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: Redis并发访问问题详细讲解

本文链接: https://www.lsjlt.com/news/173844.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • Redis并发访问问题详细讲解
    目录前言什么场景需要控制并发访问并发访问的控制方法1、加入锁机制2、操作原子化小结前言 我们在使用Redis的过程中,难免会遇到并发访问及数据更新的问题。但很多场景对数据的并发修改是很敏感的,比如库存数据如果没有做好并发...
    99+
    2022-12-02
    Redis并发访问 Redis控制并发访问
  • Mysq详细讲解如何解决库存并发问题
    目录面临的问题如何实现需求具体实现的方案总结面临的问题 长话短说,假设我们现在面临以下需求 商品的库存有两千,卖完为止某商品本日的售卖只允许卖出一百,卖完为止 如何实现 我提出的方案...
    99+
    2024-04-02
  • Redis解决高并发问题
    1 模拟商品抢购和并发的效果 这里模拟一个商品抢购的过程所带来的问题,以及解决问题的思路。 这里模拟的商品抢购过程是一个商品正常购买的过程,其中包含了两个主要的步骤:商品库存减少和商品购买记录的添加。...
    99+
    2023-09-21
    redis 数据库 mysql
  • Python访问Redis的详细操作
    目录1.连接2.String字符串3.列表4.集合5.哈希6.有序集合1.连接 测试连接是否成功: import redis r = redis.Redis(host='192....
    99+
    2024-04-02
  • Redis如何处理并发访问
    Redis本身是单线程的,因此在处理并发访问时,Redis采取了以下几种策略: 使用单线程处理请求:Redis采用单线程模型来处...
    99+
    2024-04-09
    Redis
  • Redis如何解决高并发问题
    这篇文章主要介绍Redis如何解决高并发问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:redis为什么会有高并发问题redis的出身决定 redis是一种单线...
    99+
    2024-04-02
  • 解决Golang Map 并发访问问题的方法
    一分耕耘,一分收获!既然打开了这篇文章《解决Golang Map 并发访问问题的方法》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也...
    99+
    2024-04-04
  • 如何使用Redis锁处理并发问题详解
    前言 上周“被”上线了一个紧急项目,周五下班接到需求,周一开始思考解决方案,周三开发完成,周四走流程上线,也算是面向领导编程了。之前的项目里面由于是自运维,然后大多数又都赶时间,所以在处理定时任务上面基本都...
    99+
    2024-04-02
  • Java 详细讲解用堆解决Top-k问题
    目录1、什么是堆?堆结构大根堆 VS 小根堆大根堆(最大堆)小根堆(最小堆)优先级队列(PriorityQueue)2、top-k问题解决思路总结:要解决 top-k 问题,我们应该...
    99+
    2024-04-02
  • redis能承受高并发访问吗
    是的,Redis可以承受高并发访问。Redis是一个高性能的内存数据库,其设计目标之一就是能够处理高并发的访问。Redis通过使用单...
    99+
    2023-08-24
    redis
  • Mysql超详细讲解死锁问题的理解
    目录1、什么是死锁?2、Mysql出现死锁的必要条件资源独占条件请求和保持条件不剥夺条件相互获取锁条件3、 Mysql经典死锁案例3.1 建表语句3.2 初始化相关数据3.3 正常转...
    99+
    2024-04-02
  • C#开发中如何处理并发访问问题
    C#开发中如何处理并发访问问题在C#开发中,处理并发访问问题是非常重要的,尤其是在多线程环境下。如果不正确处理并发访问,可能会导致数据不一致或者程序崩溃等问题。本文将介绍一些在C#开发中处理并发访问问题的常用方法,并提供具体的代码示例。使用...
    99+
    2023-10-22
    并发处理 线程安全 锁定
  • redis多进程并发问题怎么解决
    在处理Redis多进程并发问题时,可以考虑以下几种解决方案: 使用分布式锁:可以使用Redis的SETNX命令来实现分布式锁,确...
    99+
    2024-04-09
    redis
  • 浅谈Redis如何应对并发访问
    目录前言原子性操作单命令模式多命令模式lua简介建议事务加锁总结前言 项目中经常会遇到这种场景,我们需要先将Redis数据读取到本地,然后进行修改,修改完成后在将数据写回Redis,...
    99+
    2022-11-13
    Redis 并发访问 Redis 并发
  • redis单线程并发问题如何解决
    Redis是一个单线程的内存数据库,它使用了事件驱动的模型,通过将请求放入一个队列中顺序执行来实现并发处理。但是,在高并发情况下,可...
    99+
    2023-09-11
    redis
  • Redis锁完美解决高并发秒杀问题
    目录1 单机环境下的锁 2 分布式情况下使用Redis锁。 3 一台服务宕机,导致无法释放锁 4 给每一把锁加上过期时间 5延长锁的过期时间,解决锁失效 6 使用Redisson简化...
    99+
    2024-04-02
  • Redis遇到并发、雪崩问题怎么解决
    本篇内容介绍了“Redis遇到并发、雪崩问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Re...
    99+
    2024-04-02
  • 在Go语言中如何解决并发缓存访问问题?
    在Go语言中如何解决并发缓存访问问题?在并发编程中,缓存是一种常用的优化策略。通过缓存数据,可以减少对底层存储的频繁访问,提高系统的性能。然而,在多个并发访问的场景下,经常会遇到并发缓存访问问题,如缓存竞争、缓存穿透等。本文将介绍在Go语言...
    99+
    2023-10-22
    Go语言中的Mutex(互斥锁) Go语言中的Channel(通道) Go语言中的WaitGroup(等待组)
  • python3使用python-redis-lock解决并发计算问题
    目录需求python-redis-lock修改业务代码,增加lock操作需求 我在最近的一个任务中,存在一个redis高并发计算多个客户端接收预警信息的时长问题。 模型是首先模拟多个...
    99+
    2024-04-02
  • ASP 面试中 path 存储问题的详细讲解与解答!
    在 ASP 开发中,我们经常需要使用到 path 变量来指定文件或者文件夹的路径。但是,在实际开发中,我们也会遇到一些 path 存储问题。本篇文章将会详细讲解这些问题,并给出解答。 相对路径和绝对路径 在 ASP 中,我们可以使用相...
    99+
    2023-11-14
    面试 path 存储
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作