面试经典-Redis数据库的数据倾斜

一、定义

对于集群系统,一般缓存是分布式的,即不同节点负责一定范围的缓存数据。我们把缓存数据分散度不够,导致大量的缓存数据集中到了一台或者几台服务节点上,称为数据倾斜。一般来说数据倾斜是由于负载均衡实施的效果不好引起的。

二、危害

如果发生了数据倾斜,那么就会有某一台机器或几台保存了大量数据。轻则造成性能下降,处理请求速度骤降。重则造成Redis服务器崩溃,缓存服务不可用,将性能影响范围扩散到DB层,对后端服务造成不可估量的后果。

三、写入倾斜

1、bigkey导致倾斜

bigkey指的是某个 Redis 实例上保存了一个很大的 value (String 类型)或者是大量的集合元素(集合类型)的 key ,这个 key 就被称之为 bigkey ,而bigkey这种情况会导致集群中的某个实例的数据量很大,内存资源消耗也相应增加。

应对方案

在业务层生成数据时,要尽量避免把过多的数据保存在同一个键值对中。如果 bigkey 正好是集合类型,还有一个方法,就是把 bigkey 拆分成很多个小的集合类型数据,分散保存在不同的实例上。

2、Slot分配不均导致倾斜

介绍一下slot,slot全称HashSlot(哈希槽),类似于数据分区,每个key都会根据Hash算法计算出它应该属于哪个哈希槽,最终落到那个哈希槽中。而 Redis Cluster 就是采用哈希槽的方式来处理数据和实例间的映射关系。事实上,在 Redis Cluster 分片集群中一共有16384 个 Slot。 这里的Hash算法市面上的方式一般是先计算hash值,然后将计算结果对slot个数取模,最终确定落到哪个slot上。而计算hash值的算法有很多,常用的像CRC16、CRC64、sha1等等 运维在构建切片集群时候,需要手动分配哈希槽,并且把16384 个槽都分配完,否则 Redis 集群无法正常工作。由于是手动分配,则可能会导致部分实例所分配的slot过多,导致数据倾斜。

应对方案

使用CLUSTER SLOTS 命令来查看slot分配情况,使用CLUSTER SETSLOT,CLUSTER GETKEYSINSLOT,MIGRATE这三个命令来进行slot数据的迁移,具体内容不再这里细说,感兴趣的同学可以自行学习一下。

3、Hash Tag导致倾斜

Hash Tag 定义 :指当一个key包含 {} 的时候,就不对整个key做hash,而仅对 {} 包括的字符串做hash。假设hash算法为sha1。

对user:{user1}:ids和user:{user1}:tweets,其hash值都等同于sha1(user1)。

也就是说,如果不同 key 的 Hash Tag 内容都是一样的,那么,这些 key 对应的数据会被映射到同一个 Slot 中,同时会被分配到同一个实例上。

所以,如果不合理使用Hash Tag,会导致大量的数据可能被集中到一个实例上发生数据倾斜,集群中的负载不均衡。

应对方案

按照需求合理使用Hash Tag,甚至可以考量是否需要用到Hash Tag。

四、读取倾斜(热key)

一般来说,读取倾斜大多数都是热key问题导致的。如图所示,虽然每个集群实例上的数据量相差并没有很大,但是如果其中某个实例上的数据是热点数据,那台实例就会被访问得非常频繁。

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

在日常工作中一些突发的事件,例如:双十一期间某些热门商品在进行降价促销或秒杀时,这时某一件商品会被数万次点击浏览或者购买,会形成一个较大的需求量,这种情况下就很容易造成热点问题。

同理,被大量浏览的热点数据、明星直播等,这些典型的读多写少的场景也会产生热点问题。

危害:请求分片集中,超过单 Server 的性能极限。

在服务端读数据访问Redis时,往往会对请求key进行分片计算,此时中会将请求打到某一台 Server 上,如果热点过于集中,热点 Key 的缓存过多,访问量超过 Server 极限时,就会出现缓存分片服务被打垮现象的产生。当缓存服务崩溃后,此时再有请求产生,就会打到DB 上,这也就是我们常说的缓存穿透,如果没有合理的解决,数据库又没有扛住大量的穿透请求,则会进一步导致数据库雪崩现象。造成所有连接此数据库的系统服务不可用,上下游调用链中断,产生不可估量的后果。

五、热key解决方案

1、拆分热key

拆分热key,指的是把热点数据拆分成多份,在每份数据副本的 key 中增加一个随机后缀,让它和其它副本数据不会被映射到同一个 Slot 中。这里相当于把一份数据复制到多个实例上,通过Hash算法实现一个简陋的负载均衡。同样的,在读取的时候也要增加随机后缀,将对一个实例的读取压力,均摊到多个实例上。

