【系统设计】分布式键值数据库

26153c95a42db2e5c83070ae68349fb0.gif

键值存储 ( key-value store ),也称为 K/V 存储或键值数据库,这是一种非关系型数据库。每个值都有一个唯一的 key 关联,也就是我们常说的 键值对

常见的键值存储有 Redis, Amazon DynamoDB,Microsoft Azure Cosmos DB,Memcached,etcd 等。

你可以在 DB-Engines 网站上看到键值存储的排行。

11d7da421752cc2d51bac1981325f64f.png

  设计要求  

45eee260d21f076c387015c04f38c926.png

在这个面试的系统设计环节中,我们需要设计一个键值存储, 要满足下面的几个要求

  • • 每个键值的数据小于 10kB。

  • • 有存储大数据的能力。

  • • 高可用,高扩展性,低延迟。

  单机版 - 键值存储  

对于单个服务器来说,开发一个键值存储相对来说会比较简单,一种简单的做法是,把键值都存储在内存中的哈希表中,这样查询速度非常快。但是,由于内存的限制,把所有的数据放到内存中明显是行不通的。

所以,对于热点数据(经常访问的数据)可以加载到内存中,而其他的数据可以存储在磁盘。但是,当数据量比较大时,单个服务器仍然会很快达到容量瓶颈。

  分布式 - 键值存储  

分布式键值存储也叫分布式哈希表,把键值分布在多台服务器上。在设计分布式系统时,理解 CAP(一致性,可用性,分区容错性) 定理很重要。

  CAP 定理  

CAP 定理指出,在分布式系统中,不可能同时满足一致性、可用性和分区容错性。让我们认识一下这三个定义:

  • • 一致性:无论连接到哪一个节点,所有的客户端在同一时间都会看到相同的数据。

  • • 可用性:可用性意味着任何请求数据的客户端都会得到响应,即使某些节点因故障下线。

  • • 分区容错性:分区表示两个节点之间的网络通信中断。分区容错性意味着,当存在网络分区时,系统仍然可以继续运行。

9bb06661c6f4605360ad195bfd6d3732.png

通常可以用 CAP 的两个特性对键值存储进行分类:

CP(一致性和分区容错性)系统:牺牲可用性的同时支持一致性和分区容错。

AP(可用性和分区容错性)系统:牺牲一致性的同时支持可用性和分区容错。

CA(一致性和可用性)系统:牺牲分区容错性的同时支持一致性和可用性。

由于网络故障是不可避免的,所以在分布式系统中,必须容忍网络分区。

让我们看一些具体的例子,在分布式系统中,为了保证高可用,数据通常会在多个系统中进行复制。假设数据在三个节点 n1, n2, n3 进行复制,如下:

理想情况

在理想的情况下,网络分区永远不会发生。写入 n1 的数据会自动复制到 n2 和 n3,实现了一致性和可用性。

744cec56ec8c80fe2a5198754af3ce3f.png

现实世界的分布式系统

在分布式系统中,网络分区是无法避免的,当发生分区时,我们必须在一致性和可用性之间做出选择。

在下图中,n3 出现了故障,无法和 n1 和 n2 通信,如果客户端把数据写入 n1 或 n2,就没办法复制到 n3,就会出现数据不一致的情况。

35a2420ede5f74d52334b35848fcc1f5.png

如果我们选择一致性优先(CP系统),当 n3 故障时, 就必须阻止所有对 n1 和 n2 的写操作,避免三个节点之间的数据不一致。涉及到钱的系统通常有极高的一致性要求。

如果我们选择可用性优先(AP系统),当 n3 故障时,系统仍然可以正常的写入读取,但是可能会返回旧的数据,当网络分区恢复后,数据再同步到 n3 节点。

选择合适的 CAP 是构建分布式键值存储的重要一环。

  核心组件和技术  

接下来,我们会讨论构建键值存储的核心组件和技术:

  • • 数据分区

  • • 数据复制

  • • 一致性

  • • 不一致时的解决方案

  • • 故障处理

  • • 系统架构图

  • • 数据写入和读取流程

  数据分区  

在数据量比较大场景中,把数据都存放在单个服务器明显是不可行的,我们可以进行数据分区,然后保存到多个服务器中。

需要考虑到的是,多个服务器之间的数据应该是均匀分布的,在添加或者删除节点时,需要移动的数据应该尽量少。

一致性哈希非常适合在这个场景中使用,下面的例子中,8台服务器被映射到哈希环上,然后我们把键值的 key 也通过哈希算法映射到环上,然后找到顺时针方向遇到的第一个服务器,并进行数据存储。

