Couchbase 中的分布式储存

Stella981
• 阅读 453

概述

Couchbase 是一个具有高性能、可扩展性和可 用性强的数据库引擎。它可以让开发人员通过 NoSQL 的键值存储(二进制或者JSON)或者使用 N1QL 的形式对数据进行操作(N1QL 是非常类似于 SQL 的一种语法操作 JSON 数据的方式)。以现在整体架构来看,Couchbase 是往分布式数据库的方向发展下去。

分布式数据库一般是从单机关系数据库扩展而来,用于存储结构化数据。分布式数据库采用二维表格组织数据,提供SQL关系查询语言,支持多表关联,嵌套子查询等复杂操作,并提供数据库事务以及并发控制。

Couchbase 的数据服务在单机、 集群安装,集群、多集群通信都是非常简单去做的。在一定的场景下,使用Couchbase是非常好的选择。

本文主要使用分布式储存的一些理论来分析 Couchbase 的数据服务的分布式数据储存模型。

数据储存

存储引擎直接决定了存储系统能够提供的性能和功能。在 Couchbase 的数据储存分对象缓存和数据储存引擎。如下图所示应用对数据的操作首先是对内存操作,然后才会异步更新至数据储存引擎中。对于 Couchbase,数据层 以 memcached API 对数据进行交互,系统在 memcached 程序中嵌入持久化引擎代码对数据进行缓存、复制、持久化等操作,持久化操作就是同步数据至 CouchDB 中(新版代码中增加了forestDB引擎)。对于图中的复制是在第四节中详细介绍。

Couchbase 中的分布式储存

对象缓存

对象缓存提供先内存储存的架构,使得的读与写的操作降低了延迟。对象储存是属于在内存中以hash储存方式储存,支持增、删、改,以及随机读取操 作,其哈希分片大小,根据所储存的数据项的量会动态变动。如下图,对象缓存根据key值得相关运算计算出分片的哈希值,然后会根据根据所储存项的多少,在 一个哈希分片以链表串连数据,每个内存中储存的数据结构见图所示。

Couchbase 中的分布式储存

Couchbase 中读数据是先从内存中查找key值是否存在,如果存在则返回值,如果不存在缓存中,则会从磁盘中获取数据,如果数据存在,放入缓存,最后在返回数据值。

注:对于对象缓存大小的设置,在管理员操作平台中,可以为每个bucket设置对应的RAM内存的大小。

数据储存引擎

Couchstore(Couchbase的数据储存引擎)是按vbucket为单位的文件储存在文件系统中。Couchstore应用B+树算法 通过key值去快速指向它的内容。 为了高效的写, Couchstore应用了追加写的模型(见下文介绍)对每一个文件进行高效和安全的写操作。

注:在Couchbase中,bucket是用户所操作文档数据的集合,vbucket是系统平均划分bucket的数据进行分片数据的集合。

B+树结构

 如下图所示:主节点指向中间节点. 这些中间节点指向叶节点。主节点和中间节点针对它们的子树可以划分指向文档范围的大小。叶节点储存了文档ID和元数据指向值所储存的文件位置。

Couchbase 中的分布式储存

追加写模型

追加写模式即所有的写操作只追加数据到文件尾部,而不修改老的数据,系统中的数据删除或者更新后,原来的数据成为垃圾数据,这可以加快磁盘的写速 度。如果 这些数据一直保存下去,文件会无限膨胀下去,为了解决这个问题,需要定期执行合并操作以实现垃圾回收。所谓合并操作,即将所有老数据文件中的数据扫描一遍 并生成新的数据文件,这里的合并其实就是对同一个key的多个操作以只保留最新一个的原则进行删除,每次合并后,新生成的数据文件就不再有冗余数据了。

数据分布

分布式系统区别于传统单机系统在于能够将数据分布到多个节点,并在多个节点之间实现负载均衡。

Couchbase 数据分布

在Couchbase数据分布是按计算分配到多个节点上,每个节点都储存两部分数据有效数据和副本数据,客户端对数据的操作主要是按照节点中对应的有效数据进行操作,执行压力会部分到不同的节点,类似如下图所示:

Couchbase 中的分布式储存

Couchbase的集群管理是由erlang/otp进行集群通信管理,集群之间使用心跳机制进行监测服务器节点健康监测,配置参数信息是同步到每一个节点上进行储存。整个集群以vbucket为单位划分映射到不同服务器节点中进行储存,划分规则如下:

  1. 均匀的分配有效vbucket和副本vbucket到不同服务器节点中;

  2. 把有效数据与副本数据划分到不同物理节点中;

  3. 在复制多份数据时,尽量有其它节点进行数据传播;

  4. 扩展时,以最小化数据迁移量进行复制。

负载均衡

在 Couchbase 中,我们所操作的每一个bucket会逻辑划分为1024个vbucket,其数据的储存基于每个vbucket储存并且每个 vbucket都会映射到相对应的服务器节点,这种储存结构的方式叫做集群映射。如下图所示,当应用与Couchbase服务器交互时,会通过SDK的与 服务器数据进行交互,当应用操作某一个的bucket的key值时,在SDK中会通过哈希的方式计算,使用公式crc32(key)%1024确定key 值是属于1024个vbucket中的某个,然后根据vbucket所映射的节点服务器对数据进行操作。

