Redis--14--BigKey 和 热点Key

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • BigKey
    • 1.什么是bigkey
    • 2.bigkey的危害
    • 3.发现bigkey
          • scan
    • 4.解决bigkey
  • 什么是热点Key?该如何解决
    • 1. 产生原因和危害
        • 原因
        • 危害
    • 2.发现热点key
        • 预估发现
        • 客户端发现
        • Redis发现
          • monitor命令
          • hotkeys
        • 抓取TCP包发现
    • 3. 解决热点key
        • 使用二级缓存
        • key分散


BigKey

1.什么是bigkey

bigkey是指key对应的value所占的内存空间比较大,例如一个字符串类型的value可以最大存到512MB,一个列表类型的value最多可以存储23-1个元素。

如果按照数据结构来细分的话,一般分为字符串类型bigkey和非字符串类型bigkey。

字符串类型:体现在单个value值很大,一般认为超过10KB就是bigkey,但这个值和具体的OPS相关。

非字符串类型:哈希、列表、集合、有序集合,体现在元素个数过多。

bigkey无论是空间复杂度和时间复杂度都不太友好,下面我们将介绍它的危害。

2.bigkey的危害

bigkey的危害体现在三个方面:

  1. 内存空间不均匀.(平衡):例如在Redis Cluster中,bigkey 会造成节点的内存空间使用不均匀。

  2. 超时阻塞:由于Redis单线程的特性,操作bigkey比较耗时,也就意味着阻塞Redis可能性增大。

  3. 网络拥塞:每次获取bigkey产生的网络流量较大

假设一个bigkey为1MB,每秒访问量为1000,那么每秒产生1000MB 的流量,对于普通的千兆网卡(按照字节算是128MB/s)的服务器来说简直是灭顶之灾,而且一般服务器会采用单机多实例的方式来部署,也就是说一个bigkey可能会对其他实例造成影响,其后果不堪设想。

bigkey的存在并不是完全致命的:

如果这个bigkey存在但是几乎不被访问,那么只有内存空间不均匀的问题存在,相对于另外两个问题没有那么重要紧急,但是如果bigkey是一个热点key(频繁访问),那么其带来的危害不可想象,所以在实际开发和运维时一定要密切关注bigkey的存在。

3.发现bigkey

redis-cli --bigkeys可以命令统计bigkey的分布

image.png

但是在生产环境中,开发和运维人员更希望自己可以定义bigkey的大小,而且更希望找到真正的bigkey都有哪些,这样才可以去定位、解决、优化问题。

判断一个key是否为bigkey,只需要执行debug object key查看serializedlength属性即可,它表示 key对应的value序列化之后的字节数。

image.png

如果是要遍历多个,则尽量不要使用keys的命令,可以使用scan的命令来减少压力。

scan

Redis 从2.8版本后,提供了一个新的命令scan,它能有效的解决keys命令存在的问题。和keys命令执行时会遍历所有键不同,scan采用渐进式遍历的方式来解决 keys命令可能带来的阻塞问题,但是要真正实现keys的功能,需要执行多次scan。可以想象成只扫描一个字典中的一部分键,直到将字典中的所有键遍历完毕。scan的使用方法如下:

scan cursor [match pattern] [count number]

cursor :是必需参数,实际上cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值,直到游标值为0,表示遍历结束。

Match pattern :是可选参数,它的作用的是做模式的匹配,这点和keys的模式匹配很像。

Count number :是可选参数,它的作用是表明每次要遍历的键个数,默认值是10,此参数可以适当增大。

image.png

可以看到,第一次执行scan 0,返回结果分为两个部分:

第一个部分9就是下次scan需要的cursor

第二个部分是10个键。接下来继续

直到得到结果cursor变为0,说明所有的键已经被遍历过了。

除了scan 以外,Redis提供了面向哈希类型、集合类型、有序集合的扫描遍历命令,解决诸如hgetall、smembers、zrange可能产生的阻塞问题,对应的命令分别是hscan、sscan、zscan,它们的用法和scan基本类似,请自行参考Redis官网。

image.png