28834a872194a0e0c3b27f139ebfc57e.png

使用一致性哈希,在添加和删除节点时,只需要移动很少的一部分数据。

  数据复制  

为了实现高可用性和可靠性,一条数据在某个节点写入后,会复制到其他的节点,也就是我们常说的多副本。

那么问题来了,如果我们有 8 个节点,一条数据需要在每个节点上都存储吗?

并不是,副本数和节点数没有直接关系。副本数应该是一个可配置的参数,假如副本数为 3,同样可以借助一致性哈希环,按照顺时针找到 3 个节点,并进行存储,如下

3b8cd5a4f3b1cfaebd362fb0e0814f64.png

  一致性  

因为键值数据在多个节点上复制,所以我们必须要考虑到数据一致性问题。

Quorum 共识算法可以保证读写操作的一致性,我们先看一下 Quorum 算法中 NWR 的定义。

N = 副本数, 也叫复制因子,在分布式系统中,表示同一条数据有多少个副本。

W = 写一致性级别,表示一个写入操作,需要等待几个节点的写入后才算成功。

R = 读一致性级别,表示读取一个数据时,需要同时读取几个副本数,然后取最新的数据。

如下图,N = 3

0cbc34e5e56dd9d5d1902782b303faa7.png

注意,W = 1 并不意味着数据只写到一个节点,控制写入几个节点的是 N 副本数。

N = 3 表示,一条数据会写入到 3 个节点,W = 1 表示,只要收到任何节点的第一个写入成功确认消息(ACK)后,就直接返回写入成功。

这里的重点是,对 N、W、R的值进行不同的组合时,会产生不同的一致性效果。

  • • 当 W + R > N 的时候,通常是 N = 3, W = R = 2,对于客户端来讲,整个系统能保证强一致性,一定能返回更新后的那份数据。

  • • 当 W + R <= N 的时候,对于客户端来讲,整个系统只能保证最终一致性,所以可能会返回旧数据。

通过 Quorum NWR,可以调节系统一致性的程度。

  一致性模型  

一致性模型是设计键值存储要考虑的另外一个重要因素,一致性模型定义了数据一致性的程度。

  • • 强一致性: 任何一个读取操作都会返回一个最新的数据。

  • • 弱一致性: 数据更新之后,读操作可能会返回最新的值,也有可能会返回更新前的值。

  • • 最终一致性: 这是弱一致性的另外一种形式。可能当前节点的值是不一致的,但是等待一段时间的数据同步之后,所有节点的值最终会保持一致。

强一致性的通常做法是,当有副本节点因为故障下线时,其他的副本会强制中止写入操作。一致性程度比较高,但是牺牲了系统的高可用。

而 Dynamo 和 Cassandra 都采用了最终一致性,这也是键值存储推荐使用的一致性模型,当数据不一致时,客户端读取多个副本的数据,进行协调并返回数据。

  不一致的解决方案:版本控制  

多副本数据复制提供了高可用性,但是多副本可能会存在数据不一致的问题。

版本控制和向量时钟(vector clock )是一个很好的解决方案。向量时钟是一组 [server,version] 数据,它通过版本来检查数据是否发生冲突。

假设向量时钟由 D([S1, v1], [S2, v2], ..., [Sn, vn]) 表示,其中 D 是数据项,v1 是版本计数器,下面是一个例子

5e9423083bc253185dcd960861fcc002.png
  1. 1. 客户端把数据 D1 写入系统,写入操作由 Sx 处理,服务器 Sx 现在有向量时钟 D1[(Sx, 1)]。

  2. 2. 客户端把 D2 写入系统,假如这次还是由 Sx 处理,则版本号累加,现在的向量时钟是 D2([Sx, 2])。

  3. 3. 客户端读取 D2 并更新成 D3,假如这次的写入由 Sy 处理, 现在的向量时钟是D3([Sx, 2], [Sy, 1]))。

  4. 4. 客户端读取 D2 并更新成 D4,假如这次的写入由 Sz 处理,现在的向量时钟是 D4([Sx, 2], [Sz, 1]))。

  5. 5. 客户端读取到 D3 和 D4,检查向量时钟后发现冲突(因为不能判断出两个向量时钟的顺序关系),客户端自己处理解决冲突,然后再次写入。假如写入是 Sx 处理,现在的向量时钟是 D5([Sx, 3], [Sy, 1], [Sz, 1])。