例如:我们在放入缓存时就将对应业务的缓存key拆分成多个不同的key。如下图所示,在写入缓存的过程中,我们首先将key拆成N份,比如某个请求进来的key名字叫做"hot_key",那我们就可以把它拆成“hot_key_001”、“hot_key_002”、“hot_key_003”、“hot_key_004”…,当然了,每次更新和新增时都要记得去改动这N个key,这就是拆key。
对于Service端来讲,我们要尽可能的将访问流量分流的足够的均匀。 如何给即将访问的热key上合理的加入后缀?说一下市面上常用的方案,根据本机的ip或mac地址做hash,之后的值与拆key的数量做取余,最终决定拼接成什么样的key后缀,从而打到哪台机器上。当然也有其他的解决方案,比如在服务启动时的一个随机数对拆key的数量做取余。

public boolean getRandomHotKey(String hotKey,int count) {int random = new Random().nextInt(count);randomKey = hotKey + "_" + random;Object data = redis.get(randomKey);if (data == null){data = getFromDB(); redis.set(randomKey,expireTime + random);}}

2、多级缓存+动态计算自动发现热点缓存

该方案主要是通过主动发现热点并对其进行本地缓存来解决热点 Key 的问题。对,你没有听错,就是在缓存上再架设一层缓存。具体来说,就是在 Proxy上增加本地缓存,本地缓存采用LRU算法来缓存热点数据,后端节点增加热点数据计算模块来返回热点数据。当然了,Client会访问SLB,并且通过SLB将各种请求分发至Proxy中,Proxy会按照基于路由的方式将请求转发至Redis中。

Proxy 架构的主要有以下优点:

  • Proxy 本地缓存热点,读能力可水平扩展
  • DB 节点定时计算热点数据集合
  • DB 反馈 Proxy 热点数据
  • 对客户端完全透明,不需做任何兼容

六、热点数据的发现与存储

对于热点数据的发现,首先会在一个周期内对 Key 进行请求统计,在达到请求量级后会对热点 Key 进行热点定位,并将所有的热点 Key 放入一个小的 LRU 链表内,在通过 Proxy 请求进行访问时,若 Redis 发现待访点是一个热点,就会进入一个反馈阶段,同时对该数据进行标记。

可以使用一个etcd或者zk集群来存储反馈的热点数据,然后本地所有节点监听该热点数据,进而加载到本地JVM缓存中。

在热点 Key 的处理上主要分为写入跟读取两种形式,在数据写入过程当 SLB 收到数据 Key1 并将其通过某一个 Proxy 写入一个 Redis,完成数据的写入。

假若经过后端热点模块计算发现 Key1 成为热点 key 后, Proxy 会将该热点进行本地缓存,当下次客户端再进行访问 Key1 时,则可以不读取 Redis,直接从 Proxy 返回数据。

注意:由于 Proxy 是可以水平扩充的,因此可以任意增强热点数据的访问能力。

七、JD开源hotKey

上述的缓存倾斜解决思路,目前较为成熟解决方案是京东开源的项目HotKey,它拥有自动探测热Key、分布式一致性缓存的设计。原理就是在Client端做洞察;然后上报对应Hotkey,Server端检测到后,将对应Hotkey下发到对应服务端做本地缓存,并且能保证本地缓存和远程缓存的一致性。

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

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

相关文章

K8S调度下的ingress-controller集群的实现以及nginx配置

# 22、K8S调度下的ingress-controller集群的实现以及nginx配置 目标: 1. 实现ingress-controller的集群部署 实现方法: 1. 为ingress-controller 规划两个节点 2.将这两个节点 打上自定义的 label 3.修改yaml文件,并重新创建 ingress-co…

签约棒球自由球员算法设计

签约棒球自由球员算法设计 1. 问题描述2. 算法设计2.1 动态规划2.2 状态转移方程2.3 初始化2.4 最终结果 3. 算法实现3.1 伪代码3.2 C代码示例 1. 问题描述 假设你是一支棒球大联盟球队的总经理。在赛季休季期间,你需要签入一些自由球员。球队老板给你的预算为 X美…

攻防世界fileclude题解

攻防世界fileclude题解 ​​ 题目要求file1和file2参数不能为空 且file2这个文件内容值为hello ctf,用php://input 然后POST体内输入hello ctf即可满足这个if条件 满足这个条件后就会包含file1变量所指定的那个文件。用php伪协议来跨目录包含一下flag.php文件就可以…

人工智能培训老师叶梓:如何通过Prompt优化提升GPT-4性能

在人工智能领域,尤其是自然语言处理(NLP)中,Prompt工程是一种通过精心设计的提示(prompt)来引导模型生成期望输出的技术。最近,微软的研究团队通过Prompt优化策略,在医疗领域取得了显…

Redis系列1:深刻理解高性能Redis的本质

1 背景 分布式系统绕不开的核心之一的就是数据缓存,有了缓存的支撑,系统的整体吞吐量会有很大的提升。通过使用缓存,我们把频繁查询的数据由磁盘调度到缓存中,保证数据的高效率读写。 当然,除了在内存内运行还远远不够…

K3S 证书有效期和续签问题

