更好的样式前往 我的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. PostGIS 存储过程返回类型

    Postgresql存储过程返回值的方式有很多,在此先只记录一下自己用到过的,慢慢拓展 1.type型,这里geometry可以是任何postgresql支持的类型(integer/text/char ...

  2. 扛把子 选题 Scrum立会报告+燃尽图 03

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8680 一.小组情况组长:迟俊文组员:宋晓丽 梁梦瑶 韩昊 刘信鹏队名:扛 ...

  3. 【Luogu P3834】可持久化线段树(主席树)

    Luogu P3834 可持久化数据结构就是支持在历史版本上进行查询和修改操作的数据结构. 主席树就是对线段树的改进,使之可持久化. 前置知识:动态开点线段树 我们利用权值(值域)线段树统计区间内的数 ...

  4. 【2018寒假集训 Day2】【动态规划】垃圾陷阱(挖坑等填,未完成)

    垃圾陷阱 (well) 卡门--农夫约翰极其珍视的一条Holsteins奶牛--已经落了到"垃圾井"中."垃圾井"是农夫们扔垃圾的地方,它的深度为D (2 &l ...

  5. 如何搭建Docker私有仓库

    私有仓库 有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用. 本节介绍如何使用本地仓库. docker-registry 是官方提供的工具,可以用于构建私 ...

  6. 多进程使用同一log4j配置导致的日志丢失与覆盖问题

    最近接手了一个流传很多手的魔性古早代码,追日志时发现有明显缺失.对log4j不熟,不过可以猜测日志出问题肯定和多进程使用同一个log4j配置有关.经多次排查,终于捋清了其中逻辑.本文对排查过程进行复盘 ...

  7. 数据降维-LDA线性降维

    1.什么是LDA? LDA线性判别分析也是一种经典的降维方法,LDA是一种监督学习的降维技术,也就是说它的数据集的每个样本是有类别输出的.这点和PCA不同.PCA是不考虑样本类别输出的无监督降维技术. ...

  8. SpringBoot实现登录

    1.使用Spring Initializer快速创建Spring Boot项目 1.1 IDEA:使用 Spring Initializer快速创建项目 IDE都支持使用Spring的项目创建向导快速 ...

  9. Maven项目多环境之间的配置文件的切换

    前言:对于一个项目,开发和生产环境之间会使用不同的配置文件,最简单的例子就是数据库连接池的配置了.当然,可以在打包上线前对配置文件进行替换,不过这也太low了吧. 简单的pom.xml中的配置内容 比 ...

  10. Java-手动搭建SSH

    项目搭建工具:eclipse 项目开发环境:①Windows10-64位 ②Tomcat 8.5 ③jdk1.8.0_91 ④MySql 8.0.11 jar包准备:这里不详说,自己准备不不冲突能跑起 ...