注意,向量时钟只能检测到冲突,如何解决,那就需要客户端读取多个副本值自己处理了。

  故障处理  

在分布式大型系统中,发生故障是很常见的,接下来,我会介绍常见的故障处理方案。

  故障检测  

一种很常见的方案是使用 Gossip 协议,我们看一下它的工作原理:

  • • 每个节点维护一个节点成员列表,其中包含成员 ID 和心跳计数器。

  • • 每个节点周期性地增加它的心跳计数器。

  • • 每个节点周期性地向一组随机节点发送心跳,这些节点依次传播到另一组节点。

  • • 一旦节点收到心跳,成员列表就会更新为最新信息。

  • • 如果在定义的周期内,发现心跳计数器的值比较小,则认为该成员离线。

1bb8f9b3844704263e20a7ea8fe967ae.png

  处理临时故障  

通过 gossip 协议检测到故障后,为了保证数据一致性,严格的 Quorum 算法会阻止写入操作。而 sloppy quorum 可以在临时故障的情况下,保证系统的可用性。

当网络或者服务器故障导致服务不可用时,会找一个临时的节点进行数据写入,当宕机的节点再次启动后,写入操作会更新到这个节点上,保持数据一致性。

如下图所示,当 s2 不可用时,写入操作暂时由 s3 处理, 在一致性哈希环上顺时针查找到下一个节点就是s3,当 s2 重新上线时,s3 会把数据还给 s2。

893c4430666d36ca6d1fcaa37f0a88e3.png

  处理长时间故障  

数据会在多个节点进行数据复制,假如节点发生故障下线,并且在一段时间后恢复,那么,节点之间的数据如何同步? 全量对比?明显是低效的。我们需要一种高效的方法进行数据对比和验证。

使用 Merkle 树是一个很好的解决方案,Merkle 树也叫做哈希树,这是一种树结构,最下面的叶节点包含数据或哈希值,每个中间节点是它的子节点内容的哈希值,根节点也是由它的子节点内容的哈希值组成。

下面的过程,展示了 Merkle 树是如何构建的。

第 1 步,把键值的存储空间划分为多个桶,一个桶可以存放一定数量的键值。

78d4ad29177c022563e823bcbdcb8515.png

第 2 步,创建桶之后,使用哈希算法计算每个键的哈希值。

c8768a5ea1d7d7b2b932e071e7506d43.png

第 3 步,根据桶里面的键的哈希值,计算桶的哈希值。

8f66d58b10095eac5b994a910b1d575f.png

第 4 步,计算子节点的哈希值,并向上构建树,直到根节点结束。

0e083838f74445945ca0341071b87cee.png

如果要比较两个 Merkle 树,首先要比较根哈希,如果根哈希一致,表示两个节点有相同的数据。如果根哈希不一致,就遍历匹配子节点,这样可以快速找到不一致的数据,并进行数据同步。

  系统架构图  

我们已经讨论了设计键值存储要考虑到的技术问题,现在让我们关注一下整体的架构图,如下

af95db6a62a41719aa9f66dc79702743.png

这个架构主要有下面几个特点:

  • • 客户端通过简单的 API 和键值存储进行通信,get (key) 和 put (key, value)。

  • • coordinator 协调器充当了客户端和键值存储之间的代理节点。

  • • 所有节点映射到了一致性哈希环上。

  • • 数据在多个节点上进行复制。

  写入流程  

下图展示了数据写入到存储节点的过程,主要基于 Cassandra 的架构设计。

bb4481ce6cc1f4da7bee432c7add502b.png
  1. 1. 写入请求首先被持久化在提交日志文件中。

  2. 2. 然后数据保存在内存缓存中。

  3. 3. 当内存已满或者达到阈值时,数据移动到本地磁盘的 SSTable,这是一种高阶数据结构,感兴趣的读者自行查阅资料了解。

  读取流程  

在进行数据读取时,它首先检查数据是否在内存缓存中,如果是,就把数据返回给客户端,如下图所示:

cb30d89d0d470bf07514491c5109172f.png

如果数据不在内存中,就会从磁盘中检索。我们需要一种高效的方法,找到数据在哪个 SSSTable 中,通常可以使用布隆过滤器来解决这个问题。

bd614ddd05fd5255cc06d67f83a80ae6.png
  1. 1. 系统首先检查数据是否在内存缓存中。

  2. 2. 如果内存中没有数据,系统会检查布隆过滤器。

  3. 3. 布隆过滤器可以快速找出哪些 SSTables 可能包含密钥。

  4. 4. SSTables 返回数据集的结果。

  5. 5. 结果返回给客户端。

  Reference  

