|NO.Z.00050|——————————|BigDataEnd|——|Hadoop&Redis.V03|——|Redis.v03|并发hotkey/bigkey|
一、并发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
Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
——W.S.Landor
分类:
bdv012-redis
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」