• 2021-06-29

    分布式数据库系统的容错处理 – 100% 成功率, 超时和性能

    Views: 5039 | No Comments

    之前写过一篇文章, 介绍"可靠通信三原则". 对于一个分布式数据库, 如果想实现 100% 高可用(也即客户端的请求永远不会返回失败), 同样可以用可靠通信三原则中的重试理论和去重理论来解决. 但在实践上, 需要在成功率, 耗时(速度和性能)各方面进行取舍. 本文分享实际经验, 介绍什么样的选择是普适的, 各位可以参考.

    客户端访问数据库服务器, 发起大量的请求, 绝对不可能做到每一个请求都是成功的. 因为网络原因, 请求可能失败. 因为服务器内部处理冲突, 或者分布式节点间协调冲突, 都可能导致请求失败.

    所谓容错处理, 就是在遇到错误的时候进行重试. 因为错误必然发生, 只有重试才能消除错误的影响, 就好像 IP 层必然会丢包, 但 TCP 协议通过重传达到某种程度的可靠传输.

    某些实现了 Basic Paxos + 日志复制状态机模型的系统, 因为所谓的"Leaderless", 会产生大量冲突. 即使是使用 Raft, 在某些情况下意外发生选举, 也会导致请求冲突.

    Continue reading »

    Posted by ideawu at 2021-06-29 22:16:55 Tags: ,
  • 2021-06-27

    分布式数据库如何做到异地多活?

    Views: 9333 | 2 Comments

    前段时间写过一篇文章"分布式数据库系统如何做到平滑缩扩容?", 讲了分布式数据库在扩容(集群服务器开机关机)过程中, 如何保证服务 100% 不中断. 那篇文章主要是从客户端的角度去考虑问题, 正如该文章所说的, 一个分布式系统, 必须服务端和客户共同协作, 才能实现服务不中断. 本文从服务端, 也即狭义理解的"数据库系统"的角度, 分析一个分布式数据库系统是如何做到 100% 高可用的.

    注意, 高可用, 异地多活, 多主(Leaderless), 这些词汇, 本质上是指同一个东西, 都是指在单一节点宕机时, 客户端可以切换(切主)到其它节点访问, 或者说, 客户端在平时可以访问任意一个节点(多主) -- 切主多主是一回事, 只要可以做到足够快速地切主, 即使表面上一个系统是有 Leader Based 的, 那么它和 Leaderless 没有区别. 阅读本文之后, 相信你能加深对这些概念的理解.

    首先说一个定理: 只有强一致性的多副本系统, 才能异地多活.

    Continue reading »

    Posted by ideawu at 2021-06-27 23:24:48 Tags: ,
  • 2021-06-23

    分布式数据库异地多活不是你想的那样

    Views: 4065 | No Comments

    在分布式数据库领域, "异地多活"是一个非常诱人的特性, 被广泛用于商业广告宣传. 但是, "异地多活"未必是你所想象的那种"多活". 因为分布式数据库的三个重要特性:

    • 多副本
    • 多写入点
    • 低延迟

    "异地多活"占据了前两个, 根据"不可能三角"理论, 一旦选择了前两个特性, 那么低延迟便不再是一个选项, 而是一个结果, 给你多大的延迟(多慢), 你就得接受多大的延迟, 你无法选择.

    这里涉及到一个基础科学思维的问题, "结果"是一种客观存在的东西, 而"选择"是一种主观决定的东西. 根据"不可能三角"理论, 你无法同时选择三个特性, 不代表一旦你选择其中两个, 就一定会得到极差的第三个特性, 而是说, 一旦你选择了其中两个特性, 那么第三个特性就已经完全固定, 无法再改变.
    Continue reading »

    Posted by ideawu at 2021-06-23 23:56:43
  • 2021-06-04

    数据库内核的快照技术实现原理

    Views: 4654 | No Comments

    "快照(Snapshot)"是数据库领域非常重要的一个概念, 最初是用于数据备份. 如今, 快照技术已经成为数据库内核(引擎)最核心的技术特性之一. 数据库内核的绝大多数操作, 都依赖于快照, 例如, LevelDB 的每一次读取操作和遍历操作, 其内部都必须创建一个快照, 所以, 对于一个请求量非常大的系统, 数据库内核每秒种就要创建和销毁几十万次快照. 因此, 如何快速地创建和销毁快照, 成为一个数据库内核(引擎)必须要解决的问题.

    本文从源头出发, 逐步推演, 探讨数据库内核是如何实现快照技术的. 数据库内核创建快照, 将使用如下技术:

    1. 全量拷贝(Full Clone)
    2. 写时拷贝(Copy On Write)
    3. 分区拷贝(Partitioning)
    4. 多版本(Multi Versioning, Leveling, Zero Copy)

    无论何种实现快照的技术, 数据拷贝都不可避免, 差异点主要是不同的技术拷贝的数据量不同, 以及拷贝的数据含义不同(直接拷贝和间接拷贝). 直接拷贝意味着拷贝数据本身, 间接拷贝则拷贝数据的"指针".

    拷贝意味着互斥, 独占, 加锁, 因为拷贝需要保证数据的完整性. 硬盘数据拷贝速度是较慢的, 往往被认为不可接受, 应极力避免. 内存数据拷贝速度较快, 但仍然需要减少拷贝的数据量.
    Continue reading »

    Posted by ideawu at 2021-06-04 22:10:51
  • 2021-06-03

    分布式数据库系统如何做到平滑缩扩容?

    Views: 4331 | No Comments

    分布式数据库系统的缩扩容能力(后面也称迁移)是最基础最基本的特性, 但是, 要实现平滑扩容并不容易, 需要服务端和客户端共同完成, 这两者只要缺少任何一方的参与和配合, 便绝不可能实现平滑扩容.

    平滑迁移要解决的问题, 本质上就是故障容错(转移)处理.

    客户端请求重试

    请求重试是故障容错的最基础要求, 因为你永远无法避免遇到故障. 遇到故障时, 要么报错, 要么重试. 既然我们追求的是平滑, 那么, 一旦遇到故障, 绝对不能向上层反馈, 只能重试.

    重试要配合服务发现, 不然故障点一直不恢复的话, 重试也没用.

    重试策略的关键在于识别出可重试的故障, 对于某些故障, 如网络故障, 客户端无法确保请求到底有没有实际发出去, 或者已经被服务端处理, 冒然重试, 会导致非预期的后果.

    实际上, 所有的接口的结果不是一般人所理解的两态(成功或者失败), 而是三态(成功, 失败, 未知). 对于未知结果, 我们什么也做不了, 只能向上反馈(向业务层报错), 这种情况, 无法重试, 也就无法容错.
    Continue reading »

    Posted by ideawu at 2021-06-03 22:41:55
  • 2021-05-30

    数据库内核的并发控制

    Views: 2944 | No Comments

    大部分程序员最先接触并发编程, 一般是从编程语言里的多线程和锁开始. 但是, 并发控制是一种广义的技术思想, 千万不可将眼光局限于编程语言所提供的锁. 将编程语言里的并发控制技术推广, 就能得到任何层面的并发控制技术.

    以操作一个文件为例, 如果不做并发控制, 就会遇到数据完整性问题. 例如, 我们写入的一项数据, 对应着现实对象, 如果不做并发控制, 那么可能读到的是两项数据的混合体, 或者只读到一项数据的部分.

    互斥锁

    互斥锁是最简单的并发控制技术, 无论读还是写, 通通进行排队, 一次只处理一个请求(读或者写). 这种技术实现起来简单, 不容易出 bug, 如果为了快速实现, 可以采用此技术. 但是, 因为涉及到排队串行化, 所以在很多实际场景中, 这种技术会非常低效.

    以操作一个文件为例, 给文件加一把互斥锁(任何层面的锁, 未必和编程语言或者操作系统所提供的锁对应). 当想要往文件中写入数据时, 先获取锁, 然后写入. 同样, 想要从文件中读取数据时, 先获取锁, 然后读.
    Continue reading »

    Posted by ideawu at 2021-05-30 00:36:26
|<<<1234>>>| 2/4 Pages, 24 Results.