Redis的并发竞争问题,主要是发生在并发写竞争。

考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这种方式进行对数据的更新。

假如有某个key = "price",  value值为10,现在想把value值进行+10操作。正常逻辑下,就是先把数据key为price的值读回来,加上10,再把值给设置回去。

如果只有一个连接的情况下,这种方式没有问题,可以工作得很好,但如果有两个连接时,两个连接同时想对还price进行+10操作,就可能会出现问题了。

例如:两个连接同时对price进行写操作,同时加10,最终结果我们知道,应该为30才是正确。

考虑到一种情况:

T1时刻,连接1将price读出,目标设置的数据为10+10 = 20。

T2时刻,连接2也将数据读出,也是为10,目标设置为20。

T3时刻,连接1将price设置为20。

T4时刻,连接2也将price设置为20,则最终结果是一个错误值20。

如何解决redis的并发竞争key问题呢?下面给到3个Redis并发竞争的解决方案。

第一种方案:分布式锁+时间戳

1.整体技术方案

这种情况,主要是准备一个分布式锁,大家去抢锁,抢到锁就做set操作。

加锁的目的实际上就是把并行读写改成串行读写的方式,从而来避免资源竞争。

2.Redis分布式锁的实现

主要用到的redis函数是setnx()

用SETNX实现分布式锁,也是内置的锁

利用SETNX非常简单地实现分布式锁。例如:某客户端要获得一个名字youzhi的锁,客户端使用下面的命令进行获取:

SETNX lock.youzhi<current Unix time + lock timeout + 1>

如返回1,则该客户端获得锁,把lock.youzhi的键值设置为时间值表示该键已被锁定,该客户端最后可以通过DEL lock.foo来释放该锁。
如返回0,表明该锁已被其他客户端取得,这时我们可以先返回或进行重试等对方完成或等待锁超时。

3.时间戳

由于上面举的例子,要求key的操作需要顺序执行,所以需要保存一个时间戳判断set顺序。

系统A key 1 {ValueA 7:00}

系统B key 1 { ValueB 7:05}

假设系统B先抢到锁,将key1设置为{ValueB 7:05}。接下来系统A抢到锁,发现自己的key1的时间戳早于缓存中的时间戳(7:00<7:05),那就不做set操作了。

当然,分布式锁可以基于很多种方式实现,比如zookeeper、redis等,不管哪种方式实现,基本原理是不变的:用一个状态值表示锁,对锁的占用和释放通过状态值来标识。

第二种方案:使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)

乐观锁(redis 的命令 watch):
当执行多键值事务操作时,Redis 不仅要求这些键值需要落在同一个 Redis 实例上,还要求落在同一个 slot 上,所以 redis 的事务比较鸡肋
不过可以想办法遵循 redis 内部的分片算法把设计到的所有 key 分到同一个 slot。

如何用乐观锁方式进行解决?

本质上是假设不会进行冲突,使用redis的命令watch进行构造条件。伪代码如下:

watch price

get price $price

$price = $price + 10

multi

set price $price

exec

解释一下:

watch这里表示监控该key值,后面的事务是有条件的执行,如果从watch的exec语句执行时,watch的key对应的value值被修改了,则事务不会执行。

同样考虑刚刚的场景

T1时刻,连接1对price进行watch,读出price值为10,目标计算为20;

T2时刻,连接2对price进行watch,读出price值为10,目标计算为20;

T3时刻,连接2将目标值为20写到redis中,执行事务,事务返回成功。

T4时刻,连接1也对price进行写操作,执行事务时,由于之前已经watch了price,price在T1至T4之间已经被修改过了,所以事务执行失败。

综上,该乐观锁机制可以简单明了的解决了写冲突的问题。

又问:如果多个写操作同时过来,100个写操作同时watch,则最终只会有一个成功,99个执行失败,何解?

如果同时进行有多个请求进行写操作,例如同一时刻有100个请求过来,那么只会有一个最终成功,其余99个全部会失败,效率不高。

而且从业务层面,有些是不可接受的场景。例如:大家同时去抢一个红包,如果背后也是用乐观锁的机制去处理,那每个请求后都只有一个人成功打开红包,这对业务是不可忍受的。

在这种情况下,如果想让总体效率最大化,可以采用排队的机制进行。

将所有需要对同一个key的请求进行入队操作,然后用一个消费者线程从队头依次读出请求,并对相应的key进行操作。

这样对于同一个key的所有请求就都是顺序访问,正常逻辑下则不会有写失败的情况下产生 。从而最大化写逻辑的总体效率。

第三种方案:利用消息队列

在并发量过大的情况下,可以通过消息中间件进行处理,把并行读写进行串行化。

把Redis.set操作放在队列中使其串行化,必须的一个一个执行。

这种方式在一些高并发的场景中算是一种通用的解决方案。

以上是本文的全部内容,希望对大家的学习有帮助,也希望大家多多支持php自学中心 

