更好的样式前往 我的Github笔记 查看

<md文档排版不好>

数据模型

组合键:Table + HashKey + SortKey

  1. Table实现业务数据的隔离

  2. HashKey决定数据在那个分片

  3. SortKey决定数据在分片内的排序

一致性协议

使用PacificA协议,保证多副本数据的一致性。

<!-- addition -->

机器

Pegasus分布式集群至少需要准备这些机器:

  • MetaServer

    • link:Meta Server 的设计

    • 要求:2~3台机器,无需SSD盘。

    • 作用:用来保存表和表的分片信息。

  • ReplicaServer:

    • link:Replica Server 的设计

    • 要求至少3台机器,建议挂SSD盘。譬如一台服务器挂着8块或者12块SSD盘。这些机器要求是同构的,即具有相同的配置。

    • 作用:至少三台ReplicaServer。每一个ReplicaServer都是由多个Replica组成的。每一个Replica表示的是一个数据分片的Primary或Secondary。

  • Collector:可选角色,1台机器,无需SSD盘。该进程主要用于收集和汇总集群的统计信息,负载很小,建议放在MetaServer的其中一台机器上。

Replica

  • 一个数据分片对应3个Replica。

  • Replica有两个种类:Primary和Secondary。

  • 在一个数据分片对应的 3 个或以上的Replica中,只有1个Primary,其余的均是Secondary。

  • 很多个Replica组成一个ReplicaServer,同一个ReplicaServer中的Replica种类不相同。

    • 同一个ReplicaServer中的Replica不一定全是Primary,也不一定全是Secondary。

  • 一个最基本的Pegasus集群,最少需要 3 个ReplicaServer。

在Pegasus中,一个Replica有如下几种状态:

  • Primary

  • Secondary

  • PotentialSecondary(learner):

    • 当group中新添加一个成员时,在它补全完数据成为Secondary之前的状态

  • Inactive:

    • 和MetaServer断开连接时候的状态,或者在向MetaServer请求修改group的PartitionConfiguration时的状态

  • Error:

    • 当Replica发生IO或者逻辑错误时候的状态

写流程

写流程类似于两段提交:

  1. 客户端根据Key首先查询MetaServer,查询到这个Key对应的分片的对应的ReplicaServer。具体来说,客户端需要的其实是分片Primary所在的ReplicaServer。

  2. 客户端向Primary ReplicaServer发起写请求。

  3. Primary ReplicaServer向其对应的两台或以上的Secondary ReplicaServer复制数据。

  4. Secondary ReplicaServer将数据写入成功后,Primary ReplicaServer向客户端返回成功的响应。

可能导致ReplicaServer不能响应写请求的原因有:

  1. ReplicaServer无法向MetaServer持续汇报心跳,自动下线。

  2. Replica在IO上发生了一些无法恢复的异常故障,自动下线。

  3. MetaServer将Replica的Primary进行了迁移。

  4. Primary在和MetaServer进行group成员变更的操作,拒绝写。

  5. 当前Secondary个数太少,Replica出于安全性考虑拒绝写。

  6. 出于流控考虑而拒绝写。

读流程

只从Primary读。

宕机恢复

  • MetaServer和所有的ReplicaServer维持心跳。

  • 通过心跳来实现失败检测。

  • 宕机恢复的几种情况:

    • Primary Failover:如果某个分区的Primary所在的ReplicaServer宕机了,那么MetaServer 就会选择一个Secondary成为Primary。过后再添加Secondary。

    • Secondary Failover:如果某个分区的Secondary所在的ReplicaServer宕机了,那么暂时使用一主一副的机构继续提供服务。过后再添加Secondary。

    • MetaServer Failover:主MetaServer宕机了,备用的MetaServer通过zookeeper抢主成为新的主MetaServer。从zookeeper恢复状态,然后重新和所有ReplicaServer建立心跳。

  • 宕机恢复过程中,尽量避免数据的跨节点复制。

zookeeper抢主

<!-- zookeeper抢主 -->

link:zookeeper抢主

单机存储

一个ReplicaServer包括多个Replica,Replica使用RocksDB作为存储引擎:

  • 关闭掉了rocksdb的WAL。

  • PacificA对每条写请求都编了SequenceID,RocksDB对写请求也有内部的SequenceID。Pegasus对二者做了融合,来支持自定义的checkpoint的生成。

  • Pegasus给RocksDB添加了一些compaction filter以支持Pegasus的语义:例如某个value的TTL。

