01. 并发竞争的由来java
1.Redis高并发的问题redis
Redis缓存的高性能有目共睹,应用的场景也是很是普遍,可是在高并发的场景下,也会出现问题:缓存击穿、缓存雪崩、缓存和数据一致性,以及今天要谈到的缓存并发竞争。sql
这里的并发指的是多个redis的client同时set key引发的并发问题。数据库
2.出现并发设置Key的缘由缓存
Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。因为单线程因此Redis自己并无锁的概念,多个客户端链接并不存在竞争关系,可是利用jedis等客户端对Redis进行并发访问时会出现问题。并发
好比:同时有多个子系统去set一个key。这个时候要注意什么呢?nosql
3.举一个例子分布式
多客户端同时并发写一个key,一个key的值是1,原本按顺序修改成2,3,4,最后是4,可是顺序变成了4,3,2,最后变成了2。函数
如何解决redis的并发竞争key问题呢?下面给到2个Redis并发竞争的解决方案。高并发
02. 第一种方案:分布式锁+时间戳
1.总体技术方案
这种状况,主要是准备一个分布式锁,你们去抢锁,抢到锁就作set操做。
加锁的目的实际上就是把并行读写改为串行读写的方式,从而来避免资源竞争。
2.Redis分布式锁的实现
主要用到的redis函数是setnx()
用SETNX实现分布式锁
利用SETNX很是简单地实现分布式锁。例如:某客户端要得到一个名字youzhi的锁,客户端使用下面的命令进行获取:
SETNX lock.youzhi<current Unix time + lock timeout + 1>
2.时间戳
因为上面举的例子,要求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操做了。
3.什么是分布式锁
由于传统的加锁的作法(如java的synchronized和Lock)这里没用,只适合单点。由于这是分布式环境,须要的是分布式锁。
固然,分布式锁能够基于不少种方式实现,好比zookeeper、redis等,无论哪一种方式实现,基本原理是不变的:用一个状态值表示锁,对锁的占用和释放经过状态值来标识。
03. 第二种方案:利用消息队列
在并发量过大的状况下,能够经过消息中间件进行处理,把并行读写进行串行化。
把Redis.set操做放在队列中使其串行化,必须的一个一个执行。
这种方式在一些高并发的场景中算是一种通用的解决方案。
end~
以上就是Redis并发竞争key技术方案详解,喜欢的能够点赞关注哦~