美团大规模KV存储挑战与架构实践--图文分析

美团大规模KV存储挑战与架构实践–图文分析

原作者:美团技术团队

原文链接:https://tech.meituan.com/2024/03/15/kv-squirrel-cellar.html

1 美团 KV 存储发展历程

第一代:使用Memcached

img

什么是一致性哈希?

哈希:hash,可以通过Key存储Value,也可以通过Key取得Value. 简单说就是Value存储的位置是通过Hash算法计算出来的

(实现,如HashMap)。

随着客户端发起的请求数量越来越高,为了加快响应速度,在客户端与数据库之间增加了缓存层,把数据库中的热点数据存入缓存,这样客户端可以直接从缓存取得热点数据,无需每次都访问数据库,即加快了响应时间,又降低了数据库层的压力。

在这里插入图片描述

hash取模运算

随着业务规模不断扩大,数据量也跟着增大,缓存数量飙增,这样就需要考据搭建缓存集群,把大量的缓存分散到多台缓存服务器中进行存储

取模算法hash(key)%N,即:对缓存数据的key进行hash运算后取模,N是机器的数量;运算后的结果映射对应集群中的节点。具体如下图所示:

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=F%3A%2FBaiduNetdiskDownload%2FDevOps%E7%AC%94%E8%AE%B0-MarkDown%E5%8E%9F%E7%89%88%2FDevOps%2FPictures%2Fimage-20240607182832191.png&pos_id=img-VgEmEbVn-1717929022871在这里插入图片描述

问题,如上图,三个node,所以N为3,此时key通过公式hash(key)%3存入指定节点,之后扩容成4个节点,N为4,公式也变成了hash(key)%4,之前n为3的值取不出来了。

一致性哈希

一致性哈希算法将整个哈希值空间映射成一个虚拟的圆环。整个哈希空间的取值范围为02^32-1,按顺时针方向开始从0232-1排列,最后的节点232-1在0开始位置重合,形成一个虚拟的圆环。

对服务器IP地址进行哈希计算,哈希计算后的结果对232取模,结果一定是一个0到232-1之间的整数。最后将这个整数映射在哈希环上,整数的值就代表了一个服务器节点的在哈希环上的位置。即:hash(服务器ip)% 2^32。

当服务器接收到数据请求时,首先需要计算请求Key的哈希值;然后将计算的哈希值映射到哈希环上的具体位置;接下来,从这个位置沿着哈希环顺时针查找,遇到的第一个节点就是key对应的节点

在这里插入图片描述

服务器扩容

D数据本来应该会落在node1中,由于扩容节点node4,D数据落在了node4中

在这里插入图片描述

服务器缩容

node4节点宕机或者移除后,数据D继续顺时针找到node1节点存储。

在这里插入图片描述

数据倾斜与虚拟节点

数据abcd都落在node1中,node2,node3没事干,node1压力山大。

在这里插入图片描述

解决方案,使用虚拟节点

hash(服务器ip)% 2^32 变更为 hash(服务器ip+随机数)% 2^32

例如:Hash(“114.211.11.141”);

变更为:

Hash(“114.211.11.141#1”);

Hash(“114.211.11.141#2”);

注意,虚拟节点只是帮助真实节点扩大获取数据的范围,并不会保存数据,所获取的数据最终还是要存储在真实节点中。

在这里插入图片描述

memcached的问题

传统的memcached是不支持内存数据的持久化操作,因为它将数据存储在内存当中的,当服务器宕机重启,数据会丢失。

不适合存储1M以上的数据。

适用场景:缓存一些很小但是被频繁访问的,即便你丢失也不会影响系统以及系统业务正常执行的数据。如:新闻热点缓存,即便日后数据丢失,热点已经降温,数据不重要。

第二代:使用Redis

img

优点:支持持久化,服务宕机后数据不会丢失,可以通过哨兵机制进行故障恢复(failover)

宕机数据不丢失策略

RDB每5分钟一次生成快照,AOF每秒通过一个后台的线程持久化操作,最多丢一秒的数据。单独用RDB会丢失很多数据,单独用AOF数据恢复没RDB快,所以解决方案是第一时间用RDB恢复,然后AOF做数据补全

缺点:扩缩容丢失数据。

一致性hash只是用来减少扩缩容时数据迁移量,无法对整个集群进行统一管理(缺乏类似提供心跳检测等服务的中心管理层,数据迁徙的时候,节点无法感知整个集群的状态,数据从A节点中迁徙出去了,但接收的B节点处于网络卡顿状态导致无法接受全部迁徙数据等问题)

第三代:阿里巴巴的 Tair

Tair 开源版本的架构主要是三部分:最下边的是存储节点,存储节点会上报心跳到它的中心节点,中心节点内部设有两个配置管理节点,会监控所有的存储节点。如果有任何存储节点宕机或者扩容之类的行为,它会做集群拓扑的重新构建,拥有数据迁移机制来保证数据的完整性。

img

缺点:

1.中心节点是高可用的,但是会发生脑裂。

脑裂:选举bug,多个leader,多个从节点被选举成了主节点,不干从节点的活了导致数据丢失。

2.和redis的数据类型不兼容

第四代:

基于Tair的Cellar ,基于Redis Cluster的Squirrel

img

这两个存储其实都是 KV 存储领域的解决方案。实际应用上,如果业务的数据量小,对延迟敏感,建议用 Squirrel ;如果数据量大,对延迟不是特别敏感,我们建议用成本更低的 Cellar 。

2 大规模 KV 存储的挑战

1.集群的规模越来越大,节点增加困难(比如带宽饱和)

2.部分业务场景带来的木桶效应以及长尾延迟(例如:mget

3.如何保证集群可用性不会随着规模的变大而有所降低

名词解释:

mget:

可以一次性读取redis中多个值:

redis 127.0.0.1:6379> SET key1 "hello"
OK
redis 127.0.0.1:6379> SET key2 "world"
OK
redis 127.0.0.1:6379> MGET key1 key2 someOtherKey
1) "Hello"
2) "World"
3) (nil)

