首页 > 数据库 >Redis大key问题解决方案

Redis大key问题解决方案

时间:2023-09-26 09:02:40浏览次数:65  
标签:存储 key 解决方案 redis Key Redis 客户端

 

Redis 的大 key 如何处理

 

介绍 

大key 并不是指 key 的值很大,而是 key 对应的 value 很大(非常占内存)

一般而言,下面这两种情况被称为大 key:

  • String 类型的值大于 10 KB;
  • Hash、List、Set、ZSet 类型的元素的个数超过 5000个;

为什么会出现大key

  1. 数据结构不合理:当使用 Redis 的字符串类型存储较大的数据时,如果没有合适地切分数据,就会导致一个 Key 的值过大。例如,将整个文本内容存储在一个字符串类型的 Key 中。

  2. 批量写入数据:在进行大规模写入操作时,如果将大量的数据一次性写入到一个 Key 中,就会导致大 Key 的问题。这种情况常见于批量导入数据或者数据迁移的场景。缓存数据失效策略不当:

  3. 如果缓存的数据失效策略不合理,导致某个Key的数据长时间没有被清除,就可能导致该Key变得很大。这可能是由于没有设置合理的过期时间或没有及时删除过期的数据。

大 key 会带来以下四种影响:

  • 客户端超时阻塞。由于 Redis 执行命令是单线程处理,然后在操作大 key 时会比较耗时,那么就会阻塞 Redis,从客户端这一视角看,就是很久很久都没有响应。
  • 引发网络阻塞。每次获取大 key 产生的网络流量较大,如果一个 key 的大小是 1 MB,每秒访问量为 1000,那么每秒会产生 1000MB 的流量,这对于普通千兆网卡的服务器来说是灾难性的。
  • 阻塞工作线程。如果使用 del 删除大 key 时,会阻塞工作线程,这样就没办法处理后续的命令。
  • 内存分布不均。集群模型在 slot 分片均匀情况下,会出现数据和查询倾斜情况,部分有大 key 的 Redis 节点占用内存多,QPS 也会比较大。

如何找到大 key

使用 RdbTools 工具查找大 key

使用 RdbTools 第三方开源工具,可以用来解析 Redis 快照(RDB)文件,找到其中的大 key。

比如,下面这条命令,将大于 10 kb 的  key  输出到一个表格文件。

rdb dump.rdb -c memory --bytes 10240 -f redis.csv

如何删除大 key

这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序

这里给出两种方法:

  • 分批次删除
  • 异步删除(Redis 4.0版本以上):用 unlink 命令代替 del 来删除

为了解决大 Key 问题,可以采取以下几种方式:

  1. 分割大 Key:将一个大 Key 的值分割成多个小 Key,然后分别存储。例如,将一个大的字符串分割为多个小的字符串片段,然后分别以不同的 Key 存储。这样可以避免一个大 Key 导致的性能问题。

  2. 使用 Hash 数据结构:将大 Key 的值存储在 Hash 数据结构中,其中 Hash 的 field 作为子 Key,value 作为 value。这样可以将大 Key 分割成多个子 Key,每个子 Key 在 Hash 中都是独立的,这样可以减少对单个 Key 的访问。

  3. 使用 Redis 的分布式特性:通过使用 Redis 的分片或者集群功能,将大 Key 的数据分布到不同的 Redis 实例或节点上。这样可以利用多个实例或节点的性能来处理大 Key,减少单个实例或节点的负载。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

一、问题背景

所谓的bigkey就是存储本身的key值空间太大,或者hash,list,set等存储中value值过多。

主要包括:

1、单个简单的key存储的value很大

2、hash, set,zset,list 中存储过多的元素

3、一个集群存储了上亿的key

bigkey会带来一些问题,如:
1.读写bigkey会导致超时严重,甚至阻塞服务。

2.大key相关的删除或者自动过期时,会出现qps突降或者突升的情况,极端情况下,会造成主从复制异常,Redis服务阻塞无法响应请求。bigkey的体积与删除耗时可参考下表:

 