和很多一致性协议的实现一样,Pegasus中PacificA的实现也是和存储引擎解耦的。

RocksDB

<!-- RocksDB -->

link:RocksDB

数据安全

  • Table软删除

    • Table删除后,数据会保留一段时间,防止误删除

  • 元数据恢复

    • Zookeeper损坏时,从各ReplicaServer收集并重建元数据

  • 远程冷备份

    • 数据定期备份到异地,譬如HDFS或者金山云 • 在需要的时候可快速恢复

  • 跨机房同步

    • 在多个机房部署集群

    • 采用异步复制的方式同步数据

冷备份

Pegasus的冷备份功能用来将Pegasus中的数据定期生成快照文件,并备份到其他存储介质上,从而为数据容灾多提供一层保障。但由于备份的是某个时间点的数据快照文件,所以冷备份并不保证可以保留所有最新的数据,也就是说,恢复的时候可能会丢失最近一段时间的数据。

具体来看,冷备份过程要涉及到如下一些参数:

  • 存储介质(backup_provider):

    • 指其他的文件存储系统或服务,如本地文件系统或者HDFS。

  • 数据冷备份的周期(backup_interval):

    • 周期的长短决定了备份数据的覆盖范围。如果周期是1个月,那么恢复数据时,就可能只恢复一个月之前的数据。但如果周期设的太短,备份就会太频繁,从而使得备份开销很大。在小米内部,冷备份的周期通常是1天。

  • 保留的冷备份个数(backup_history_count):

    • 保留的备份个数越多,存储的空间开销就越大。在小米内部,一般保留最近的3个冷备份。

  • 进行冷备份的表的集合(backup_app_ids):

    • 并不是所有的表都值得进行冷备份。在小米内部,对于经常重灌全量数据的表,我们是不进行冷备份的。

在Pegasus中,以上这几个参数的组合称为一个冷备份策略(backup_policy)。数据的冷备份就行按照policy为单位进行的。

跨机房同步

link:跨机房同步文档

小米内部有些业务对服务可用性有较高要求,但又不堪每年数次机房故障的烦恼,于是向 pegasus 团队寻求帮助,希望在机房故障时,服务能够切换流量至备用机房而数据不致丢失。因为成本所限,在小米内部以双机房为主。

通常解决该问题有几种思路:

  1. 由 client 将数据同步写至两机房。这种方法较为低效,容易受跨机房专线带宽影响,并且延时高,同机房 1ms 内的写延时在跨机房下通常会放大到几十毫秒,优点是一致性强,但需要 client 实现。服务端的复杂度小,客户端的复杂度大。

  2. 使用 raft/paxos 协议进行 quorum write 实现机房间同步。这种做法需要至少 3 副本分别在 3 机房部署,延时较高但提供强一致性,因为要考虑跨集群的元信息管理,这是实现难度最大的一种方案。

  3. 在两机房下分别部署两个 pegasus 集群,集群间进行异步复制。机房 A 的数据可能会在 1 分钟后复制到机房 B,但 client 对此无感知,只感知机房 A。在机房 A 故障时,用户可以选择写机房 B。这种方案适合 最终一致性/弱一致性 要求的场景。后面会讲解我们如何实现 “最终一致性”。

基于实际业务需求考虑,我们选择方案3。

即使同样是做方案 3 的集群间异步同步,业内的做法也有不同:

  1. 各集群单副本:这种方案考虑到多集群已存在冗余的情况下,可以减少单集群内的副本数,同时既然一致性已没有保证,大可以索性脱离一致性协议,完全依赖于稳定的集群间网络,保证即使单机房宕机,损失的数据量也是仅仅几十毫秒内的请求量级。考虑机房数为 5 的时候,如果每个机房都是 3 副本,那么全量数据就是 3*5=15 副本,这时候简化为各集群单副本的方案就是几乎最自然的选择。

  2. 同步工具作为外部依赖使用:跨机房同步自然是尽可能不影响服务是最好,所以同步工具可以作为外部依赖部署,单纯访问节点磁盘的日志(WAL)并转发日志。这个方案对日志 GC 有前提条件,即日志不可以在同步完成前被删除,否则就丢数据了,但存储服务日志的 GC 是外部工具难以控制的。所以可以把日志强行保留一周以上,但缺点是磁盘空间的成本较大。同步工具作为外部依赖的优点在于稳定性强,不影响服务,缺点在于对服务的控制能力差,很难处理一些琐碎的一致性问题(后面会讲到),难以实现最终一致性

  3. 同步工具嵌入到服务内部:这种做法在工具稳定前会有一段阵痛期,即工具的稳定性影响服务的稳定性。但实现的灵活性肯定是最强的。