长尾效应:

红色区域量大响应时间短,黄色区域量小耗时长。比如使用了上面的mget批量读取就有大概率造成此类问题。

在这里插入图片描述

3 内存 KV Squirrel 挑战和架构实践

img

上图是美团的 Squirrel 架构。中间部分跟 Redis 社区集群是一致的。它有主从的结构,Redis 实例之间通过 Gossip 协议去通信。右边添加了一个集群调度平台管理整个集群,把管理结果作为元数据更新到 ZooKeeper。我们的客户端会订阅 ZooKeeper 上的元数据变更,实时获取到集群的拓扑状态,直接对 Redis 集群节点进行读写操作。

难点补充:

Gossip 原理:

节点1更新数据,告知了相邻节点2,4,7;相邻节点再去告诉自己的相邻节点。

在这里插入图片描述

优点:去中心化(多个缓存中间件采用,区块链采用)

缺点:当节点特别多的时候消耗性能,节点更新后相邻节点可能会重复更新,非常损耗性能。

3.2 Gossip优化

为了解决上述的扩展性问题,我们对社区的 Gossip 方案进行了优化。首先针对 Gossip 传输的消息,我们通过 Merkle Tree 对其做了一个摘要,把集群 Gossip 通信的数据量减少了90%以上。服务端节点仅需要对比 Hash 值即可判断元数据是否有更新对于存在更新的情况也能快速判断出更新的部分并仅对此部分元数据进行获取、更新,大幅降低了 Gossip 消息处理的资源消耗

原文中的默克尔树(Merkle Tree)

img

补全图:

在这里插入图片描述

类似平衡二叉树,通过对比上层节点的hash是否一致即可得知是否已经更新,可双向判断:判断更新以及找到更新位置。难度:之前为O(N)现在为O Log(N)

3.3 Squirrel 垂直扩展的挑战

节点过大,Fork生成RDB影响性能。(执行RDB的主要三种场景:save,bgsave,主从复制)

Redis备份数据做持久化操作有AOF和RDB两种,为了不影响主线程,会通过内置的Fork系统启动一个子线程执行,但Fork子进程过程中如果节点过大,依然会占用大量资源导致阻塞。可以简单理解为,Redis会在数据增长到一定程度或者执行主从复制的时候,备份自己的数据,生成一个RDB文件(快照),保存当时Redis中的所有数据用于以后的数据恢复,但这个RDB文件尽管通过子线程生成,但每次生成一个大文件在保存还是耗费资源。

3.4 forkless RDB

解决方案就是采用复制队列的方式,由原来的一次拷贝一个大的(越大越慢,会造成阻塞),改成一个key一个key的往队列拷贝生成的方式。

拷贝期间数据变化怎么办:把变化过程也拷贝到队列里。

拷贝期间发生rehash导致里面的key顺序重排怎么办:暂停rehash.

img

这里的rehash 又是什么意思呢?

redis中有一个全局Hash表(HashTable),表里有一个一个的哈希桶(Bucket),桶里装着Entry(存放key,value的指针),数据量特别大的时候会发生Hash冲突行成链表,如下图的Bucket2.

在这里插入图片描述

