摘要:在KV数据库领域,“强一致性”不仅是一个技术名词,它更是业务与运维的重要需求。

清明刚过,五一假期就要来了。大好春光,不如去婺源看油菜花吧!小云迅速打开APP刷出余票2张,赶紧下单!唉,怎么又没抢到!转念一想倒也能理解:从勾选乘车人到正式下单,起码要10秒,真若是“见者有份”,恐怕这两个座位大家要挤挤共用了!每逢节假日,全国几百万小伙伴同时查票订票,12306是如何保证余票显示准、车票不超卖的?

于是,按捺不住好奇心,笔者进行了一番深入研究。原来,问题背后隐藏着一个分布式数据库领域极其关键的技术——数据强一致性保障。

1. 什么是强一致?

在介绍概念之前,我们不妨先来模拟一场球赛直播。

假设笔者做了一款APP,后台使用上图的主从数据库。比分写入主节点,从节点分担用户查询。比赛中,Alice惊呼比赛结束,Bob闻声刷新APP,却显示比赛仍在继续!Bob体验到了明显的数据不一致,于是默默给APP打了个差评……

那么,产生不一致的原因究竟是什么?

异步复制时,主节点不等待从节点写入就直接返回了。由于网络延迟等原因,从节点无法保证更新时间。Alice和Bob明明在同时同地查询同一系统,得到正确结果却有先有后。其实这就是典型的弱一致性。

实际上,为解决单点故障、增强吞吐性能,分布式数据库内部都会对同一份数据进行复制,把冗余副本分散保存到不同节点上。简单的异步复制只能构建出弱一致系统,很难满足业务要求。

那么,究竟什么样的一致性才靠谱?有哪些类别?下面我们就来认识这个神秘家族!

1.1 强一致性/线性一致性(Linearizability)

一致性的最高标准,实现难度最高。核心要求是:一旦写操作完成,随后任意客户端的查询都必须返回这一新值。以下图为例,一旦“写入b”完成,必须保证读到b。而写入过程中,认为值的跳变可能发生在某一瞬间,因此读到a或b都是可能的。

从业务角度来说,强一致性带来的体验简直可以用丝滑来形容!因为它内部的数据“仿佛”只有一份,即使并发访问不同节点,每个操作也都能原子有序。正因如此,强一致数据库在业务架构中往往被用在关键位置。

etcd是强一致俱乐部里的元老。它基于Raft共识算法,真正实现了强一致,也因此在Leader选举、服务发现等场景起到重要作用。GaussDB(for Redis)作为一款分布式云数据库,凭借多年潜心打磨,也是强一致的代言人。

1.2 顺序一致性(Sequential Consistency)

弱于线性一致,不保证操作的全局时序,但保证每个客户端操作能按顺序被执行。下图中,A先写x=10,后写x=20;B先写x=99,后写x=999。当C读取时,顺序一致性保证了10先于20被读到、99先于999被读到。

Zookeeper基于ZAB协议,所有写操作都经由主节点协调,实现了顺序一致性。

1.3 因果一致性(Causal Consistency)

进一步放宽要求,只对并发访问中具有因果关系的操作保序。例如:

A写入3,B读到后乘以100再更新它。在这个场景下,由于“A写入3”与“B写入300”有着明确因果关系,因果一致性保证300晚于3被读到。

因果一致性多用于各种博客的评论系统、社交软件等。自然,我们回复某条评论的内容,不应早于评论本身被显示出来。

1.4 最终一致性(Eventual Consistency)

停止写入并等待一段时间,最终所有客户端都能读到相同的新数据,但具体时限不作保证。许多分布式数据库满足最终一致性,如MySQL主从集群等。

然而,这其实是一个非常弱的保证。由于不确定系统内部过多久才能收敛一致,在此之前,用户随时可能体验到数据不一致。因此最终一致性有天然的局限性,经常会给业务逻辑带来混乱。

1.5 弱一致性(Weak Consistency)