渐进式遍历可以有效的解决keys命令可能产生的阻塞问题,但是scan并非完美无瑕,如果在scan 的过程中如果有键的变化(增加、删除、修改),那么遍历效果可能会碰到如下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键,这些是我们在开发时需要考虑的。

如果键值个数比较多,scan + debug object会比较慢,可以利用Pipeline机制完成。对于元素个数较多的数据结构,debug object执行速度比较慢,存在阻塞Redis的可能,所以如果有从节点,可以考虑在从节点上执行。

4.解决bigkey

主要思路为拆分

对 big key 存储的数据 (big value)进行拆分,变成value1,value2… valueN等等。

  • 例如big value 是个大json 通过 mset 的方式,将这个 key的内容打散到各个实例中,
  • 或者一个hash,每个field代表一个具体属性,通过hget、hmget获取部分value,hset、hmset来更新部分属性。
  • 例如big value 是个大list,可以拆成将list拆成。= list_1, list_2, list3, …listN

其他数据类型同理。

什么是热点Key?该如何解决

在Redis中,访问频率高的key称为热点key。

1. 产生原因和危害

原因

热点问题产生的原因大致有以下两种:

用户消费的数据远大于生产的数据(热卖商品、热点新闻、热点评论、明星直播)。

在日常工作生活中一些突发的事件,例如:双十一期间某些热门商品的降价促销,当这其中的某一件商品被数万次点击浏览或者购买时,会形成一个较大的需求量,这种情况下就会造成热点问题。同理,被大量刊发、浏览的热点新闻、热点评论、明星直播等,这些典型的读多写少的场景也会产生热点问题。

请求分片集中,超过单Server的性能极限。在服务端读数据进行访问时,往往会对数据进行分片切分,此过程中会在某一主机Server上对相应的Key进行访问,当访问超过Server极限时,就会导致热点Key问题的产生。

危害

1、流量集中,达到物理网卡上限。

2、请求过多,缓存分片服务被打垮。

3、DB击穿,引起业务雪崩。

2.发现热点key

预估发现

针对业务提前预估出访问频繁的热点key,例如秒杀商品业务中,秒杀的商品都是热点key。

当然并非所有的业务都容易预估出热点key,可能出现漏掉或者预估错误的情况。

客户端发现

客户端其实是距离key"最近"的地方,因为Redis命令就是从客户端发出的,以Jedis为例,可以在核心命令入口,使用这个Google Guava中的AtomicLongMap进行记录,如下所示。

使用客户端进行热点key的统计非常容易实现,但是同时问题也非常多:

(1) 无法预知key的个数,存在内存泄露的危险。

(2) 对于客户端代码有侵入,各个语言的客户端都需要维护此逻辑,维护成本较高。

(3) 规模化汇总实现比较复杂。

Redis发现
monitor命令

monitor命令可以监控到Redis执行的所有命令,利用monitor的结果就可以统计出一段时间内的热点key排行榜,命令排行榜,客户端分布等数据。

image.png

Facebook开源的redis-faina正是利用上述原理使用Python语言实现的,例如下面获取最近10万条命令的热点key、热点命令、耗时分布等数据。为了减少网络开销以及加快输出缓冲区的消费速度,monitor尽可能在本机执行。

此种方法会有两个问题:

1、monitor命令在高并发条件下,内存暴增同时会影响Redis的性能,所以此种方法适合在短时间内使用。

2、只能统计一个Redis节点的热点key,对于Redis集群需要进行汇总统计。

可以参考的框架:Facebook开源的redis-faina正是利用上述原理使用Python语言实现的

hotkeys

Redis在4.0.3中为redis-cli提供了–hotkeys,用于找到热点key。

image.png

如果有错误,需要先把内存逐出策略设置为allkeys-lfu或者volatile-lfu,否则会返回错误。

image.png

image.png

但是如果键值较多,执行较慢,和热点的概念的有点背道而驰,同时热度定义的不够准确。

抓取TCP包发现