解决方案:rehash,扩容。

创建一个比原来还大的HashTable,向其中传递原来HashTable的数据,并对存在Hash冲突的地方进行哈希桶的重新分配。

在这里插入图片描述

这就是为什么美团的forkless RDB执行的时候需要停止rehash了,因为要一个一个的拷贝key,并且有游标指向key的位置,但rehash发生后,key的位置就会发生变化。

3.5 工作多线程

原生Redis:IO多线程,工作线程为单线程。

修改为:IO多线程,工作线程也是多线程,通过加锁解决线程安全问题。

img

3.6 Squirrel可用性的挑战

只有两个机房,A选B,B选A,选不出主或者造成脑裂,必须部署3机房,但通常两个副本足够用了,没必要部署3个副本。

3.7 两机房容灾

img

参考 Google Spanner(可伸缩分布式数据库)的见证者投票方式。

简单说就是:

还是三个机房,但保存两个副本就行了,另外一个只投票,不保存副本。

3.8 跨地域容灾

img

3.9 双向同步冲突自动解决

img

简单说就是谁的时间新就保存谁的。

服务器发生了时间回退怎么办:保存数据时使用时间戳,发生回退了依然使用时间戳来防止数据跟着回退。

两个值的更新时间一样怎么办:比较集群ID,保存集群ID大的那一个。(个人理解类似足球比赛积分净胜球等都相同,靠抽签决定谁进入下一轮)

由复制操作改为复制变更后的数据:只考虑操作后的数据,而不是复制操作。

链图片转存中…(img-qMRzytbP-1717929022879)]

3.9 双向同步冲突自动解决

[外链图片转存中…(img-CDljEhDy-1717929022880)]

简单说就是谁的时间新就保存谁的。

服务器发生了时间回退怎么办:保存数据时使用时间戳,发生回退了依然使用时间戳来防止数据跟着回退。

两个值的更新时间一样怎么办:比较集群ID,保存集群ID大的那一个。(个人理解类似足球比赛积分净胜球等都相同,靠抽签决定谁进入下一轮)

由复制操作改为复制变更后的数据:只考虑操作后的数据,而不是复制操作。

保存最近删除的 Key:简单说就是B集群同步复制A集群数据的时候,对于复制过来一个已经不存在的数据,先不要创建,而是到删除库中看一看这个数据是不是已经被删除了。

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

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

相关文章

kafka如何保证消息不丢失

Kafka发送消息是异步发送的,所以我们不知道消息是否发送成功,所以会可能造成消息丢失。而且Kafka架构是由生产者-服务器端-消费者三种组成部分构成的。要保证消息不丢失,那么主要有三种解决方法。 生产者(producer)端处理 生产者默认发送消息…

AI炒股:用Kimi获取美股的历史成交价格并画出股价走势图

