CC00050.Redis——|Hadoop&Redis.V03|——|Redis.v03|并发hotkey/bigkey|

本文探讨了Redis中的并发问题,提出分布式锁加时间戳及消息队列作为解决方案。同时,分析了热Key和大Key的影响,并提供了发现和处理这两种问题的方法,包括本地缓存、限流熔断以及大Key的分拆和非阻塞删除策略。
摘要由CSDN通过智能技术生成
一、并发hotkey/bigkey
### --- 数据并发竞争

~~~     这里的并发指的是多个redis的client同时set 同一个key引起的并发问题。
~~~     多客户端(Jedis)同时并发写一个key,一个key的值是1,本来按顺序修改为2,3,4,
~~~     最后是4,但是顺序变成了4,3,2,最后变成了2。
二、数据并发竞争方案
### --- 第一种方案:分布式锁+时间戳

~~~     # 整体技术方案
~~~     这种情况,主要是准备一个分布式锁,大家去抢锁,抢到锁就做set操作。
~~~     加锁的目的实际上就是把并行读写改成串行读写的方式,从而来避免资源竞争。
~~~     # Redis分布式锁的实现
~~~     主要用到的redis函数是setnx()
~~~     用SETNX实现分布式锁
~~~     # 时间戳
~~~     由于上面举的例子,要求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操作了。
### --- 第二种方案:利用消息队列

~~~     在并发量过大的情况下,可以通过消息中间件进行处理,把并行读写进行串行化。
~~~     把Redis的set操作放在队列中使其串行化,必须的一个一个执行。
三、Hot Key
### --- Hot Key

~~~     当有大量的请求(几十万)访问某个Redis某个key时,
~~~     由于流量集中达到网络上限,从而导致这个redis的服务器宕机。
~~~     造成缓存击穿,接下来对这个key的访问将直接访问数据库造成数据库崩溃,
~~~     或者访问数据库回填Redis再访问Redis,继续崩溃。
### --- 如何发现热key

~~~     预估热key,比如秒杀的商品、火爆的新闻等
~~~     在客户端进行统计,实现简单,加一行代码即可
~~~     如果是Proxy,比如Codis,可以在Proxy端收集
~~~     利用Redis自带的命令,monitor、hotkeys。但是执行缓慢(不要用)
~~~     利用基于大数据领域的流式计算技术来进行实时数据访问次数的统计,
~~~     比如 Storm、SparkStreaming、Flink,这些技术都是可以的。
~~~     发现热点数据后可以写到zookeeper中
### --- 如何处理热Key:

~~~     # 变分布式缓存为本地缓存
~~~     发现热key后,把缓存数据取出后,直接加载到本地缓存中。
~~~     可以采用Ehcache、Guava Cache都可以,这样系统在访问热key数据时就可以直接访问自己的缓存了。(数据不要求时时一致)
~~~     在每个Redis主节点上备份热key数据,
~~~     这样在读取时可以采用随机读取的方式,将访问压力负载到每个Redis上。
~~~     # 利用对热点数据访问的限流熔断保护措施
~~~     每个系统实例每秒最多请求缓存集群读操作不超过 400 次,一超过就可以熔断掉,不让请求缓存集群,
~~~     直接返回一个空白信息,然后用户稍后会自行再次重新刷新页面之类的。
~~~     首页不行,系统友好性差通过系统层自己直接加限流熔断保护措施,可以很好的保护后面的缓存集群。
四、Big Key
### --- 大key指的是存储的值(Value)非常大,常见场景:

~~~     热门话题下的讨论
~~~     大V的粉丝列表
~~~     序列化后的图片
~~~     没有及时处理的垃圾数据
### --- 大key的影响:

~~~     大key会大量占用内存,在集群中无法均衡
~~~     Redis的性能下降,主从复制异常
~~~     在主动删除或过期删除时会操作时间过长而引起服务阻塞
### --- 如何发现大key:

~~~     # redis-cli --bigkeys命令。
~~~     可以找到某个实例5种数据类型(String、hash、list、set、zset)的最大key。
~~~     但如果Redis 的key比较多,执行该命令会比较慢
~~~     # 获取生产Redis的rdb文件,
~~~     通过rdbtools分析rdb生成csv文件,再导入MySQL或其他数据库中进行分析统计,
~~~     根据size_in_bytes统计bigkey
### --- 大key的处理:

~~~     优化big key的原则就是string减少字符串长度,list、hash、set、zset等减少成员数。
~~~     # string类型的big key,
~~~     尽量不要存入Redis中,可以使用文档型数据库MongoDB或缓存到CDN上。
~~~     如果必须用Redis存储,最好单独存储,不要和其他的key一起存储。采用一主一从或多从。
~~~     # 单个简单的key存储的value很大,
~~~     可以尝试将对象分拆成几个key-value, 使用mget获取值,这样
~~~     分拆的意义在于分拆单次操作的压力,将操作压力平摊到多次操作中,降低对redis的IO影响。
~~~     hash, set,zset,list 中存储过多的元素,可以将这些元素分拆。(常见)
~~~     以hash类型举例来说对于field过多的场景,
~~~     可以根据field进行hash取模,生成一个新的key,例如原来的
~~~     # 可以hash取模后形成如下
~~~     #  取模后,将原先单个key分成多个key,每个key filed个数为原先的1/N

hash_key:{filed1:value, filed2:value, filed3:value ...},   
key:value形式
hash_key:1:{filed1:value}
hash_key:2:{filed2:value}
hash_key:3:{filed3:value}
...
### --- 删除大key时不要使用del,因为del是阻塞命令,删除时会影响性能。

~~~     # 使用 lazy delete (unlink命令)
~~~     删除指定的key(s),若key不存在则该key被跳过。但是,相比DEL会产生阻塞,
~~~     该命令会在另一个线程中回收内存,因此它是非阻塞的。 
~~~     这也是该命令名字的由来:仅将keys从key空间中删除,真正的数据删除会在后续异步操作。
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> UNLINK key1 key2 key3
(integer) 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yanqi_vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值