最初 Pegasus 的热备份方案借鉴于 HBase Replication,基本只考虑了第三种方案。而事实证明这种方案更容易保证 Pegasus 存储数据不丢的属性。

每个 replica (这里特指每个分片的 primary,注意 secondary 不负责热备份复制)独自复制自己的 private log 到远端,replica 之间互不影响。复制直接通过 pegasus client 来完成。每一条写入 A 的记录(如 set / multiset)都会通过 pegasus client 复制到 B。为了将热备份的写与常规写区别开,我们这里定义 duplicate_rpc 表示热备写。

A->B 的热备写,B 也同样会经由三副本的 PacificA 协议提交,并且写入 private log 中。这里有一个问题是,在 A,B 互相同步的场景,一份写操作将形成循环:A->B->A,同样的写会无数次地被重放。为了避免循环写,我们引入 cluster id 的概念,每条 duplicate_rpc 都会标记发送者的 cluster id。

[duplication-group]
A=1
B=2
void set(String tableName, byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds)

直接使用pegasus优化,直接对pegasus读、写。可以替代redis缓存的架构。

  1. 读写逻辑复杂

  2. 要特意维护数据一致性

  3. 服务可用性不高

  4. 机器成本高

问题:

读取:先读取缓存,如果缓存中不存在,那么再读取数据库中的数据。

写入:双写,既写入缓存、也要写入数据库。

原先:Redis 作为缓存 + HBase/mysql/MongoDB 作为数据库。

业务应用

  HashKey SortKey Value
map MapId key value
set SetId key null
list ListId index value

Pegasus本身不支持容器类型,但是其HashKey + SortKey的数据模型可以模拟容器。

容器支持

对HashKey或者SortKey进行字符串匹配, 只有符合条件的结果才会返回。对HashKey或者SortKey进行字符串匹配,只有符合条件的

条件过滤

同一个HashKey的数据写入同一个Replica,同一个Replica的操作,在同一个线程中串行执行。这样就避免了同步的问题。

对同一个HashKey的写操作,保证总是原子的,包括set、multiSet、del、multiDel、incr、 checkAndSet。

单行事务

支持对数据指定过期时间, 数据过期后就无法读取到。

TTL过期策略
  1. 线程安全

    • 所有的接口都是线程安全的,不用担心多线程的问题。

  2. 并发性能

    • 客户端底层使用异步的方式实现,可以支持大的并发,不用担心性能的问题。

  3. Client单例

    • 通过 getSingletonClient() 获得的Client是单例, 可以重复使用。

  4. 翻页功能

    • 通过客户端提供的接口,能够轻松实现数据翻页功能 。

Java客户端

集群使用falcon进行监控。

集群监控

使用

热备份同时也需要容忍在 replica 主备切换下复制的进度不会丢失,例如当前 replica1 复制到日志 decree=5001,此时发生主备切换,我们不想看到 replica1 从 0 开始,所以为了能够支持 断点续传,我们引入 confirmed_decree。replica 定期向 meta 汇报当前进度(如 confirmed_decree = 5001),一旦meta将该进度持久化至 zookeeper,当replica故障恢复时即可安全地从 5001重新开始热备份。

所以当 B 重放某条 duplicate_rpc 时,发现其 cluster_id = 1,识别到这是一条发自 A 的热备写,则不会将它再发往 A。