在Kimi中输入提示词: 你是一个Python编程专家,要完成一个编写Python脚本的任务,具体步骤如下: 用akshare库获取谷歌(股票代码:105.GOOG)、亚马逊(股票代码:105.AMZN )、苹果(股票代码:105.AAP…

明天15点!如何打好重保预防针:迎战HVV经验分享

在当今数字化时代,网络攻击日益猖獗,各行各业面临的网络安全威胁不断升级。从钓鱼邮件到复杂的APT攻击,网络犯罪分子的手法层出不穷,给各行各业的信息安全带来了前所未有的挑战。 在这样的背景下,"HVV行动"应…

6月7号作业

1, 搭建一个货币的场景,创建一个名为 RMB 的类,该类具有整型私有成员变量 yuan(元)、jiao(角)和 fen(分),并且具有以下功能: (1)重载算术运算符…

2024年电子工程与自动化技术国际会议(ICEEAT 2024)

2024 International Conference on Electronic Engineering and Automation Technology 【1】大会信息 会议简称:ICEEAT 2024 大会地点:中国西安 审稿通知:投稿后2-3日内通知 【2】会议简介 2024年电子工程与自动化技术国际会议是聚焦电子…

OrangePi AIpro小试牛刀-目标检测(YoloV5s)

非常高兴参加本次香橙派AI Pro,香橙派联合华为昇腾打造的一款AI推理开发板评测活动,以前使用树莓派Raspberry Pi4B 8G版本,这次有幸使用国产嵌入式开发板。 一窥芳容 这款开发板搭载的芯片是和华为昇腾的Atlas 200I DK A2同款的处理器&#…

Vue3中的常见组件通信之$attrs

Vue3中的常见组件通信之$attrs 概述 ​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refs、parent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。 组件关系传递方式父传子1. props2. v-model3. $re…

[Linux]内网穿透nps

文章目录 基础文件下载项目地址下载地址 客户端安装解压文件客户端启动客户端注册到linux系统服务客户端注册到windows系统服务windows bat 一键管理员注册windows bat 一键管理员取消 基础文件下载 项目地址 https://github.com/ehang-io/nps 下载地址 Releases ehang-io…

微服务第二轮

学习文档 背景 由于每个微服务都有不同的地址或端口,入口不同 请求不同数据时要访问不同的入口,需要维护多个入口地址,麻烦 前端无法调用nacos,无法实时更新服务列表 单体架构时我们只需要完成一次用户登录、身份校验&#xff…

想在VBA软件中做个登录验证会员授权,用什么云服务器好?

想在VBA中做个登录验证会员授权,用什么服务器好? 腾讯云99起,百度云50元起,不过也不知道到底是一整个虚拟机服务器, 装了WIN2012系统的,还是只是一个虚拟网站只给你一个文件夹可以上传PHP,ASP网页后台。 价…

6、组件通信详解(父子、兄弟、祖孙)

一、父传子 1、props 用法: (1)父组件用 props绑定数据,表示为 v-bind:props"数据" (v-bind:简写为 : ,props可以任意命名) (2)子组件用 defineProps([props&…

Java 编译报错:找不到符号? 手把手教你排查解决!

Java 编译报错:找不到符号? 手把手教你排查解决! 在 Java 开发过程中,我们经常会遇到编译器抛出 "找不到符号" 错误。这个错误提示意味着编译器无法在它所理解的范围内找到你所引用的类、变量或方法。这篇文章将带你一步…

一文学习yolov5 实例分割:从训练到部署

一文学习yolov5 实例分割:从训练到部署 1.模型介绍1.1 YOLOv5结构1.2 YOLOv5 推理时间 2.构建数据集2.1 使用labelme标注数据集2.2 生成coco格式label2.3 coco格式转yolo格式 3.训练3.1 整理数据集3.2 修改配置文件3.3 执行代码进行训练 4.使用OpenCV进行c部署参考文…

手写kNN算法的实现-用欧几里德空间来度量距离

kNN的算法思路:找K个离预测点最近的点,然后让它们进行投票决定预测点的类型。 step 1: kNN存储样本点的特征数据和标签数据step 2: 计算预测点到所有样本点的距离,关于这个距离,我们用欧几里德距离来度量(其实还有很多…

苍穹外卖笔记-07-菜品管理-增加、删除、修改、查询分页还有菜品起售或停售状态

菜品管理 1 新增菜品1.1 需求分析与设计1.2 代码开发文件上传新增菜品实现 1.3 功能测试 2 菜品分页查询2.1 需求分析和设计2.2 代码开发设计DTO类设计VO类Controller层Service层Mapper层 2.3 功能测试 3 删除菜品3.1 需求分析和设计3.2 代码开发Controller层Service层Mapper层…

机器学习——卷积神经网络

卷积神经网络CNN 多层感知机MLP的层数足够,理论上可以用其提取出二位特征,但是毕竟复杂,卷积神经网络就可以更合适的来提取高维的特征。 而卷积其实是一种运算 二维离散卷积的公式 可以看成g是一个图像的像素点,f是每个像素点对…

【计网复习】应用层总结(不含HTTP和错题重点解析)

应用层总结(不含HTTP和错题重点解析) 应用层简介 应用层的主要功能常见的应用层协议小林对于应用层通常的解释 网络应用模型 客户端-服务器模型(Client-Server Model, C/S) 特点优点缺点应用场景 对等网络模型(Peer-to…

IO流字符流(FileReader与FileWriter)

目录 FileReader 空参read方法 带参read方法👇 FileWriter void write(intc) 写出一个字符 void write(string str) 写出一个字符串 void write(string str,int off,int len) 写出一个字符串的一部分 void write(char[] cbuf) …

备战 清华大学 上机编程考试-冲刺前50%,倒数第5天

T1:多项式求和 小K最近刚刚习得了一种非常酷炫的多项式求和技巧,可以对某几类特殊的多项式进行运算。非常不幸的是,小K发现老师在布置作业时抄错了数据,导致一道题并不能用刚学的方法来解,于是希望你能帮忙写一个程序…

C语言 树与二叉树基础部分

树与二叉树基础部分 树的基础概念二叉树的性质二叉树的遍历前序遍历中序遍历后序遍历层序遍历根据遍历结果恢复二叉树 二叉树的创建第一种第二种 二叉树的其他典型操作查找指定元素(一般二叉树)二叉树的高度(深度)二叉树的拷贝二叉…