说它最为“厚脸皮”也不为过,因为它连数据写入后将来被读到都不能保证!弱一致性实现技术门槛低,应用场景也不多。严格来说,单纯的开源Redis主从集群就属于这一类别。

OK,一致性家族的各位成员已经跟大家打过照面。显然,一致性越强的数据库系统,能够支撑的业务场景越多。有的业务同学小声说,强一致技术再牛,可我业务简单,不用也没关系吧。实际上恰恰相反:

强一致不仅仅是技术问题,它更是一个不可忽视的业务需求、运维需求!

接下来我们就先来聊一聊:业务上那些只有强一致才能搞定的事儿!

2 强一致是业务刚需

2.1 计数器/限流器

计数服务是典型的强一致应用场景。电商在秒杀活动中,往往会搭建Redis主从集群给下层MySQL做缓存。因为要抗住超大流量,需要Redis的计数器功能做限流。简单讲,我们初始化counter=5000。随后每次业务访问都执行DECR命令,当counter归零就阻塞后续请求。此外,每隔一个时间段重置counter=5000,通过这样的手段来实现“细水长流”。

然而,完美的假设还不够!

开源Redis采用异步复制,如遇网络不畅,经常发生主节点复制buffer堆积。这将导致从节点counter偏大很多。此时,一旦主节点宕机,切换到从节点继续执行DECR命令,压力很容易超出阈值,全部落到下层脆弱的MySQL,随时可能引起系统雪崩!

因此,在限流场景下,只有真正的强一致才能提供可靠的计数器。

2.2 Leader选举

当业务部署的节点较多、可用性要求高时,往往要用到Leader选举。etcd作为强一致KV存储,能完美cover这一场景。etcd依赖两大功能实现Leader选举:

1)TTL:给key设置有效期,到期后key自动删除。

2)CAS:对key的原子操作。(这一功能只有强一致数据库才能实现)

使用etcd搭建Leader选举服务的设计如下:

1)约定key,用于选举时抢占。其value用于保存Leader节点名称。

2)约定TTL,用于给key设定有效期。

3)启动时:每个参与节点尝试cas create key&设置TTL。在etcd集群强一致CAS机制保障下,只有一个节点能执行成功。该节点成为Leader并将名称写入value;其余节点成为Follower。

4)运行中:每个节点定期TTL/2尝试get key,将value与自身名称对比:

  • 如相同,说明已是Leader,此后只需每隔TTL/2刷新key的TTL即可。
  • 如不同,说明是Follower,接下来要每隔TTL/2执行cas create key&设置TTL。

5)当Leader节点异常退出,无法刷新TTL,key会很快过期。此时,其余Follow之中便会有新的Leader产生。

从原理上能看出,强一致能力是Leader选举的根基。类似的“刚需”业务场景还有很多,强一致不可或缺。

好了,业务上的事儿就聊到这里,接下来让我们听听运维怎么说。

3. 强一致为运维减负

3.1 辅助组件架构复杂、问题难定位

后台架构中,MySQL主从热备也是常见的部署方式。由于数据保存在本地磁盘中,当主库发生严重故障,仅仅依靠MySQL自身同步机制,主从切换后无法保证所提供数据与之前状态完全一致。于是出现了“重量级”的辅助组件——MHA(Master High Availability)。我们来看一下它的部署方式:

MHA负责在故障转移过程中,帮助从库尽量追平主库最新状态,提供近似一致的数据。但这一能力需要额外的Manager节点,同时还要在每一个MySQL节点上部署Node服务。故障切换时,Manager先为从库补充落后的数据,再通过切换VIP恢复用户访问,过程可能长达数十秒。

这样的HA系统部署和后期维护都很复杂。如未能顺利执行故障切换或发生数据丢失,运维面临的场面都将很棘手。其实运维同学何尝不希望手中的系统稳定运行呢?要是数据库自身能提供强一致保障,何苦再依赖复杂的辅助组件!