Couchbase 中的分布式储存

复制

为了保证分布式存储系统的高可靠和高可用,数据在系统中一般存储多个副本。当某个副本所在的存储节点出现故障时,分布式存储系统能够自动将服务切换到其它的副本,从而实现自动容错。

复制的概述

分布式存储系统中数据保存多个副本,一般来说,其中一个副本为主副本,其它副本为备副本,常见的做法是数据写入到主副本,由主副本确定操作的顺序并复制到其它副本。以下是两种复制类型:

  • 强同步复制:复制协议要求主备同步成功才可以返回客户端写成功,这种协议称为强同步协议。强同步协议提供了强一致性,但是,如果备副本出现问题将阻塞写操作,系统可用性较差。

  • 异步复制:在异步复制下,主副本不需要等待备副本的回应,只需要本地修改成功就可以告知客户端写操作成功。异步复制的好处在于系统可用性较好,但是一致性较差,如果主副本发生不可恢复故障,可能丢失最后一部分更新操作。

Couchbase 中的复制

集群内复制(单集群内复制)

集群内复制主要针对同一个集群中多个节点的数据进行多份复制备份,并且复制的份数会分布到不同的节点中。在数据分布中我们知道每个节点都会储存有效 的 vbucket和复制的vbucket。如下图展示,当应用对对数据进行写操作,此操作会先到集群节点中所对应有效的vbucket的数据进行写操作,并 且有效的vbucket节点会根据DCP协议传输写操作的变更传输到复制的vbucket所对应的节点,对复制的vbucket进行变更。可复制的 vbucket的份数,可以在操作bucket的时候进行配置,备份数量为1-3份。

Couchbase 中的分布式储存

集群内复制在Couchbase中可以由应用在写数据的时候选择一致性与可用性之间的权衡,Couchbase提供了以下几种模式的复制:

  1. 内存级的储存。此种模式是当应用写数据时,当数据已经储存到内存中后,就会返回正确回复给应用,同步其它节点和持久化储存都是由异步处理。此种模式速度最快,相对的容错性也是最差。

  2. 内存+持久化级的储存。此种模式是当应用写数据时,只有数据储存在内存和硬盘中后,才会返回正确回复给应用,同步其它节点是异步处理方式。此种模式,如果单节点出现问题,数据可能出现不一致性。

  3. 内存+备份节点级的储存。此种模式是当应用写数据时,只有数据储存同步到其它节点的内存中时,才会返回正确回复给应用,持久话处理都是异步处理,应用是可以选择出同步数据的节点数量。此种模式保证了数据一定备份和容灾,但是也有一定可能数据没有持久话会丢失。

  4. 内存+持久化+备份节点的储存。此种模式是当应用写数据时,数据存储必须满足所需要的节点中内存复制和持久化都完成后,才可以返回正确给应用。这种模式保证即使有效vbucket节点机器出现无法恢复的故障。

注:在程序流程中,第2,3,4种储存方式持久化数量节点和备份节点的数量是由客户端进行设置和进行检测的。第1种储存方式客户端是直接进行操作并且没有检测过程的。

在对于读的一致性的权衡,Couchbase 也提供了以下两种形式:

  1.  读取时,获取一致性的的数据。此种方式是当数据更新后所有的应用读到数据都是一样的。主要原理是读和写都是操作有效vbucket。

  2. 读取时,可以获取不一致性的数据。此种方式适合对于对数据一致性不是很重要,对可用性比较注重的场景。主要原理是读的时候,有效vbucket不可用时,数据会从备份vbucket中获取数据。

跨数据中心复制(多集群间复制)

跨数据中心复制主要是针对多个集群间的数据复制,此种复制主要以异步的方式通过XDCR协议同步数据到其它集群中备份,从而实现单集群或机房出现问 题级的容灾。跨数据中心复制是以bucket为单位进行复制的,在管理员操作界面可以通过配置XDCR来进行此种复制方式,下图为跨数据中心复制示例图:

Couchbase 中的分布式储存

容错

单台服务器故障的概率是不高的,然而,只要集群的规模足够大,每天都可能有机器故障发生,系统需要能够自动处理。首先,分布式存储系统需要能够 检测到机器故障,在分布式系统中,故障检测往往通过租约协议实现。接着,需要能够将服务复制或者迁移到集群中的其它正常服务的存储节点。

在Couchbase中可分单集群中和多集群容错:

  1. 单集群中可以设置auto-failover的方式来实现自动容错。管理员可在后台设置auto-failover的时间,当集群检测到单点机器超过设置的时间后,则选取uuid/seqno为最新的机器的副本数据激活,更新vbucket所映射的服务器来恢复业务。

  2. Couchbase现阶段没有实现多集群容错的方式,在设计应用的时候,需要检测单机群问题,进行集群的切换来恢复业务。