小米开源数据库<pegasus>简介的更多相关文章

  1. JanusGraph : 图和图数据库的简介

    JanusGraph:图数据库系统简介 图(graph)是<数据结构>课中第一次接触到的一个概念,它是一种用来描述现实世界中个体和个体之间网络关系的数据结构. 为了在计算机中存储图,< ...

  2. Cayley图数据库的简介及使用

    图数据库   在如今数据库群雄逐鹿的时代中,非关系型数据库(NoSQL)已经占据了半壁江山,而图数据库(Graph Database)更是攻城略地,成为其中的佼佼者.   所谓图数据库,它应用图理论( ...

  3. 小米开源监控open-falcon

    小米开源监控系统Open-Falcon安装使用笔记 07net01.com 发布于 2016-10-25 18:42:03 分类:IT技术 阅读(88) 评论 前言 近期爆出Zabbix有严重bug, ...

  4. 图数据库Neo4j简介

    图数据库Neo4j简介 转自: 图形数据库Neo4J简介 - loveis715 - 博客园https://www.cnblogs.com/loveis715/p/5277051.html 最近我在用 ...

  5. 数据库PDO简介

    php简介,php历史,php后端工程师职业前景,php技术方向,php后端工程师职业体系介绍. php是世界上使用最广泛的web开发语言,是超文本预处理器,是一种通用的开源脚本语言,语法吸收了c语言 ...

  6. 【转】 MySQL与PostgreSQL:该选择哪个开源数据库?哪一个更好?

    转载地址:http://www.infoq.com/cn/news/2013/12/mysql-vs-postgresql 如果打算为项目选择一款免费.开源的数据库,那么你可能会在MySQL与Post ...

  7. MySQL、PostgreSQL、Ingres r3、MaxDB等开源数据库的详细比较

    1.MySQL 5 作为当今最流行的开放源码数据库之一,MySQL数据库为用户提供了一个相对简单的 解决方案,适用于广泛的应用程序部署,能够降低用户的TCO.MySQL是一个多线程.结构化查询语言(S ...

  8. MySQL全世界最流行的开源数据库软件

    誉天全国首推全球市场占有率第二的数据库——MySQL培训课程,阿里巴巴.新浪等知名企业正在使用MySQL数据库系统,而这方面的人才需求也是供不应求,誉天作为国内2014年首批ORACLE官方授权MyS ...

  9. Java免费开源数据库、Java嵌入式数据库、Java内存数据库

    Java免费开源数据库.Java嵌入式数据库.Java内存数据库 http://blog.csdn.net/leiyinsu/article/details/8597680

随机推荐

  1. 报错:尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。

    问题: 在写windows服务时,发布后日志报错:尝试加载 Oracle 客户端库时引发 BadImageFormatException.如果在安装 32 位 Oracle 客户端组件的情况下以 64 ...

  2. Android中的设计模式

    一.设计模式的分类 总体来说23种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式 ...

  3. Learning Markov Clustering Networks for Scene Text Detection

    Learning Markov Clustering Networks for Scene Text Detection 论文下载:https://arxiv.org/pdf/1805.08365v1 ...

  4. PowerMock学习(七)之Mock Constructor的使用

    前言 我们在编码的时候,总习惯在构造器中传参数,那么在powermock中是怎么模拟带参数构造的呢,这并不难. 模拟场景 我们先模拟这样一个场景,通过dao中的传入一个是布尔类型(是否加载)和一个枚举 ...

  5. 2019-11-19:xxe漏洞利用,笔记

    xxe,也就是xml,外部实体注入攻击,漏洞是对非安全的外部实体数据进行处理时引发的安全问题,要了解xxe,就必须懂得xml的一些规则xml是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据 ...

  6. 记一次net/net core delete 方法报404 解决方案

    今天一个net core的delete方法 执行的时候 报404 网上查阅资料后发现是IIS 默认只允许get/post方法接入 网上查找资料后 在web.config添加如下代码: 意为移除WebD ...

  7. JVM的类加载机制全面解析

    什么是类加载机制 JVM把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型,这就是JVM的类加载机制. 如果你对Class文件的结 ...

  8. LESSON 4- Entropy and Asymptotic Equipartition Property

    1.        Entropy 2.        序列熵(无记忆,有记忆,马尔科夫) 3.   Fixed-to-variable-length codes  (给n个输出symbols进行变长 ...

  9. AWS re:Invent 2019 召开 | 云原生生态周报 Vol. 30

    作者 | 何淋波.宋净超.徐迪 业界要闻 1. AWS re:Invent 2019 AWS 年度云计算盛会于 12.2-12.6 在拉斯维加斯举行. 技术分享超过 2500 场,技术方向涵盖数据分析 ...

  10. Kafka 0.10.0.1 consumer get earliest partition offset from Kafka broker cluster - scala code

    Return: Map[TopicPartition, Long] Code: val props = new Properties() props.put(ConsumerConfig.BOOTST ...