读到这里,对强一致的看法,相信各位读者心里已经有了自己的一杆秤。让我们再一次划重点:强一致不仅仅是技术问题,它更是一个不可忽视的业务需求、运维需求!

从产品选型角度出发,开源Redis提供的一致性保证很弱。而etcd虽有强一致能力,但它单点写入性能不足,也未能提供hash、sorted set、stream等诱人的数据结构……纠结!

此时,有追求的读者会说——我全都要!

GaussDB(for Redis)应声而起——我,可以。

4. GaussDB(for Redis)与强一致

自设计之初,GaussDB(for Redis)(后文简称高斯Redis)给自己的定位就是“强一致KV数据库”,因此彻底摒弃了开源Redis的异步复制机制。借助华为云GaussDB系列先进的“存算分离”架构,将全量数据下沉到强一致存储层(DFV Pool),从核心技术上超越了传统开源产品的极限。

让我们来一起认识一下高斯Redis的强悍:

· 用户购买的实例作为一个整体,提供强一致KV存储。

用户业务统一通过Proxy集群接入高斯Redis,不用考虑内部复杂逻辑。多点并发访问实例,读写操作满足强一致性,再也不必担心开源Redis异步复制的不一致隐患。

· 计算层智能处理数据分片、动态故障转移,将数据全量下沉到共享存储池。

cfgsvr集群统一管理ShardServer节点,自动对海量数据进行分片。并能够在故障场景实现秒级接管,严格防止任何中间态下的数据不一致。

· 存储层通过RDMA高速网络实现高性能分布式数据持久化,三副本冗余保证强一致、零丢失。

DFV Pool是强一致、高性能的分布式存储系统。这是华为内部自研的公司级Data Lake,它能够稳定支撑各类全栈数据服务。高斯Redis突破了开源Redis“小格局”的内存架构,将数据全量下沉,基于DFV Pool强大的一致性保障能力,给用户业务带来更广阔的拓展空间。

5. 结语

试想,当处在关键位置的数据库“不给力”,业务层就要忙于为系统添加复杂、易出错的一致性保障逻辑。与此同时,运维还要时刻担心故障引发的数据落后问题......这样的系统真的“香”吗?

专业的事情交给专业的团队来做!

华为云NoSQL航道旗舰——GaussDB(for Redis)自研发初期就持续关注数据强一致性设计。借助GaussDB系列先进的强一致存储池DFV Pool,GaussDB(for Redis)始终如一,为用户提供真正强一致的海量KV存储解决方案。

6. 附录

本文作者:华为云高斯Redis团队

杭州西安深圳简历投递:yuwenlong4@huawei.com

更多技术文章,关注高斯Redis官方博客:https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813

点击关注,第一时间了解华为云新鲜技术~