Redis客户端使用TCP协议与服务端进行交互,通信协议采用的是RESP。如果站在机器的角度,可以通过对机器上所有Redis端口的TCP数据包进行抓取完成热点key的统计

此种方法对于Redis客户端和服务端来说毫无侵入,是比较完美的方案,但是依然存在3个问题:

(1) 需要一定的开发成本

(2) 对于高流量的机器抓包,对机器网络可能会有干扰,同时抓包时候会有丢包的可能性。

(3) 维护成本过高。

对于成本问题,有一些开源方案实现了该功能,例如ELK(ElasticSearch Logstash Kibana)体系下的packetbeat[2] 插件,可以实现对Redis、MySQL等众多主流服务的数据包抓取、分析、报表展示

3. 解决热点key

发现热点key之后,需要对热点key进行处理。

使用二级缓存
  • 可以使用guava-cache或hcache,发现热点key之后,将这些热点key加载到JVM中作为本地缓存。访问这些key时直接从本地缓存获取即可,不会直接访问到redis层了,有效的保护了缓存服务器。
key分散
  • 将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。当通过热点key去查询数据时,通过某种hash算法随机选择一个子key,然后再去访问缓存机器,将热点分散到了多个子key上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/193943.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用RTOS时需要注意的几点内容

对许多嵌入式项目来说,系统设计师都倾向于选择实时操作系统(RTOS)。但RTOS总是必要的吗? 答案是取决于具体的应用,因此了解我们要达到什么目标是决定RTOS是必要的还是花瓶的关键。 一般来说,在采用非实时操作系统(non-RTOS)的任何场合&…

praseInt 和 逻辑或连用

