CockroachDB_DB商城

2022-09-20 11:22:37 浏览数 (3)

概述

  • CockroachDB是一个分布式关系型数据库,主要设计目标是可扩展,强一致和高可靠。
  • 在无人干预情况下, 能以极短的中断时间容忍磁盘、主机、机架甚至整个数据中心的故障。
  • 采用完全去中心化架构, 集群中各个节点的地位完全对等。
  • 所有功能封装在一个二进制文件中, 可以做到尽量不依赖盘配置文件直接部署。
  • 对外提供标准SQL接口,集群中任意节点都可以作为接入节点处理用户的SQL请求。
    • 接入节点把SQL请求转换为KV操作,并且在必要时将该操作发送至其它节点进行处理,完成后将结果返回给客户端。
    • CockroachDB底层将数据组织成有序的Key-Value对形成一个KV map,其中Key和Value均为字节串。
    • KV map逻辑上按照范围被切分成大量的Key空间,每个Key空间称为Range。
    • 每个Range数据由本地KV存储引擎(RocksDB,LevelDB的变体)存储。
    • 每个Range被复制多份分布到多个CockroachDB节点上,Range副本数量可配置。
    • 每个Range默认大小为64M,合理的Range大小有利于加速节点故障恢复和扩容,及均衡读写负载。
    • Range大小应该根据系统压力进行设置,以便管理更多Range。
  • 支持水平扩展
    • 添加更多节点可以提升整个集群的存储容量, 理论上最大可以支撑4EB的数据存储
    • 客户端的查询请求可以发送到集群任意节点, 且每个查询可独立并发执行, 集群的吞吐能力可以随着节点数的增加线性提升。
    • 查询以分布式任务的方式在各个数据节点并发执行,可以通过增加节点数来提升单个查询的性能。
  • 支持强一致性
    • Range的多个副本之间使用Raft一致性协议, 所有一致性状态都存储在RocksDB中。
    • 对同一个Range内数据的单一或批量修改, 由Raft保证Range操作的ACID语义。
    • 涉及多个Range的操作, CockroachDB使用高效的无锁分布式事务保障ACID语义。
  • 支持高可用
    • 将Range副本分布在一个数据中心, 可以确保低延迟复制, 同时能容忍磁盘或机器故障。
    • 如果将副本分布在不同机架, 即使某些网络交换机故障, CockroachDB仍可提供服务。
    • Range副本可以跨数据中心和跨地域分布, 以应对来自数据中心电源中断或网络中断, 以及区域电力故障等问题。
  • 隔离级别
    • 基于历史快照时间和当前时间, 提供外部一致的无锁读写。
    • 快照隔离(SI) [Snapshot Ioslation]
      • SI提供无锁读写, 但是存在写偏序问题(write skew)
    • 串行快照隔离(SSI) [Serializable Snapshot Isolation]
      • SSI消除了写偏序, 但在竞争激烈的系统中会存在性能问题
    • SSI是默认的隔离级别, 用户须根据实际性能情况, 选择合适的隔离级别。CockroachDB只提供有限的linearizability(严格的顺序一致性)。

架构

  • 架构图

  • 采用分层架构
  • SQL层
    • CockroachDB支持标准SQL, 当CockroachDB集群的某个节点收到SQL请求时,会经过SQL解析、SQL执行计划生成、SQL执行等重要步骤。
    • CockroachDB兼容PostgreSQL协议,对于报文的封装和解析完全按照PostgreSQL的方式进行,所以用户可以直接使用PostgreSQL的客户端访问CockroachDB。
    • CockroachDB对于用户的SQL语句按照PostgreSQL的语法进行解析,解析完成后生成抽象语法树(AST)
    • CockroachDB 会根据不同的语法树生成对应的执行计划。目前执行计划基本是基于规则的方式来生成的。
      • 对于OLAP的SQL Statement, CockroachDB会将逻辑计划转化为物理执行计划,即通过分布式任务的方式进行并行执行。
    • 当执行计划生成完毕后,CockroachDB会按照约定的方式开始执行,此时CockroachDB将调用事务性的KV接口。执行完成后通过协议层将执行结果返回给客户端。
  • 分布式KV存储
    • 负责Range路由寻址,提供统一的key-value存储。
    • 可以由任意数量的CockroachDB物理节点组成,每个节点包含一个或多个Store(通常一个Store独占一块磁盘)
    • 每个Store包含多个Range,Range为KV层数据管理的最小单元,每个Range的多个副本之间使用Raft协议进行同步
    • Range示意图
    • 这个其实可以类比下hdfs的分片和elasticSearch的分片, 思想上都是相似的。
    • 节点和Range可以根据不同的物理网络拓扑结构进行编排,从而在可靠性和性能之间折衷。
    • 假设一个Range包含三个副本,每个副本可以位于不同的位置:
      • 如果副本分布于同一台服务器上的多块磁盘,可以容忍单块磁盘故障。
      • 如果副本分布于同一机架上的不同服务器,可以容忍单台服务器故障。
      • 如果副本分布于同一个数据中心不同机架,可以容忍单个机架电源和网络故障。
      • 如果副本分布于不同数据中心,可以容忍大规模网络中断或断电。