Redis的并发竞争问题,你用哪些方案来解决?的更多相关文章

  1. Redis的并发竞争问题的解决方案总结

    什么是Redis的并发竞争问题 Redis的并发竞争问题,主要是发生在并发写竞争. 考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这 ...

  2. 12.redis 的并发竞争问题是什么?如何解决这个问题?了解 redis 事务的 CAS 方案吗?

    作者:中华石杉 面试题 redis 的并发竞争问题是什么?如何解决这个问题?了解 redis 事务的 CAS 方案吗? 面试官心理分析 这个也是线上非常常见的一个问题,就是多客户端同时并发写一个 ke ...

  3. 关于redis的几件小事(九)redis的并发竞争问题

    1.什么是并发竞争 就是多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了.或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了. 2.怎么解决 采 ...

  4. 如何解决redis的并发竞争问题?

    这个也是线上非常常见的一个问题,就是多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了.或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了. 而且 ...

  5. redis的并发竞争问题是什么?如何解决这个问题?

    这个也是线上非常常见的一个问题,就是多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了.或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了. 而且 ...

  6. Redis的并发竞争问题

    问题描述:多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了.或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了. 一个key的值是1,本来按顺序 ...

  7. Redis缓存穿透、缓存雪崩、redis并发问题 并发竞争key的解决方案 (阿里)

    阿里的人问我 缓存雪崩(大量数据在同一时间过期了)了如何处理,缓存击穿了如何处理,回答的很烂,做了总结: 把redis作为缓存使用已经是司空见惯,但是使用redis后也可能会碰到一系列的问题,尤其是数 ...

  8. 高并发架构系列:Redis并发竞争key的解决方案详解

    https://blog.csdn.net/ChenRui_yz/article/details/85096418 https://blog.csdn.net/ChenRui_yz/article/l ...

  9. 分布式-技术专区-Redis并发竞争key的解决方案详解

    Redis缓存的高性能有目共睹,应用的场景也是非常广泛,但是在高并发的场景下,也会出现问题:缓存击穿.缓存雪崩.缓存和数据一致性,以及今天要谈到的缓存并发竞争.这里的并发指的是多个redis的clie ...

随机推荐

  1. strcpy和memcpy的区别-(转自stone Jin)

    strcpy和memcpy都是标准C库函数,它们有下面的特点.strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符. 已知strcpy函 ...

  2. 10.20 host:域名查询工具

    host命令 是用于查询DNS的工具,它可以将指定主机名称转换为IP地址. host命令的参数选项及说明 -a 显示详细的DNS信息-t 指定查询的域名信息类型,可以是"A".&q ...

  3. DLL重定向处理

    说明 目前正在做的项目批次功能涉及第三方插件,而第三方插件需依赖4.* 版本的Newtonsoft.Json.dll,由于现有功能已经使用6.*版本的Newtonsoft.Json.dll,故采用了d ...

  4. 004:ZYNQ_AXI总线学习笔记(1)

    1.    WHAT IS AXI? AXI是一种高级可扩展接口,是ARM AMBA的一部分. 2.    WHAT IS AMBA? AMBA是高级微控制器总线架构,开放的片内互联总线标准. 3.A ...

  5. 4D毫米波雷达Radar

    4D毫米波雷达Radar 围绕雷达.激光雷达.高精定位等新一代传感器技术将会进入量产周期. 自动驾驶公司的竞争,在传感器配置上坦白说并没有太多差异化.除了车载激光雷达属于近几年的产物,类似摄像头.毫米 ...

  6. 国内操作系统OS分析(下)

    国内操作系统OS分析(下) 3.2 Android/iOS移动互联网时代 Android是一种基于Linux的自由及开放源代码的操作系统.主要使用于移动设备,如智能手机和平板电脑,由Google公司和 ...

  7. FFmpeg扩展开发

    FFmpeg扩展开发 对FFmpeg RTMP/FLV部分做了扩展,用于支持H.265. 针对<video_file_format_spec_v10_1> VIDEODATA部分扩展如下: ...

  8. 转置卷积Transposed Convolution

    转置卷积Transposed Convolution 我们为卷积神经网络引入的层,包括卷积层和池层,通常会减小输入的宽度和高度,或者保持不变.然而,语义分割和生成对抗网络等应用程序需要预测每个像素的值 ...

  9. [NOIP1998 提高组] 拼数

    题目描述 设有 n 个正整数​ a1-an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数. 输入格式 第一行有一个整数,表示数字个数 n. 第二行有 n 个整数,表示给出的 n 个整数 a_ ...

  10. ContOS8 配置MariaDB

    导语: 该篇文章主要记录ContOS8安装MariaDB后的一些配置内容,若想要详细了解安装过程请移步至上一篇博文! 正文: 首先对MariaDB进行相关的简单配置 使用mysql_secure_in ...