这是做项目时遇到json文件转换 的一个小坑 将json 对象中的值 由字符串(数字字符串) 转换为 数值类型,如果是 转换失败 ,就返回 -1 这里的 parseInt 看起来非常简洁,但是存在一个小坑 transformedData[fieldsToCheck[i]] parseInt(origina…

Stable Diffusion AI绘画系列【11】:超萌的Q版手办萌宠系列

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

C语言memcpy,memmove的介绍及模拟实现

文章目录 每日一言memcpy介绍模拟实现 memmove介绍模拟实现思路代码 结语 每日一言 If you want to lift yourself up, lift up someone else. 如果你想振奋自己, 先振奋周遭的人。 memcpy 介绍 函数原型: void *memcpy(void *dest, const void *sr…

送女朋友一个猜数字小游戏,猜对了会显示爱心(给你心爱的他或她一个惊喜)

起因是我在学习C语言完成老师布置C语言写一个猜数字的作业,突发奇想,能不能在这个猜对了之后弹出一个不一样的页面,然后就试试看能不能实现。基本思路是这样的: 1:先写一个C语言的猜数字的小游戏,在我上个文…

StackGres 1.6 数据库平台工程功能介绍以及快速上手

StackGres 1.6 数据库平台工程功能 声明式 K8S CRs StackGres operator 完全由 Kubernetes 自定义资源管理。除了 kubectl 或任何其他 Kubernetes API 访问之外,不需要安装任何客户端或其他工具来管理 StackGres。您的请求由 CRD 的 spec 部分表示,任何 …

Redis 数据结构详解

分类 编程技术 Redis 数据类型分为:字符串类型、散列类型、列表类型、集合类型、有序集合类型。 Redis 这么火,它运行有多块?一台普通的笔记本电脑,可以在1秒钟内完成十万次的读写操作。 原子操作:最小的操作单位&a…

无懈可击的身份验证:深入了解JWT的工作原理

🎏:你只管努力,剩下的交给时间 🏠 :小破站 无懈可击的身份验证:深入了解JWT的工作原理 前言JWT的基础概念基本概念JWT的工作流程注意事项 JWT的工作原理生成令牌传输令牌验证令牌 JWT的安全性考量1. 使用强…

MySql下载和安装

MySql下载和安装 一、概述 MySQL是一个开放源代码的关系型数据库管理系统 ,由瑞典MySQL AB(创始人Michael Widenius)公 司1995年开发,迅速成为开源数据库的 No.1。 二、下载和安装 下载地址:https://dev.mysql.com…

Python编程技巧 – 迭代器(Iterator)

Python编程技巧 – 迭代器(Iterator) By JacksonML Iterator(迭代器)是Python语言的核心概念之一。它常常与装饰器和生成器一道被人们提及,也是所有Python书籍需要涉及的部分。 本文简要介绍迭代器的功能以及实际的案例,希望对广大读者和学生有所帮助。…

自然语言处理(NLP)技术-AI生成版

自然语言处理(NLP)是一种涵盖众多技术的交叉学科,旨在使计算机能够理解、生成和处理自然语言文本。它涉及语言学、计算机科学、统计学和人工智能等多个领域。下面将举例说明NLP技术在实际应用中的一些场景。 情感分析 情感分析是指使用NLP技…

Xshell会话文件解密获取密码

Xshell会话文件解密获取密码 开发了一个小工具用于获取已存储的xshell会话密码功能简介截图展示下载地址 开发了一个小工具用于获取已存储的xshell会话密码 在日常开发中,服务器太多,密码记不住。使用xshell管理服务器会话,记住密码&#xf…

Linux网络之连接跟踪 conntrack

一 Linux网络之连接跟踪 conntrack k8s 有关conntrack的分析 ① 什么是连接跟踪 netfilter连接跟踪 conntrack 详述 思考:连接跟踪模块会对哪些协议进行跟踪?TCP、UDP、ICMP、DCCP、SCTP、GRE ② 为什么需要连接跟踪 没有连接跟踪有很多问题是不好解决的&a…

WebGL笔记:js中矩阵库的使用

矩阵库 手写矩阵,其实很麻烦,可以将其模块化市面上已经有许多开源的矩阵库 比如《WebGL 编程指南》里的 cuon-matrix.jsthree.js 的 Matrix3 和 Matrix4 对象 three.js的 Matrix4 对象的用法 1 )核心代码 1.引入Matrix4对象 import { Mat…

Spring一些基础问题整理

备注:针对基本问题做一些基本的总结,不是详细解答! 1.Spring Boot与以前的Spring有什么区别? 具体可以见博客: 微服务架构具体实现工具框架:Spring Boot概览与核心原理 https://blog.csdn.net/xiaofeng103…

牛客在线编程(SQL大厂面试真题)

1.各个视频的平均完播率_牛客题霸_牛客网 ROP TABLE IF EXISTS tb_user_video_log, tb_video_info; CREATE TABLE tb_user_video_log (id INT PRIMARY KEY AUTO_INCREMENT COMMENT 自增ID,uid INT NOT NULL COMMENT 用户ID,video_id INT NOT NULL COMMENT 视频ID,start_time d…

最大乘积分解(动态规划)

相较于我上一题写的动态规划&#xff0c;这一题比较简单 代码如下&#xff1a; #include<stdio.h>int main(void) {long long n, max[101] {0, 1};scanf("%lld", &n);for(int i 1; i < n; i)max[i] i;for(int i 1; i < n; i)for(int j 1; j &…

springboot数据源配置

springboot数据源配置 数据层解决方案——持久化技术 内置持久化解决方案——jdbcTemplate 内置数据库 H2一般用于测试环境&#xff0c;配置profiels&#xff0c;只在开发阶段使用&#xff0c;让他在上线的时候不走这里就可以了 要使用内嵌的数据库H2,要先导入jar包

设置WPF启动画面

WPF启动时间比较长&#xff0c;总让人觉得程序好像没有启动起来&#xff0c;所以想设置一个启动画面 发现WPF设置启动画面竟然如此的简单 第一步将图片放置在主工程目录下&#xff0c;如下图 第二步 将图片生成属性设置为SplashScreen即可 第三步 启动项目你就看到效果了

java面经1day

String, StringBuffer,StringBuilder的区别 从俩方面开始下手 是否可变 是否安全 回答: String是final实现&#xff0c;其为不可变长&#xff0c;每次变长都会新增对象。而StringBuffer,StringBuilder他们的父类都是AbstractStringBuilder 然后安全&#xff1a;String因为…