key类型 field数量 耗时
Hash 100万 1000ms
List 100万 1000ms
Set 100万 1000ms
ZSet 100万 1000ms

 

redis 是单线程,操作 bigkey 比较耗时,那么阻塞 redis 的可能性增大。每次获取 bigKey 的网络流量较大,假设一个 bigkey 为 1MB,每秒访问量为 1000,那么每秒产生 1000MB 的流量,对于普通千兆网卡,按照字节算 128M/S 的服务器来说可能扛不住。而且一般服务器采用单机多实例方式来部署,所以还可能对其他实例造成影响。

 

二、redis单线程模型

1、redis单线程操作过程

 

 

(1)redis 会将每个客户端都关联一个指令队列。客户端的指令通过队列来按顺序处理,先到先服务。

(2)在一个客户端的指令队列中的指令是顺序执行的,但是多个指令队列中的指令是无法保证顺序的。

(3)redis 同样也会为每个客户端关联一个响应队列,通过响应队列来顺序地将指令的返回结果回复给客户端。

(4)一个响应队列中的消息可以顺序的回复给客户端,多个响应队列之间是无法保证顺序的。

(5)所有的客户端的队列中的指令或者响应,redis 每次都只能处理一个,同一时间绝对不会处理超过一个指令或者响应。

2、redis内部操作过程

redis基于Reactor模式开发了自己的网络事件处理器,

 

 

Redis通过socket与客户端进行连接,并将服务器对socket的操作抽象为文件事件。redis通过单线程,并通过I/O多路复用来处理来自客户端的多个连接请求,当产生连接后,i/o多路复用程序,会将产生事件的套接字放置一个队列,通过队列以有序、同步的、每次一个套接字的方式向文件事件分派发器传送套接字。当上一个套接字的事件被处理完毕后,I/O多路复用才会向文件分派器传送下一个套接字。服务端通过监听这些事件,并完成相应的处理。被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作,与操作相关的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。

三、对于bigkey常用的解决办法

1、单个简单的key存储的value很大

(1)对象需要每次都整存整取

可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;

(2)该对象每次只需要存取部分数据

可以像第一种做法一样,分拆成几个key-value, 也可以将这个存储在一个hash中,每个field代表一个具体的属性,使用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性

2、 hash, set,zset,list 中存储过多的元素

可以对存储元素按一定规则进行分类,分散存储到多个redis实例中。

对于一些榜单类的场景,用户一般只会访问前几百及后几百条数据,可以只缓存前几百条以及后几百条,即对用户经常访问的数据做缓存(正序倒序的前几页),而不是全部都做,对于获取中间的数据则可以直接从数据库获取

3、一个集群存储了上亿的key

如果key的个数过多会带来更多的内存空间占用,

1.key本身的占用。

2.集群模式中,服务端有时需要建立一些slot2key的映射关系,这其中的指针占用在key多的情况下也是浪费巨大空间。

所以减少key的个数可以减少内存消耗,可以参考的方案是转Hash结构存储,即原先是直接使用Redis String 的结构存储,现在将多个key存储在一个Hash结构中

 

对缓存操作的改善可以利用pipeline管道

拆分之后可以考虑采用pipeline去取,由于redis是单线程的,一次只能执行一个命令,这里采用Pipeline模式,一次发送多个命令,无需等待服务端返回。这样就大大的减少了网络往返时间,提高了系统性能。

 

 

 

-----------------------------------------------------------------------------------------------------------------

标签:存储,key,解决方案,redis,Key,Redis,客户端
From: https://www.cnblogs.com/jiaodaoniujava/p/17729308.html