关键字

  • CockroachDB key可以是任意字节数组
  • key有两种类型:系统表key和用户表key
    • 系统表key被CockroachDB用于内部数据结构和元数据。用户表key包含用户表数据(以及索引数据)
    • 系统表key和用户表key通过前缀区分,并保证系统表key始终小于用户表key
  • 系统表key有以下几种类型:
    • Global key存储集群级别的数据,例如“meta1”和“meta2” ,以及系统级别的key,例如节点和Store 的ID标识。
    • Store local key用于标识该Store的本地元数据(例如,StoreIdent结构),该部分元数据与所处Store生命周期相关,因此无需复制,即不会通过Raft同步到其它Store。
    • Range local key存储Range的元数据,并与Global key(实际存储层的全局Key)相关联。Range local key由一个特殊前缀,加Global key及一个特殊后缀组成。例如,事务记录是Range local key,形如: x01k txn- 。
    • Replicated Range ID local key存储Range元数据(RangeDescriptor),该元数据包含Range所有副本的元信息,这些元数据的变更会通过Raft同步。例如Range lease状态和事务的abort缓存记录。
    • Unreplicated Range ID local key存储该Range副本的元数据,例如Raft状态机的状态信息以及持久化后的Raft日志。
  • 用户表key用于存储所有非系统数据

多版本数据

  • CockroachDB维护了数据的历史版本,版本之间通过事务的提交时间戳区分。
  • 指定快照时间可以读取此时间戳之前的最新版本数据。
  • 所有版本都有一个最小有效期,当系统进行compaction时,过期的版本数据会被系统回收。
  • 为了防止长时间数据扫描(例如MapReduce)中历史数据被清理,用户也可自行指定数据有效期。
  • 通过RocksDB存储每个key的提交时间戳和GC有效期,支持多版本数据。

无锁分布式事务

  • CockroachDB提供无锁分布式事务
  • 支持的两种事务隔离界别
    • 快照隔离级别(SI)
      • 隔离级别实现简单,性能较好, 但是存在write skew 问题。
    • 串行化快照隔离级别(SSI)
      • 实现上稍微复杂一些, 但仍然能保证较高性能 (读写冲突严重的情况下稍弱), 但是不存在write skew问题。
  • 默认使用SSI隔离级别
    • 在对性能要求较高,并且没有write skew的情况下可使用SI隔离级别。
    • 在冲突较少的情况下,SSI和SI性能相当,不需要加锁或额外写操作。
    • 在冲突激烈的情况下,SSI仍然不需要加锁,但是会有更多事务被终止。
    • 在任何长事务场景中,SI和SSI都能防止事务饿死。
    • SI和SSI之间的核心区别在于事务提交时,SI允许事务的候选时间戳变大,而SSI不允许。
  • SI和SSI都要求缓存该Range上发生的读操作结果
    • 如果写操作时间戳比最近一次读操作时间戳要小, 则写操作失败。
    • 每个Range都有一个缓存 (timestamp cache), 保存该Range中key被读取的最新时间戳。
    • 读操作会更新相应的timestamp cache, 部分写操作 (例如Range删除) 也会更新timestamp cache。
      • timestamp cache中最老时间戳会被优先剔除。
  • 每一个CockroachDB事务开始时都会分配一个随机优先级和一个“候选时间戳”。
    • 候选时间戳是接收事务请求时节点分配的本地当前时间戳 (HLC), 作为事务提交的临时时间戳。
    • 如果没有事务冲突,在事务完成所有操作后,该时间戳会成为事务的最终提交时间戳。
  • 在跨多个节点的分布式事务执行过程中, 候选时间戳可能会变大, 但不会回退。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168034.html原文链接:https://javaforall.cn

0 人点赞