[0] System Design Interview Volume 2:
https://www.amazon.com/System-Design-Interview-Insiders-Guide/dp/1736049119

[1] Amazon DynamoDB: https://aws.amazon.com/dynamodb/

[2] memcached: https://memcached.org/

[3] Redis: https://redis.io/

[4] Dynamo: Amazon’s Highly Available Key-value Store: https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf

[5] Cassandra: https://cassandra.apache.org/

[6] Bigtable: A Distributed Storage System for Structured Data: https://static.googleusercontent.com/media/research.google.com/en//archive/bigtable-osdi06.pdf

[7] Merkle tree: https://en.wikipedia.org/wiki/Merkle_tree

[8] Cassandra architecture: https://cassandra.apache.org/doc/latest/architecture/

[9] SStable: https://www.igvita.com/2012/02/06/sstable-and-log-structured-storage-leveldb/

[10] Bloom filter https://en.wikipedia.org/wiki/Bloom_filter

END

做了一个 .NET 的学习网站,内容涵盖了分布式系统,数据结构与算法,设计模式,操作系统,计算机网络等,以及工作推荐和面试经验分享,欢迎来撩。

回复 dotnet 获取网站地址。

回复 面试题 获取 .NET 面试题。

回复 程序员副业 获取适合程序员的副业指南。

0fd80de05aadafef81e0b8f2e63e6ff6.gif

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

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

相关文章

【BIM入门实战】Revit建筑墙体:构造、包络、叠层图文详解

本文主要讲解Revit建筑墙体:构造、包络、叠层。 一、基本墙 第一步: 选择菜单栏的【建筑】选项卡中的【墙】下拉菜单→【属性】面板中切换至基本墙→点击属性面板中的【编辑类型】,弹出如下墙体对话框。 第二步: 选择【复制】按钮→重新进行编辑名称,命名为“外墙-1F-2…

win11 恢复win10开始菜单及任务栏

Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced] "Start_ShowClassicMode"dword:00000001 "TaskbarSi"dword:00000000将上述代码存为reg文件&#xff0c;双击导入注册表。 任务栏…

CentOS安装Tomcat

1. 下载Tomcat安装包&#xff1a; Tomcat官网 解压下载下来的tar.gz至任意目录下&#xff0c;执行命令&#xff1a; Java代码 tar -xzf apache-tomcat-7.0.56.tar.gz 解压后如图&#xff1a; 如果是在windows上&#xff0c;则直接解压zip包到任意目录&…

【BIM+GIS】ArcGIS Pro2.8如何打开Revit模型,BIM和GIS融合?

ArcGIS Pro2.8中,可以直接打开Revit模型(.rvt)项目文件,实现了从数据格式方面BIM与GIS的有机融合,具体操作如下所示: 1. Revit2018模型绘制 打开Revit2018软件,选择【建筑样板】,打开标高1楼层平面,新建一个简单的户型:包括四面墙体、2个门和一扇窗户,如下图所示。…

Edge 开发者沙龙|一小时精通Edge扩展开发

点击蓝字关注我们编辑&#xff1a;Alan Wang排版&#xff1a;Rani Sun微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0c;将…

tomcat 开启远程debug

1、linux服务器上tomcat配置startup.sh 文件末尾添加&#xff08;不换行&#xff09;&#xff1a;declare -x CATALINA_OPTS"-server -Xdebug -Xnoagent -Djava.compilerNONE -Xrunjdwp:transportdt_socket,servery,suspendn,address9876"2、eclipse配置&#xff1a;…

