网站网页设计屏幕尺寸,用asp.net做的网站模板,公司网站如何维护,八师石河子精神文明建设网站前序
还记得上次和同事一起去面试候选人时#xff0c;同事提了一个问题#xff1a;Redis的大key有什么危害#xff1f;当时候选人主要作答的角度是一个key的value较大时的情况#xff0c;比如#xff1a;
内存不均#xff1a;单value较大时#xff0c;可能会导致节点之…前序
还记得上次和同事一起去面试候选人时同事提了一个问题Redis的大key有什么危害当时候选人主要作答的角度是一个key的value较大时的情况比如
内存不均单value较大时可能会导致节点之间的内存使用不均匀间接地影响key的部分和负载不均匀阻塞请求redis为单线程单value较大读写需要较长的处理时间会阻塞后续的请求处理阻塞网络单value较大时会占用服务器网卡较多带宽可能会影响该服务器上的其他Redis实例或者应用。
虽说答的是挺好的但是我又随之产生了另一个疑惑如果redis的key较长时会产生什么样的影响呢查了很多文章说的都不是特别清楚。所以我决心探究一下这个问题。 我们需要知道Redis是如何存储key和value的 根结构为RedisServer其中包含RedisDB数据库。而RedisDB实际上是使用Dict字典结构对Redis中的kv进行存储的。这里的key即字符串value可以是string/hash/list/set/zset这五种对象之一。
Dict字典结构中存储数据的主题为DictHt即哈希表。而哈希表本质上是一个DictEntry哈希表节点的数组并且使用链表法解决哈希冲突问题关于哈希冲突的解决方法可以参考大佬的文章 解决哈希冲突的常用方法分析。
所以在这里实际存储时key和value都是存储在DictEntry中的。所以基本上来说大key和大value带来的内存不均和网络IO压力都是一致的只是key相较于value还多一个做hashcode和比较的过程链表中进行遍历比较key会有更多的内存相关开销。
结论
大key和大value的危害是一致的内存不均、阻塞请求、阻塞网络。key由于比value需要做更多的操作如hashcode、链表中比较等操作所以会比value更多一些内存相关开销。
我们需要知道Redis是如何存储key和value的 根结构为RedisServer其中包含RedisDB数据库。而RedisDB实际上是使用Dict字典结构对Redis中的kv进行存储的。这里的key即字符串value可以是string/hash/list/set/zset这五种对象之一。
Redis 大key如何处理
Redis使用过程中经常会有各种大key的情况 比如 单个简单的key存储的value很大 hash setzsetlist 中存储过多的元素以万为单位 由于redis是单线程运行的如果一次操作的value很大会对整个redis的响应时间造成负面影响所以业务上能拆则拆下面举几个典型的分拆方案。
业务场景
即通过hash的方式来存储每一天用户订单次数。那么key order_20200102, field order_id, value 10。那么如果一天有百万千万甚至上亿订单的时候key后面的值是很多存储空间也很大造成所谓的大key。
大key的风险 读写大key会导致超时严重甚至阻塞服务。 如果删除大keyDEL命令可能阻塞Redis进程数十秒使得其他请求阻塞对应用程序和Redis集群可用性造成严重的影响。
redis使用会出现大key的场景
单个简单key的存储的value过大hash、set、zset、list中存储过多的元素。
解决问题
单个简单key的存储的value过大的解决方案
将大key拆分成对个key-value使用multiGet方法获得值这样的拆分主要是为了减少单台操作的压力而是将压力平摊到集群各个实例中降低单台机器的IO操作。
hash、set、zset、list中存储过多的元素的解决方案 1).类似于第一种场景使用第一种方案拆分; 2).以hash为例将原先的hget、hset方法改成加入固定一个hash桶的数量为10000先计算field的hash值模取10000确定该field在哪一个key上。
将大key进行分割为了均匀分割可以对field进行hash并通过质数N取余将余数加到key上面我们取质数N为997。
那么新的key则可以设置为
newKey order_20200102_String.valueOf( Math.abs(order_id.hashcode() % 997) ) field order_id value 10 hset (newKey, field, value) ; hget(newKey, field)
大value数据是什么会有怎样的问题
当String类型的数据10Klist、hash、set、sort set中元素个数超过1000时就可以被称为大value当超过100K或集合元素个数超过10000时可以被称为是超大value。大value最直接的影响就是有可能造成机器内存不足就是数据倾斜同时因为redis数据处理是单线程的当value过大时处理起来响应时间也会变慢。 常见的例子有参与人数很多的盖楼活动或者很活跃的群聊消息列表等
怎么处理Redis大value
大value的处理方式还是结合业务对其进行拆分将其数据分布在各个redis节点中将操作压力平摊开防止对单个实例IO或内存影响过大。
简单说一下 热点数据和大value的拆分如果它是一个list、 set集合类型比如原来的 为key valuevalue为list为拆为 list1 、list2、list3那么新的key为 keyhash(list1)%10000 得到新的key再对对应数据value进行set或get操作
如果是一个对象的json字符串可以考虑将该对象的不同属性映射到不同hash槽从而分布在不同redis节点中或者将不同属性拆分利用hash结构进行存储从而每次处理时仅获取一部分数据