分布式协议

DCP (Database Change Protocol)

DCP 协议是一个高效的二进制协议,它主要用于集群内的数据复制、索引复制、备份数据等等。主要概念有以下几点:

  1. 有序复制,基于每个vbucket存在一个顺序序列号,同步时根据序列号进行更新;

  2. 重启恢复,当同步连接中断后,重新连接后,会对冲突数据进行恢复;

  3. 一致性,使用快照数据同步数据统一性;

  4. 内存间复制。

XDCR (Cross Data Center Replication)

XDCR提供了多个有效vbucket的数据的复制,主要用于跨数据中心的多集群间的复制。主要概念有一下几点:

  1. 基于bucket复制,两个集群的同一个bucket可以实现单向或者双向复制;

  2. 通过DCP协议保持持续性复制,一个XDCR连接中包括多个DCP数据流。这些流可以根据不同的分区对目的集群进行同步复制;

  3. 支持多种集群拓扑复制。集群间可以通过单向,双向复制。多个集群可以实现1对1,1对多,多对1等的集群复制拓扑图;

  4. 安全复制。数据中心见传输数据可以使用SSL进行加密;

  5. 最终一致性和解决数据冲突的能力。当出现冲突数据,会使用元数据的序列值,CAS值,文档标签和过期时间限制对数据进行冲突解决。

跨机房部署

在分布式系统中,跨机房问题一直都是比较复杂问题。机房之间的网络延时较大,且不稳定。跨机房问题主要包含两个方面:数据同步以及服务切换。

在Couchbase中可以以一下两种方式跨机房:

  • 集群整体切换,这种方式是两个机房部署了相同的Couchbase集群,由XDCP以异步方式同步集群副本,当出现问题时,可切换集群。这种方式 的问题是 当主机房整体出现故障时,有两种选择:要么将服务切换到备机房,忍受数据丢失的风险;要么停止服务,直到主机房恢复为止。因此,主备机房切换往往是手工 的,允许用户根据业务的特点选择“丢失数据”或者“停止服务”。

  • 单个集群跨机房,这种方式是将单个集群部署到多个机房,允许不同数据分片的主副本位于不同的机房。这种方式主要是考虑到写数据的时候,一致性比较强的数据是同步到每个节点中才算写成功的案例,当机房出现问题时,大部分数据是可以继续可用。

Couchbase的分布式及理论

CAP理论:一致性(Consistency),可用性(Availability)以及分区可容忍性(Tolerance of network Partition)三者不能同时满足。

  • 一致性:读操作总是能读取到之前完成的写操作结果,满足这个条件的系统称为强一致系统,这里的“之前”一般对同一个客户端而言;

  • 可用性:读写操作在单台机器发生故障的情况下仍然能够正常执行,而不需要等待发生故障的机器重启或者其上的服务迁移到其它机器;

  • 分区可容忍性:机器故障、网络故障、机房停电等异常情况下仍然能够满足一致性和可用性。

分布式存储系统要求能够自动容错,也就是说,分区可容忍性总是需要满足的,因此,一致性和写操作的可用性不能同时满足。

以下表格描述了Couchbase 所对应的 CAP 理论的部署方式:

部署拓扑结构

故障范围保护

CAP 平衡

评论

单Couchbase服务器机群

节点故障(例如, 节点之前硬件故障,通信失败)

可以配置成CP,并且可以通过配置auto failover操作得到有效性

当故障时,Couchbase服务器允许有效的读和配置 auto-failover一个很少的时间超时来恢复写的可用性。

多Couchbase服务器机群单向XDCR复制

节点或机群故障 (例如: 数据中心自然灾害)

AP是通过XDCR机群间单向复制来防止节点故障或者

单向复制可以用于同步数据在秒级计算能力数据中心中,

目的集群数据就可以通过最终一致性的数据用来读取和当原集群故障时,升级为读写集群(主从模式业务,读写分离)

多Couchbase服务器机群双向XDCR复制

节点或机群故障(例如: 数据中心自然灾害)

AP是通过XDCR机群间双向向复制来防止节点故障或者

双向服务可以用于有效/划分计算能力的跨数据中心,目的集群数据就可以读取和写最终一致性的数据在稳定状态,你会发现两个集群在操作同一个数据时发生了冲突,许多用户使用写在不同的划分段来让各自集群来处理避免冲突。(多主模式)

 最终一致性主要是来源于 BASE 理论。BASE 理论是对 CAP 理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。

基本可用(Basically Available)
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。
电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。
软状态( Soft State)
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。
最终一致性( Eventual Consistency)
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

总结

以上大致介绍 Couchbase 服务器的数据的分布式储存架构及一些分布式理论的知识。

Couchbase在系统分布式方面提供了基础的支持,然而在分布 式储存的一致性、可用性和分区性是需要有所权衡,Couchbase 服务器提供了多种选择的方式让用户根据自己的业务场景选择不同的非功能性的需求点,来 实现对数据的储存。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
2个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这