【测绘程序设计】坐标反算神器V1.0(附C/C#/VB源程序)

【拓展阅读】:【测绘程序设计】坐标正算神器V1.0(附C/C#/VB源程序) 一、坐标反算原理 ​坐标反算:已知两点坐标,反求边长和方位角,称为坐标反算。 原理坐标系: 计算公式: 二、C#程序实现 1. 界面设计 2

ASP.NET Core 6框架揭秘实例演示[01]: 编程初体验

本篇提供的20个简单的演示实例基本涵盖了ASP.NET Core 6基本的编程模式&#xff0c;我们不仅会利用它们来演示针对控制台、API、MVC、gRPC应用的构建与编程&#xff0c;还会演示Dapr在.NET 6中的应用。除此之外&#xff0c;这20个实例还涵盖了针对依赖注入、配置选项、日志记录…

DBeaverEE 21.1.0安装指南

1、 安装jdk11 2、 配置环境变量 将jdk11安装目录加入path&#xff1a;C:\Program Files\Java\jdk-11.0.10\bin3、 安装DBEE 21.1 4、 将dbeaver-agent文件夹复制到DBEE安装目录 5、将DBEE安装目录下的jre目录删除或改名 6、 修改dbeaver.ini文件&#xff0c;在文件最后添加…

跟风学Docker之四:Docker网络解决方案

2019独角兽企业重金招聘Python工程师标准>>> 跟风学Docker之四&#xff1a;Docker网络解决方案 博客分类&#xff1a; docker 前言&#xff1a;前面的部分一直都是单机跑docker&#xff0c;但实际生产环境不可能只用一台来跑。肯定会用到多台&#xff0c;因为他们都…

【测绘程序设计】坐标方位角推算神器(C#版)

本文讲解利用C#语言实现坐标方位角推算,附源码赠送。 1. 神器效果展示 (1)连接角为左角 (2)连接角为右角 2. 方位角推算原理速递 (1)原理示意图

原型模式——创建型模式

2019独角兽企业重金招聘Python工程师标准>>> 思路&#xff1a; 马上又到找工作的时候了&#xff0c;当我们在准备一份份简历的时候有没有考虑过这样一个问题&#xff1f; 面对不同的工作岗位我们需要准备不同的求职简历&#xff0c;但是这样的几份不同的简历中还是有…

如何获取 ASP.NET Core 当前启动地址?

前言上次&#xff0c;我们介绍了配置ASP.NET Core启动地址的多种方法。那么&#xff0c;如何通过代码方式&#xff0c;获取启动后的地址&#xff1f;WebApplication.Urls 对象使用 WebApplication.Urls.Add 方法可以添加启动地址。那么&#xff0c;使用 WebApplication.Urls 应…

【CASS精品教程】CASS9.1查询功能大全(坐标、长度、面积、方位角)

文章目录 1. 查询指定点坐标2. 查询两点距离及方位3. 查询线长4. 查询实体面积CASS9.1中提供了查询指定点坐标、查询两点距离及方位、查询线长、查询实体面积等查询功能,如下图所示: 本文以动画演示的方式,对以上提到的功能进行讲解。 1. 查询指定点坐标 点击【工程应用】…

自定义smokeping告警(邮件+短信)

前段时间接到公司IT同事需求&#xff0c;帮助其配置smokeping的告警功能&#xff0c;之前配置的姿势有些问题&#xff0c;告警有些问题&#xff0c;现在调试OK&#xff0c;在此将关键配置点简单记录下。 关键的配置项主要有&#xff1a; 定义告警规则并配置将告警信息通过管道交…

selenium 定制启动 chrome 的选项

2019独角兽企业重金招聘Python工程师标准>>> selenium 定制启动 chrome 的选项 博客分类&#xff1a; java 搜索引擎&#xff0c;爬虫 使用 selenium 时&#xff0c;我们可能需要对 chrome 做一些特殊的设置&#xff0c;以完成我们期望的浏览器行为&#xff0c;比如…

平台级 SAAS 架构的基础:统一身份管理系统

业内在用户统一身份认证及授权管理领域&#xff0c;主要关注 4 个方面&#xff1a;集中账号管理&#xff08;Account&#xff09;、集中认证管理&#xff08;Authentication&#xff09;、集中授权管理&#xff08;Authorization&#xff09;和集中审计管理&#xff08;Audit&a…

【ArcGIS Pro微课1000例】0017:ArcGIS Pro 2.8制作炫酷的ETOPO1全球DEM地图

ArcGIS Pro相对于ArcGIS,在制图方面做了很大的提升,做出的地图更加优美,本文讲解基于NOAA的ETOPO1数据全球DEM数据制作炫酷的全球DEM地图,先看效果再教学! 1. 效果展示 全球 澳大利亚大陆

Js中的for in

2019独角兽企业重金招聘Python工程师标准>>> 后台数据&#xff1a; List<Map<String, Object>> uTags query.selectAllList("velocity.userGetTags", map); 前端解析&#xff1a; for(var i in data.content){//由于这里是List[i](Map).IDc…

VMWare 安装 Linux

参考 &#xff1a; http://www.aboutyun.com/thread-6780-1-1.html 这的是很详细。赞一下 我这里就简化一下。 1 下载&#xff1a; VMWare : https://download3.vmware.com/software/wkst/file/VMware-workstation-full-10.0.0-1295980.exe ubuntu : http://www.aboutyun…