本文使用k3s版本:k3s version v1.24.17k3s1 (026bb0ec) 默认安装情况下,ca证书有效期是10年,普通证书有效期是1年。 普通证书 k3s官网描述:K3s 客户端和服务器证书自颁发日起 365 天内有效。每次启动 K3s 时,已过期或…

linux 云计算平台基本环境(知识准备篇)

为了更多的了解云计算平台,结合云计算和linux的知识写了一篇云计算的介绍和汇总。 文章目录 前言1. centos的软件管理1.1 yum软件包管理1.1.1 yum命令语法:1.1.2 安装软件包的步骤1.1.3 yum源 2. 主机名管理与域名解析3. centos的防火墙管理4. openstack…

java锁介绍

乐观锁 乐观地认为并发访问不会造成数据冲突,只在更新时检查是否有冲突。乐观锁和CAS的关系可以用“乐观锁是一种思想,CAS是一种具体的实现”来理解。 当使用CAS操作修改数据时,如果版本号不匹配或者其他线程已经修改了要操作的数据&#x…

面试题集中营—分布式共识算法

分布式共识算法目标 分布式主要就是为了解决单点故障。一开始只有一个服务节点提供服务,如下图所示。那么如果服务节点挂了,对不起等着吧。 为了服务的高可用性,我们一般都会多引入几个副节点当备份,当服务节点挂了,就…

记一次Mac(M1)交叉编译Windows系统的过程

做了一个导出文件项目来实践学习GO的成果,开发完成后,在本地调试环境一切正常,打包到Windows测试出现了报错Error: Binary was compiled with CGO_ENABLED0, go-sqlite3 requires cgo to work. This is a stub。后研究得知,gorm的…

如何逃过极域的管控

本文由Jzwalliser原创,发布在CSDN平台上,遵循CC 4.0 BY-SA协议。 因此,若需转载/引用本文,请注明作者并附原文链接,且禁止删除/修改本段文字。 违者必究,谢谢配合。 个人主页:blog.csdn.net/jzw…

【Java框架】Spring框架(四)——Spring中的Bean的创建与生命周期

目录 SpringBean的创建步骤后置处理器(PostProcessor)BeanFactoryPostProcessorBeanPostProcessorInstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationpostProcessAfterInstantiationpostProcessProperties SmartInstantiationAwareBeanPostProcessordetermine…

医疗大模型产品设计

医疗领域的大型模型可以涵盖许多功能点,以提供全面的医疗支持和解决方案。以下是一些可能的功能点设计: 1. **疾病诊断与预测**:利用机器学习算法和医疗数据对患者的症状进行诊断和预测,帮助医生提供更准确的诊断和治疗建议。 2…

如何采集opc服务器数据上传云端

为了进一步提高生产效率,生产制造的不断朝着智能化发展和升级,传统的自动化生产系统已经不能满足需求。传统的SCADA系统一般是用于现场的数据采集与控制,但是本地控制已经无法满足整个工厂系统智能化数字化的需求,智能化数字化是需…

呼叫系统的技术实现原理和运作流程,ai智能系统,呼叫中心外呼软交换部署

呼叫系统的技术实现原理和运作流程可以涉及多个组成部分,包括硬件设备、软件系统和通信协议。以下是一般情况下呼叫系统的技术实现原理和运作流程的概述: 硬件设备: 服务器:用于承载呼叫系统的核心软件和数据库。电话交换机&#…

《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)

1.简介 前面宏哥一连几篇介绍如何通过开源jar包Log4j.jar、log4j2.jar和logback实现日志文件输出,Log4j和logback确实很强大,能生成三种日志文件,一种是保存到磁盘的日志文件,一种是控制台输出的日志,还有一种是HTML格…

Docker 镜像仓库常见命令

Docker Registry (镜像仓库) 常用命令 docker login 功能:登录到一个 Docker 镜像仓库,如果没有指定镜像仓库的地址,默认就是官方的 Docker Hub 仓库。 语法: docker login [options] [server]选项: -u:登…

字母加密(C语言)

一、题目; 为使电文保密,往往按一定规律将其转换成密码,收报人再按约定的规律将其译回原文。例如,可以按以下规律将电文变成密码:将字母A变成字母E,a变成e,即变成其后的第4个字母,W…

<script>和<script setup>的区别

在Vue 3中&#xff0c;<script setup>是Composition API的一个语法糖&#xff0c;它提供了一种更简洁的方式来编写组件逻辑。使用<script setup>&#xff0c;您可以在组件外部直接导入或定义方法和响应式数据&#xff0c;而不需要在setup()函数内部进行。 <scr…

iframe嵌套页面 拒绝访问 X-Frame-Options配置

iframe嵌套页面 拒绝访问 X-Frame-Options配置 iframe拒绝访问 X-Frame-Options: deny X-Frame-Options: sameorigin X-Frame-Options: allow-from https://example.com/deny 表示该页面不允许在 frame 中展示&#xff0c;即便是在相同域名的页面中嵌套也不允许。 sameorigi…