相关文章

  • 山海鲸智慧交通解决方案demo——构建未来城市出行的数字蓝图
    随着城市化进程的不断加速,城市交通问题也变得日益严重。为了改善城市交通体验、提高出行效率以及减少交通拥堵和环境污染。山海鲸可视化打造城市智慧交通系列解决方案模板,解决方案以“数字孪生技术”为核心,通过数据分析、人工智能和物联网技术来优化城市出行,下面带大家详细了解一......
  • Microsoft 365 解决方案:为访客用户创建安全的Microsoft团队和共享频道环境
    博客链接:https://blog.51cto.com/u_13637423随着数字化转型的推进,企业都纷纷采用云端的解决方案来满足日常企业的运作需求,这包含与企业外部的供应商和合作伙伴的业务往来,那么从IT和Secure角度,如何考虑在不影响安全的情况下确保在MicrosoftTeams上与外部用户协作和工作是顺利的呢?·......
  • 阿姆达尔解决方案
    阿姆达尔(Amdahl)定律是这样的:系统中对某部件采用某种更快执行方式,所获得的系统性能的改变程度,取决于这种方式被使用的频率,或所占总执行时间的比例。阿姆达尔定律定义了采用特定部件所取得的加速比。假定使用某种增强部件,计算机的性能就会得到提高,那么加速比就是下式所定义的比率:......
  • Redis之Lua语言入门
    前言Redis通过lua脚本来支持多条语句的原子性。Linux下安装#下载压缩包curl-R-Ohttp://www.lua.org/ftp/lua-5.4.3.tar.gz#解压tar-zxvflua-5.4.3.tar.gz#进入解压目录cdlua-5.4.3#编译makelinuxtest#安装,此步骤也可以省略makeinstall运行my......
  • Redis
    一、简介    NoSql的一种。性能优越,支持每秒十几万次的读写操作。性能远超数据库,还支持集群、分布式、主从同步等。还支持一定的事务能力。保证了高并发场景下的数据安全和一致性。二、Redis与Memcache的区别    1、Redis支持更丰富额度数据类型(支持更复杂的应......
  • 探索Navicat Premium 16:卓越的数据库管理软件解决方案 mac+win版
    在当今的数据驱动时代,一款高效、便捷的数据库管理软件对于企业、机构以及个人用户来说至关重要。NavicatPremium16,作为一款备受赞誉的数据库管理软件,正在满足这一需求,以其独特的功能和优势吸引着广大用户。→→↓↓载NavicatPremium16mac/win版一、NavicatPremium16的核......
  • 前端显示数据库中的换行文本:HTML和CSS解决方案
    在项目中经常会出现要显示数据库中的大段文本内容,如说明或备注等信息,当其中存储有换行符的时候,前端通常会忽略这个换行,直接在一行显示,那么怎么解决呢?解决方案一:使用HTML<br>标签HTML的<br>标签是一种简单而直观的方法,它可以将文本中的换行符正确地呈现在浏览器中。示例代码......
  • pbjs 无法编码 bytes 类型数据问题的解决方案
    问题背景之前写过一篇《使用脚本收发protobuf协议数据》,通过pbjs命令可以将protobuf二进制数据转换为json:>pbjsmsg.proto--decodeProbeIpv6Response<response.bin{"selfAddr":{"addrV6":"2409:8900:7900:8f0d:ecd9:4aee:aa3:7ad","port......
  • 关于JWT Token 自动续期的解决方案
    前言在前后端分离的开发模式下,前端用户登录成功后后端服务会给用户颁发一个jwttoken。前端(如vue)在接收到jwttoken后会将token存储到LocalStorage中。后续每次请求都会将此token放在请求头中传递到后端服务,后端服务会有一个过滤器对token进行拦截校验,校验token是否过期,如果t......
  • Maven 出现问题及解决方案
    问题描述相信使用过Maven的同学,偶尔会遇到莫名其妙的问题,就是pom.xml添加的依赖,老是显示红色的波浪线,而且无论怎么刷新都无法消除。原因分析出现这种情况多半是由于网络传输原因(网络不稳定),没有将Maven的依赖的jar包下载完整而导致。jar包下载出现不完整,本地jar包仓......