mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
581 lines
28 KiB
HTML
581 lines
28 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
||
<head>
|
||
|
||
<head>
|
||
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
|
||
<link rel="icon" href="/static/favicon.png">
|
||
|
||
<title>22 发展与局限:传统数据库在分布式领域的探索.md.html</title>
|
||
|
||
<!-- Spectre.css framework -->
|
||
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
|
||
<!-- theme css & js -->
|
||
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
|
||
<div class="book-sidebar">
|
||
|
||
<div class="book-brand">
|
||
|
||
<a href="/">
|
||
|
||
<img src="/static/favicon.png">
|
||
|
||
<span>技术文章摘抄</span>
|
||
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<div class="book-menu uncollapsible">
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="../">上一级</a></li>
|
||
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/00 开篇词 吃透分布式数据库,提升职场竞争力.md.html">00 开篇词 吃透分布式数据库,提升职场竞争力.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/01 导论:什么是分布式数据库?聊聊它的前世今生.md.html">01 导论:什么是分布式数据库?聊聊它的前世今生.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/02 SQL vs NoSQL:一次搞清楚五花八门的“SQL”.md.html">02 SQL vs NoSQL:一次搞清楚五花八门的“SQL”.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/03 数据分片:如何存储超大规模的数据?.md.html">03 数据分片:如何存储超大规模的数据?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/04 数据复制:如何保证数据在分布式场景下的高可用?.md.html">04 数据复制:如何保证数据在分布式场景下的高可用?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/05 一致性与 CAP 模型:为什么需要分布式一致性?.md.html">05 一致性与 CAP 模型:为什么需要分布式一致性?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/06 实践:设计一个最简单的分布式数据库.md.html">06 实践:设计一个最简单的分布式数据库.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/07 概要:什么是存储引擎,为什么需要了解它?.md.html">07 概要:什么是存储引擎,为什么需要了解它?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/08 分布式索引:如何在集群中快速定位数据?.md.html">08 分布式索引:如何在集群中快速定位数据?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/09 日志型存储:为什么选择它作为底层存储?.md.html">09 日志型存储:为什么选择它作为底层存储?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/10 事务处理与恢复(上):数据库崩溃后如何保证数据不丢失?.md.html">10 事务处理与恢复(上):数据库崩溃后如何保证数据不丢失?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/11 事务处理与恢复(下):如何控制并发事务?.md.html">11 事务处理与恢复(下):如何控制并发事务?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/12 引擎拓展:解读当前流行的分布式存储引擎.md.html">12 引擎拓展:解读当前流行的分布式存储引擎.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/13 概要:分布式系统都要解决哪些问题?.md.html">13 概要:分布式系统都要解决哪些问题?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/14 错误侦测:如何保证分布式系统稳定?.md.html">14 错误侦测:如何保证分布式系统稳定?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/15 领导选举:如何在分布式系统内安全地协调操作?.md.html">15 领导选举:如何在分布式系统内安全地协调操作?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/16 再谈一致性:除了 CAP 之外的一致性模型还有哪些?.md.html">16 再谈一致性:除了 CAP 之外的一致性模型还有哪些?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/17 数据可靠传播:反熵理论如何帮助数据库可靠工作?.md.html">17 数据可靠传播:反熵理论如何帮助数据库可靠工作?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/18 分布式事务(上):除了 XA,还有哪些原子提交算法吗?.md.html">18 分布式事务(上):除了 XA,还有哪些原子提交算法吗?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/19 分布式事务(下):Spanner 与 Calvin 的巅峰对决.md.html">19 分布式事务(下):Spanner 与 Calvin 的巅峰对决.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/20 共识算法:一次性说清楚 Paxos、Raft 等算法的区别.md.html">20 共识算法:一次性说清楚 Paxos、Raft 等算法的区别.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/21 知识串讲:如何取得性能和可扩展性的平衡?.md.html">21 知识串讲:如何取得性能和可扩展性的平衡?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
<a class="current-tab" href="/专栏/24讲吃透分布式数据库-完/22 发展与局限:传统数据库在分布式领域的探索.md.html">22 发展与局限:传统数据库在分布式领域的探索.md.html</a>
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/23 数据库中间件:传统数据库向分布式数据库的过渡.md.html">23 数据库中间件:传统数据库向分布式数据库的过渡.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/24 现状解读:分布式数据库的最新发展情况.md.html">24 现状解读:分布式数据库的最新发展情况.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/加餐1 概念解析:云原生、HTAP、图与内存数据库.md.html">加餐1 概念解析:云原生、HTAP、图与内存数据库.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/加餐2 数据库选型:我们该用什么分布式数据库?.md.html">加餐2 数据库选型:我们该用什么分布式数据库?.md.html</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
|
||
<div class="sidebar-toggle-inner"></div>
|
||
|
||
</div>
|
||
<script>
|
||
|
||
function add_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.add('show')
|
||
|
||
}
|
||
function remove_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.remove('show')
|
||
|
||
}
|
||
function sidebar_toggle() {
|
||
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let content = document.querySelector('.off-canvas-content')
|
||
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
|
||
sidebar_toggle.classList.remove('extend')
|
||
|
||
sidebar.classList.remove('hide')
|
||
|
||
content.classList.remove('extend')
|
||
|
||
} else { // hide
|
||
|
||
sidebar_toggle.classList.add('extend')
|
||
|
||
sidebar.classList.add('hide')
|
||
|
||
content.classList.add('extend')
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
function open_sidebar() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.add('show')
|
||
|
||
overlay.classList.add('show')
|
||
|
||
}
|
||
|
||
function hide_canvas() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.remove('show')
|
||
|
||
overlay.classList.remove('show')
|
||
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
|
||
<div class="columns">
|
||
|
||
<div class="column col-12 col-lg-12">
|
||
|
||
<div class="book-navbar">
|
||
|
||
<!-- For Responsive Layout -->
|
||
|
||
<header class="navbar">
|
||
|
||
<section class="navbar-section">
|
||
|
||
<a onclick="open_sidebar()">
|
||
|
||
<i class="icon icon-menu"></i>
|
||
|
||
</a>
|
||
|
||
</section>
|
||
|
||
</header>
|
||
|
||
</div>
|
||
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
|
||
overflow-x: auto;
|
||
|
||
overflow-y: hidden;">
|
||
|
||
<div class="book-post">
|
||
|
||
<p id="tip" align="center"></p>
|
||
|
||
<div><h1>22 发展与局限:传统数据库在分布式领域的探索</h1>
|
||
|
||
<p>从这一讲开始,我们进入实践(扩展)模块,目的是帮助你更了解现代分布式数据库,并且我会把之前学习的理论知识应用到实际案例中。</p>
|
||
|
||
<p>这个模块的讲解思路如下。</p>
|
||
|
||
<ol>
|
||
|
||
<li>传统数据库分布式:传统数据库,如 Oracle、MySQL 和 PostgreSQL 没有一刻放弃在分布式领域的探索。我会介绍分布式技术如何赋能传统数据库,以及它们的局限性。</li>
|
||
|
||
<li>数据库中间件:虽然中间件严格来说并不包含在数据库领域内,但它是很多用户首次接触分布式数据库的切入点,故在该领域有着不可代替的作用。我会介绍数据库中间件的功能,特别是处理事务的方式,它与模块三中介绍的分布式事务还是有差别的。</li>
|
||
|
||
<li>当代分布式数据库:该部分重点介绍目前大家能接触到的 NewSQL、DistributedSQL 类型的数据库。重点关注它们在异地多活、容灾等方面的实践。</li>
|
||
|
||
<li>其他类型数据库与数据库选型:查缺补漏为你介绍其他类型的分布式数据库,扩宽你的视野。最后结合金融、电信和电商等场景,为你介绍这些行业是如何选择分布式数据库的。</li>
|
||
|
||
</ol>
|
||
|
||
<p>以上就是本模块整体的讲解流程,那么现在让我们进入第一个问题的学习,来看看传统数据库如何进行分布式化改造。</p>
|
||
|
||
<h3>传统数据库分布式化</h3>
|
||
|
||
<p>我在模块一中介绍过,业务应用系统可以按照交易类型分为 OLTP 场景和 OLAP 场景两大类。OLTP 是面向交易的处理过程,单笔交易的数据量小,但是要在很短的时间内给出结果,典型场景包括购物、转账等;而 OLAP 场景通常是基于大数据集的运算,典型场景包括生成各种报表等。</p>
|
||
|
||
<p>OLTP 与 OLAP 两种场景有很大的差异,虽然传统数据库在其早期是将两者融合在一起的。但是随着它们向分布式,特别是 Sharding(分片)领域转型,OLAP 类型的数据逐步被抛弃,它们将所有的精力集中在了 OLTP 上。</p>
|
||
|
||
<p>OLTP 场景通常有三个特点:</p>
|
||
|
||
<ul>
|
||
|
||
<li>写多读少,而且读操作的复杂度较低,一般不涉及大数据集的汇总计算;</li>
|
||
|
||
<li>低延时,用户对于延时的容忍度较低,通常在 500 毫秒以内,稍微放大一些也就是秒级,超过 5 秒的延时通常是无法接受的;</li>
|
||
|
||
<li>高并发,并发量随着业务量而增长,没有理论上限。</li>
|
||
|
||
</ul>
|
||
|
||
<p>传统数据库,比如 MySQL 和 Oracle 这样的关系型数据库就是服务于 OLTP 场景的,但我们一般认为它们并不是分布式数据库。这是为什么呢?因为这些数据库传统都是单节点的,而我们说的分布式数据库都是多节点的。</p>
|
||
|
||
<p>传统关系型数据库是单机模式的,也就是主要负载运行在一台机器上。这样,数据库的并发处理能力与单机的资源配置是线性相关的,所以并发处理能力的上限也就受限于单机配置的上限。这种依靠提升单机资源配置来扩展性能的方式,被称为垂直扩展(Scale Up)。我们之前介绍过,垂直扩展是瓶颈的,因为物理机单机配置上限的提升是相对缓慢的。这意味着,在一定时期内,依赖垂直扩展的数据库总会存在性能的天花板。</p>
|
||
|
||
<p>那么传统数据库的单机模式可以变为分布式吗?答案是可以的。这些传统数据库在维持关系型数据库特性不变的基础上,可以通过水平扩展,也就是 Sharding 模式,增加机器数量、提供远高于单体数据库的并发量。这个并发量几乎不受单机性能限制,我们将这个级别的并发量称为“高并发”。这里说的“高并发”并没有一个具体的数字与之对应。不过,我可以给出一个经验值,这个“高并发”应该至少大于一万 TPS。</p>
|
||
|
||
<p>在 Sharding 之外,还需要引入可靠的复制技术,从而提高系统整体的可用度,这在金融级的容灾场景中非常重要。这些理念都是我在模块一中就强调过的,分片与同步才是分布式数据库的核心。</p>
|
||
|
||
<p>那么介绍完了传统数据库如何改造为分布式数据库的基本理念,现在让我们看看它们是如何具体操作的吧。</p>
|
||
|
||
<h3>商业产品</h3>
|
||
|
||
<p>我在“01 | 导论:什么是分布式数据库?聊聊它的前世今生”介绍过,商业数据库如 Oracle 通过底层存储的分布式达到数据分散的目的。其实这类数据库一直没有放弃对分布式领域的探索。现在我介绍一下 Oracle Sharding。</p>
|
||
|
||
<p>Oracle 数据库从 12.2 版本开始引入 Sharding 特性,集成了 NoSQL 和成熟的关系型数据库的优势,到如今已经过多个版本迭代,成为一整套成熟的分布式关系型数据库解决方案。Oracle Sharding 可以让用户将数据分布和复制到一组 Oracle 数据库集群中,集群中的数据库只需要网络连接,不需要共享软件和硬件。Oracle Sharding 可以为应用提供线性扩展能力和完全容错能力。</p>
|
||
|
||
<p>Oracle Sharding 主要包括下面这些组件。</p>
|
||
|
||
<ul>
|
||
|
||
<li>Sharded database(SDB):逻辑上 SDB 是一个数据库,但是物理上 SDB 包括多个物理独立的数据库,SDB 类似一个数据库池(pool),数据库池中包括多个数据库(Shard)。</li>
|
||
|
||
<li>Shards:SDB 包括多个物理独立的数据库,每一个数据库都称为 shard,每个 shard 数据库位于不同的服务器。这些 Shard 被部署在独立的机器上,每个 shard 数据库中保存表的不同数据集,但是每个 Shard 中都有相同的列,也就是说这些 Shard 是按行进行分片的。</li>
|
||
|
||
<li>Shard catalog:是一个 Oracle 数据库,用于集中存储管理 SDB 配置信息,是 SDB 的核心。SDB 配置变化,比如添加/删除 shard 等,都记录在 Shard catalog。如果应用查询多个 shard 中的数据,那么由 Shard catalog 统一协调分配。Shard catalog 需要进行 HA,也就是高可用部署。因为里面的数据非常重要,一旦丢失,会造成整个数据库不可用。</li>
|
||
|
||
<li>Shard directors:Global Data Service(GDS)实现对 Sharding 的集中部署和管理。GSM 是 GDS 的核心组件,GSM 作为 Shard director。GSM 类似监听器,将客户端对 SDB 的请求路由到对应的 shard,负载均衡客户端的访问。</li>
|
||
|
||
</ul>
|
||
|
||
<p>Oracle Sharding 优点如下。</p>
|
||
|
||
<ul>
|
||
|
||
<li>线性扩展:因为每个 shard 是一个独立的数据库,通过增加新的 Shard 节点,来线性扩展性能,自动 rebalance 数据。</li>
|
||
|
||
<li>失败隔离:由于 Shard 是一种 shared-nothing 技术,每个 shard 使用独立的硬件,因此一个 shard 节点出现故障,只会影响到这个 shard 存放的数据,而不会影响到其他 shard。</li>
|
||
|
||
<li>按照地理位置分布数据:可以选择根据地理位置不同,将数据存储在不同的 shard。</li>
|
||
|
||
</ul>
|
||
|
||
<p>除了以上的优点,其缺点也非常明显。</p>
|
||
|
||
<ul>
|
||
|
||
<li>用户设计复杂:不同于传统的 RAC 模式,Sharding 需要用户对表进行严格设计,从而才能发挥该模式扩展性与可用性方面的优势。同时,对于老系统迁移,这往往意味着要修改现有代码。</li>
|
||
|
||
<li>跨分片性能低:跨分片事务,聚合查询的性能很低。一般比单分片低 10%。</li>
|
||
|
||
</ul>
|
||
|
||
<p>最后一个缺点就是商业数据库的老问题,性价比低。这个我在后面会进一步阐述。</p>
|
||
|
||
<p>那么商业方案看起来很好,但是如果你更喜欢开源的解决方案,下面我会介绍开源传统数据库对这个问题的思考。</p>
|
||
|
||
<h3>开源定制</h3>
|
||
|
||
<p>单体开源数据要向分布式数据库演进,就要解决写入性能不足的问题。</p>
|
||
|
||
<p>最简单直接的办法就是分库分表。分库分表方案就是在多个单体数据库之前增加代理节点,本质上是增加了 SQL 路由功能。这样,代理节点首先解析客户端请求,再根据数据的分布情况,将请求转发到对应的单体数据库。代理节点分为“客户端 + 单体数据库”和“中间件 + 单体数据库”两个模式。</p>
|
||
|
||
<p>客户端组件 + 单体数据库通过独立的逻辑层建立数据分片和路由规则,实现单体数据库的初步管理,使应用能够对接多个单体数据库,实现并发、存储能力的扩展。其作为应用系统的一部分,对业务侵入比较深。这种客户端组件的典型产品是 Apache ShardingShpere 的 JDBC 客户端模式,下图就是该模式的架构图。</p>
|
||
|
||
<p><img src="assets/CioPOWBhewWAL2D3AADkzhnu3iE396.png" alt="Drawing 0.png" /></p>
|
||
|
||
<p>Apache ShardingShpere 的 JDBC 客户端模式架构图</p>
|
||
|
||
<p>代理中间件 + 单体数据库以独立中间件的方式,管理数据规则和路由规则,以独立进程存在,与业务应用层和单体数据库相隔离,减少了对应用的影响。随着代理中间件的发展,还会衍生出部分分布式事务处理能力。这种中间件的典型产品是 MyCat、Apache ShardingShpere 的 Proxy 模式。</p>
|
||
|
||
<p><img src="assets/CioPOWBhexWAcIBeAAJA7FyRXw0760.png" alt="Drawing 1.png" /></p>
|
||
|
||
<p>Apache ShardingShpere 的 Proxy 模式架构图</p>
|
||
|
||
<p>代理节点需要实现三个主要功能,它们分别是客户端接入、简单的查询处理器和进程管理中的访问控制。另外,分库分表方案还有一个重要的功能,那就是分片信息管理,分片信息就是数据分布情况。不过考虑分片信息也存在多副本的一致性的问题,大多数情况下它会独立出来。显然,如果把每一次的事务写入都限制在一个单体数据库内,业务场景就会很受局限。</p>
|
||
|
||
<p>因此,跨库事务成为必不可少的功能,但是单体数据库是不感知这个事情的,所以我们就要在代理节点增加分布式事务组件。同时,简单的分库分表不能满足全局性的查询需求,因为每个数据节点只能看到一部分数据,有些查询运算是无法处理的,比如排序、多表关联等。所以,代理节点要增强查询计算能力,支持跨多个单体数据库的查询。更多相关内容我会在下一讲介绍。</p>
|
||
|
||
<p>这时离分布式数据库还差重要的一步,那就是逻辑时钟。我们在分布式系统模块已经介绍了逻辑时钟的意义,它是实现数据一致性的必要条件。加上这最后一块拼图,这类分布式数据库区别于单体数据库的功能也就介绍完整了,它们是分片、分布式事务、跨节点查询和逻辑时钟。</p>
|
||
|
||
<p>这类数据库一般以 MySQL 或 PostgreSQL 为基础进行开发。MySQL 类的解决方案有 TDSQL、Vitess 和具有 JDTX 的 ShardingShpere。PGXC(PostgreSQL-XC)的本意是指一种以 PostgreSQL 为内核的开源分布式数据库。因为 PostgreSQL 的开放软件版权协议,很多厂商在 PGXC 上二次开发,推出自己的产品。不过,这些改动都没有变更主体架构风格,所以我把这类产品统称为 PGXC 风格,其中包括 TBase、GuassDB 和 AntDB 等。</p>
|
||
|
||
<p>以上我们讨论了开源领域中传统数据库在分布式领域中的尝试。但是,此类方案是有一些局限的,看看都有哪些。</p>
|
||
|
||
<h3>局限</h3>
|
||
|
||
<p>目前传统数据库在分布式领域内的探索,我们可以总结为“<strong>商业靠实力而开源靠合作</strong>”,它们分别打开了自己的一片天地。但是,它们长久的技术积累不仅带来了功能的丰富,同时一些局限也是其无法克服的。</p>
|
||
|
||
<ol>
|
||
|
||
<li><strong>性价比</strong>。以 Oracle Sharding 为代表的商业解决方案,虽然功能很完善,同时能满足多种场景,对传统 Oracle 用户有极强的吸引力。但是其费用与收益其实是不成正比的,其对分片事务支持有限,同时跨分片查询性能很低。这些重要功能的缺失与其高昂的售价相比是极不相称的。故商业的 Sharding 方案一直没有成为主流。</li>
|
||
|
||
<li><strong>事务</strong>。由于传统数据库都需要复用原有的存储节点,故事务方案大多都是我们介绍过的两阶段提交这类原子提交协议。学习过模块三中分布式事务的同学都清楚,传统两阶段在性能和规模上都有很大的限制,必须采用新的事务模式才能突破这层天花板。而传统数据库的底层被锁死,很难在这个领域有更好的表现。</li>
|
||
|
||
<li><strong>OLAP</strong>。传统数据库在转为分布式之前能很好地支持 OLAP。但其 Sharding 后,该过程变得越来越困难。同时随着大数据技术的崛起,它们有主动放弃该领域的趋势。而新一代的 HTAP 架构无一例外都是 NewSQL 和云原生数据库的天下,这个领域是从传统数据库发展而来的分布式数据库无法企及的。</li>
|
||
|
||
</ol>
|
||
|
||
<p>以上我们谈的传统数据库在分布式领域的局限其实总结为一点就是,<strong>它们的底层存储引擎限制了其上层分布式功能的拓展</strong>。只有如 NewSQL 类数据库一般,使用创新的存储引擎,才能在整体上打造出功能与性能匹配的现代分布式数据库。但是,此类数据库由于发展多年,在稳定性、维护性上有不可动摇的优势,即使存在一些局限性,但其对单机版本的用户依然有很强的吸引力。</p>
|
||
|
||
<h3>总结</h3>
|
||
|
||
<p>这一讲,我们介绍了传统单机数据库向分布式数据库的转型尝试,它们一般经过分片、复制、分布式事务和物理时钟等过程的改造,从而打造以单体数据库为数据节点的分布式数据库。</p>
|
||
|
||
<p>同时我们也讨论了此类数据库的天花板,因此应该从底层去构建分布式数据库,就像 NewSQL 类数据库,才是分布式数据库发展的正途。</p>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/21 知识串讲:如何取得性能和可扩展性的平衡?.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/24讲吃透分布式数据库-完/23 数据库中间件:传统数据库向分布式数据库的过渡.md.html">下一页</a>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
|
||
</div>
|
||
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70996e25bae63d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
|
||
</body>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
|
||
<script>
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
|
||
dataLayer.push(arguments);
|
||
|
||
}
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'G-NPSEEVD756');
|
||
|
||
var path = window.location.pathname
|
||
|
||
var cookie = getCookie("lastPath");
|
||
|
||
console.log(path)
|
||
|
||
if (path.replace("/", "") === "") {
|
||
|
||
if (cookie.replace("/", "") !== "") {
|
||
|
||
console.log(cookie)
|
||
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
setCookie("lastPath", path)
|
||
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
|
||
var d = new Date();
|
||
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
|
||
var expires = "expires=" + d.toGMTString();
|
||
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
|
||
}
|
||
function getCookie(cname) {
|
||
|
||
var name = cname + "=";
|
||
|
||
var ca = document.cookie.split(';');
|
||
|
||
for (var i = 0; i < ca.length; i++) {
|
||
|
||
var c = ca[i].trim();
|
||
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
|
||
}
|
||
|
||
return "";
|
||
|
||
}
|
||
</script>
|
||
</html>
|
||
|