如何处理Redis集群中的Big key和Hot keys

amang2000
发布于 2022-4-30 19:43
浏览
0收藏

作者 | 川石信息
来源 | 今日头条

Big key

即数据量大的 key ,由于其数据大小远大于其他key,导致经过分片之后,某个具体存储这个 big key 的实例内存使用量远大于其他实例,造成,内存不足,拖累整个集群的使用。big key 在不同业务上,通常体现为不同的数据,比如:

  1. 论坛中的大型持久盖楼活动;
  2. 聊天室系统中热门聊天室的消息列表;

Hot key

即热点 key,指的是在一段时间内,该 key 的访问量远远高于其他的 redis key, 导致大部分的访问流量在经过 proxy 分片之后,都集中访问到某一个 redis 实例上。hot key 通常在不同业务中,存储着不同的热点信息。比如:

  1. 新闻应用中的热点新闻内容;
  2. 活动系统中某个用户疯狂参与的活动的活动配置;

(1)查看Big key

[root@localhost bin]# redis-cli --bigkeys 
# Scanning the entire keyspace to find biggest keys as well as 
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec 
# per 100 SCAN commands (not usually needed). 
[00.00%] Biggest string found so far 'counter:__rand_int__' with 5 bytes 
[00.00%] Biggest string found so far 'test1' with 8 bytes 
[00.00%] Biggest string found so far 'name' with 111 bytes 
[00.00%] Biggest hash found so far 'bash_insert' with 1000 fields 
[00.00%] Biggest list found so far 'mylist' with 20000 items 
-------- summary ------- 
Sampled 10 keys in the keyspace! 
Total key length in bytes is 87 (avg len 8.70) 
Biggest string found 'name' has 111 bytes 
Biggest list found 'mylist' has 20000 items 
Biggest hash found 'bash_insert' has 1000 fields 
6 strings with 135 bytes (60.00% of keys, avg size 22.50) 
1 lists with 20000 items (10.00% of keys, avg size 20000.00) 
0 sets with 0 members (00.00% of keys, avg size 0.00) 
3 hashs with 1003 fields (30.00% of keys, avg size 334.33) 
0 zsets with 0 members (00.00% of keys, avg size 0.00) 
0 streams with 0 entries (00.00% of keys, avg size 0.00)

(2)bigkey带来的问题:

1.内存空间不均匀

在集群模式中,由于bigkey的存在,会造成主机节点的内存不均匀,这样会不利于集群对内存的统一管理,存在丢失数据的隐患。

2.超时阻塞

由于redis单线程的特性,操作bigkey通常比较耗时,也就意味着阻塞redis可能性越大,这样会造成客户端阻塞或者引起故障切换。慢查询通常就会有它们的身影。

3.网络拥塞

bigkey也就意味着每次获取要产生的网络流量较大。假设一个bigkey为1MB,客户端每秒访问量为1000,那么每秒产生1000MB的流量,对于普通的千兆网卡(按照字节算是128MB/s)的服务器来说简直是灭顶之灾。

4.阻塞删除

有个bigkey,对它设置了过期时间,当它过期后会被删除,如果使用Redis 4.0之前的版本,过期key是异步删除,就会存在阻塞redis的可能性,而且这个过期删除不会从慢查询发现(因为这个删除不是客户端产生的,是内部循环事件)。

bigkey的产生主要是由于程序的设计不当所造成的,如以下几种常见的业务场景:

社交类:粉丝列表,如果某些明星或者大v不精心设计下,必是bigkey。

统计类:例如按天存储某项功能或者网站的用户集合,除非没几个人用,否则必是bigkey。

缓存类:将数据从数据库load出来序列化放到redis里,这个方式经常常用,但有两个地方需要注意:第一,是不是有必要把所有字段都缓存;第二,有没有相关关联的数据。

(3)优化 bigkey

优化big key的原则就是string减少字符串长度,list、hash、set、zset等减少成员数;string长度大于10K,list长度大于10240认为是big bigkeys。

1.拆分

如果对象是整存争取,将对象拆分后才能多个小key-value,get不同的key或者批量获取stringRedisTemplate.opsForValue() .multiGet(keyList)

如果对象是部分更新获取数据,可以分拆成几个key-value,也可以存储在hash中,部分更新部分存取!

2.本地缓存

减少访问redis次数,降低危害减少访问redis次数,降低危害!当然本地开销也会变大!

Redis 4.0.3中新增查看热点数据命令行,使用热点数据必须将内存策略修改为LFU算法。

查看内存策略

config get maxmemory-policy 

> config get maxmemory-policy 
maxmemory-policy 
allkeys-lfu

查看 key 使用频率

object freq name 
> object freq name 
1

Hot key 错误

如果在查看key使用频率或查看hot key时出现以下错误,那就必须先修改LFU算法

(error) ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust.

Least Frequently Used:最不经常使用。

Redis有两种LFU算法:

  • volatile-lfu:设置了过期时间的key中,进行LFU淘汰。
  • allkeys-lfu:所有key参与LFU淘汰。

更改内存策略

config set maxmemory-policy allkeys-lfu

查看热点数据

统计时间隔0.1秒,防止阻塞其他线程。

redis-cli --hotkeys -i 0.1 

[root@localhost bin]# redis-cli --hotkeys -i 0.1 
# Scanning the entire keyspace to find hot keys as well as 
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec 
# per 100 SCAN commands (not usually needed). 

[00.00%] Hot key 'counter:__rand_int__' found so far with counter 1 
[00.00%] Hot key 'test1' found so far with counter 1 
[00.00%] Hot key 'key:__rand_int__' found so far with counter 1 
[00.00%] Hot key 'test' found so far with counter 1 
[00.00%] Hot key 'name' found so far with counter 1 
[00.00%] Hot key 'bash_insert' found so far with counter 1 
[00.00%] Hot key 'mylist' found so far with counter 1 
[00.00%] Hot key 'v' found so far with counter 1 
[00.00%] Hot key 'ht' found so far with counter 1 
[00.00%] Hot key 'myset:__rand_int__' found so far with counter 1 
  -------- summary -------  
Sampled 10 keys in the keyspace! 
hot key found with counter: 1 keyname: counter:__rand_int__ 
hot key found with counter: 1 keyname: test1 
hot key found with counter: 1 keyname: key:__rand_int__ 
hot key found with counter: 1 keyname: test 
hot key found with counter: 1 keyname: name 
hot key found with counter: 1 keyname: bash_insert 
hot key found with counter: 1 keyname: mylist 
hot key found with counter: 1 keyname: v 
hot key found with counter: 1 keyname: ht 
hot key found with counter: 1 keyname: myset:__rand_int__

收藏
回复
举报
回复
    相关推荐