华为云PB级数据库GaussDB(for Redis)揭秘第七期:高斯Redis与强一致的更多相关文章

  1. 华为云PB级数据库GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数

    摘要:高斯Redis,计数的最佳选择! 一.背景 当我们打开手机刷微博时,就要开始和各种各样的计数器打交道了.我们注册一个帐号后,微博就会给我们记录一组数据:关注数.粉丝数.动态数-:我们刷帖时,关注 ...

  2. 华为云数据库GaussDB(for Cassandra)揭秘第二期:内存异常增长的排查经历

    摘要:华为云数据库GaussDB(for Cassandra) 是一款基于计算存储分离架构,兼容Cassandra生态的云原生NoSQL数据库:它依靠共享存储池实现了强一致,保证数据的安全可靠. 本文 ...

  3. 华为云企业级Redis揭秘第16期:超越开源Redis的ACID"真"事务

    摘要: 开源Redis只支持伪事务,应用场景受限.高斯Redis发布企业级事务特性,支持完备ACID,为交易.库存等上层业务带来全新可能. 本文分享自华为云社区<华为云企业级Redis揭秘第16 ...

  4. Redis笔记(七):Redis应用场景

    特性优势 1 支持持久化 Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用. 2 数据类型丰富 Redis不仅仅支持简单的key-value类型的数据,同时还 ...

  5. 深入理解Spring Redis的使用 (七)、Spring Redis 使用 jackson序列化 以及 BaseDao代码

    之前在介绍Spring Redis进行存储的时候,都是通过RedisTemplate中的defaultSerializer,即JdkSerializationRedisSerializer.通过Jdk ...

  6. Redis搭建(七):Redis的Cluster集群动态增删节点

    一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cluste ...

  7. 华为云企业级Redis评测第一期:稳定性与扩容表现

    摘要:采用Redis Labs推出的多线程压测工具memtier_benchmark对比测试下GaussDB(for Redis) 和原生Redis的特性差异. 本文分享自华为云社区<华为云企业 ...

  8. 升级的华为云“GaussDB”还能战否?

    摘要:芯片.操作系统.数据库是现代信息技术领域的三大核心基础,做数据库,不仅需要技术和投入,对华为这种做通讯起家的企业,更需要的是一种并非玩票性质的态度. GaussDB,不仅蕴含着华为对数学和科学的 ...

  9. 从阿里云迁移分布式redis实例到华为云解决方案(详细)

    如果要换多数是经济因素啦- 一. 准备工作 先在华为云上买一台redis数据库,配置一定要注意多数要保持一致,至于4.0还是5.0倒问题不大亲测兼容 可用区要找现有ECS云主机中的相同的机器.记下:这 ...

随机推荐

  1. GitHub for mobile

    GitHub for mobile https://github.com/mobile

  2. RTPS解析

    资料参考: https://blog.csdn.net/HBS2011/article/details/102520704

  3. Windows 常用命令与快捷键

    1.自选区截图Shift+win+s 2.全屏截图Prtsc 3.活动窗口截图Alt+Prtsc 4.新建文件夹Ctrl + Shift + N 5.返回上级目录Alt + 上方向键 6.后退到上一次 ...

  4. Python函数注解

    目录 函数注解概述 实际应用 inspect模块 业务代码 总结 以下内容基于Python 3x 涉及的知识前提: 建议理解Python装饰器后学习此内容 函数注解概述 函数注解可以针对函数的参数.返 ...

  5. 学习了解使用docker

    学习了解使用docker docker是项目开发部署相关工具容器,本文通过官网等资料阅读学习,简单介绍一些基本使用操作: docker是什么 2.docker安装使用 连接进入docker容器 doc ...

  6. 聊一聊JVM

    JVM 什么是JVM? ​ JVM是java虚拟机的缩写,本质上是一个程序,能识别.class字节码文件(.java文件编译后产生的二进制代码),并且能够解析它的指令,最终调用操作系统上的函数,完成我 ...

  7. DatePicker 多时间粒度选择器组件

    使用方法: 在.vue文件引入 import ruiDatePicker from '@/components/rattenking-dtpicker/rattenking-dtpicker.vue' ...

  8. mysql从一个表提取数据更新另外一个表(修复表数据的不一致)

    目前碰到一个数据不一致的情况,有两张表,一张项目表,一张项目成员表,项目表有个字段是项目工作时间,是项目成员的工作时间汇总.是由于该了逻辑,所以要把数据改成一致. 项目表的大致结构如下. 表名:pro ...

  9. Java 读取Word文本框中的文本/图片/表格

    Word可插入文本框,文本框中可嵌入文本.图片.表格等内容.对文档中的已有文本框,也可以读取其中的内容.本文以Java程序代码来展示如何读取文本框,包括读取文本框中的文本.图片以及表格等. [程序环境 ...

  10. C#中委托、匿名函数、Lambda表达式的一些个人理解

    0x01定义一个委托,相当于定义一个可以存储方法的特殊变量类型 下面我们看具体的代码,通过代码更好理解 delegate void IntMethodInvoker(int x); 这行代码就是声明一 ...