SequoiaDB巨杉数据库是一款面向金融行业的自研分布式数据库,支持多种主流关系型数据库实例、文档数据库实例以及S3对象存储等非结构化数据存储实例。核心开发团队成员来自前IBM DB2的北美研发团队、华为分布式存储团队,可谓实力雄厚。
前段时间有幸参加巨杉举办的“湖仓一体”高校技术宣讲会,萧少聪老师深入浅出地为我们介绍了数据库技术在金融行业的发展历程,以及该行业特有的痛点。其中提到的很有意思的一点是,我国拥有人口众多、网络基础设施完善的特点,所以金融信息系统每天产生的数据量是无可比拟的。作为信息系统基础支撑的数据库,自然也在这片土地上开出了不一样的花朵。
上个月月初巨杉数据库发布了SequoiaDB v5.2版本,在非结构化数据实时存取、分析能力上有了很大提升,优化了运维、监控等数据生命周期管理流程。完整的发布会视频请看:巨杉数据库SequoiaDB V5.2发布会
说到分布式数据库,早年谷歌的Bigtable、亚马逊的Dynamo都是面向K-V类型的非结构化数据。由于互联网应用自身的特点,为了获得更高的可用性,通常采取牺牲一致性的策略。保证最终一致性,用户不知道什么时候才能读取到最新的数据。但在金融行业,数据库如果只能提供较弱的分布式一致性和事务能力,很可能会给客户造成不可挽回的损失。因此如何让分布式数据库在拥有高并发和水平扩展能力的前提下,提供更完备的分布式事务能力,是数据库在金融行业应用的一个痛点。
另一方面,金融行业存在应用场景丰富、数据类型庞杂的特点。传统关系型数据库基于关系模型对数据进行管理,然而多元化的应用背景下,非结构化数据呈现爆发式增长的态势。为了应对多模数据存储难题,出现了以Data Lake为代表的新型技术。这种技术可以同时提供结构化和半结构化数据的弹性存储能力,却有着缺少事务和一致性保证的致命弱点。如果能让Data Lake和数据仓库融合,就能更好地满足金融行业对多模数据统一存储和检索能力的需求。
从以上两个问题切入,来看看巨杉数据库是如何实现兼容多模数据、支持分布式事务的同时,提供透明的弹性扩展能力,实现金融级服务能力。
要了解一个数据库,先看看它的整体架构划分为模块哪几个模块。
从模块划分上看,SequoiaDB总体可以划分为存储引擎和数据库实例两大模块:
实例和引擎分离可以提供更好的兼容性,在其它的关系型分布式数据库中也可以看到采用了类似的架构。
通常来说,上层的数据库实例负责实现负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。实例层本身无状态,运行过程中就可以启动多个实例,将请求可以均匀的分摊在多个实例上以达到负载均衡。
底层的数据库存储引擎支持弹性的扩容和缩容,数据分布在多个存储节点中。存储节点提供对分布式事务的原生支持,提供读未提交、读已提交以及读稳定性三个隔离级别。上层的数据库实例做完 SQL 解析后,将执行计划转换为实际对数据库实例API 的调用。
分布式数据库的每个模块都可以有多个节点,这些节点组成整个数据库集群。SequoiaDB的集群同样由多个节点组成,每个节点都是独立的进程,节点之间通过TCP/IP协议进行连接。通过指定不同的端口可以在同一台主机上部署多个节点,相互之间不会产生干扰。
SequoiaDB集群中,节点可以分为三种类型:
数据节点和编目节点中的数据以节点为单位复制了多份副本,分发到不同的节点中。拥有同一数据不同副本的几个节点组成复制组,复制组之间通过同步日志实现同步,猜测大概是类似于raft的机制。
SequoiaDB将数据拆分为不相交的多个小数据集进行管理,拆分的好处是方便做负载均衡和并行计算。拆分出来的小数据集通过复制形成复制组。分区方式有范围划分和哈希划分两种,两种方式都需要指定分区键,告诉数据库要以哪几个字段为依据进行划分。
SequoiaDB采用湖仓一体的新型架构,独特的数据存储和索引模型使Sequoia可以支持结构化、半结构化和非结构化数据的融合管理,底层支持多种数据类型存储,具备实时查询和分析的能力。
数据储存模型为数据建立了从逻辑概念到物理概念的映射,对json存储和块存储的支持,是实现多模数据统一管理的核心,与之相关的逻辑概念如下:
与结构化和半结构化数据存储相关的有以下三个核心逻辑概念:
集合空间由多个集合组成,每个集合通过链表将多个数据块连接起来,在查找时可以进行线性扫描。
与非结构化数据存储相关的逻辑概念有:
大对象依附于集合,系统会为每个大对象分配一个唯一的OID作为键值,进行查找时使用OID对对象进行检索。
索引作为管理数据的元数据,起到提高检索效率的作用,如果每次查询都对整个表进行线性扫描,用户很快就会变得难以忍受。
SequoiaDB中索引以B-tree形式组织,支持正序索引、倒序索引、唯一索引、复合索引等多种索引类型。在各个数据节点上还可以单独构建独立索引,独立索引不会被记录到管理元数据的编目节点。
比较有特点的是SequoiaDB通过Elasticsearch实现了全文索引。原理是建立词库,统计每个词条出现的频率和位置,在查询时就可以快速定位到关键词出现的位置。词库单独存储到Elasticsearch集群中,查询时协调节点将请求路由到数据节点,数据节点转发到Elasticsearch。Elasticsearch检索到索引信息返回给数据节点,数据节点根据信息查找到真实的数据,最后逐层返回给用户。
sdbseadapter负责数据节点与Elasticsearch集群交互的适配器,通俗的理解就是充当两个集群之间翻译官的角色。
了解完多模数据管理模型,接下来看看巨杉数据库是怎么实现分布式事务的。
在集中式数据库系统中,需要保证事务的ACID特性。然而将环境放到分布式数据库下,事务保证就变得加倍复杂。这种复杂性主要是由多副本,以及每个节点之间通过可能会出问题的网络进行交流所带来的。
SequoiaDB中通过事务日志记录所有的更改,每条日志有一个LSN,日志中记录了修改的类型、新旧值和一些其他的元信息。恢复和回滚通过扫描日志实现。在一个事务中只允许进行插入、删除和修改操作。除此之外的操作不会被记录到日志,因此在进行回滚时也不会考虑。
事务使用两阶段提交(2PL) 保证ACID特性:
步骤1和2属于就绪阶段,3和4属于提交阶段。就绪阶段完成后,就可以保证所有数据节点中不可能出现一部分节点没有完成事务,而另外一部分数据节点已经将事务提交的情况。这样在事务管理器发现某个数据节点上事务没有正常执行时,就可以安全地向所有节点发送回滚信息,保证ACID特性。
巨杉数据库中提供三种可选择的隔离级别:
三种隔离级别是通过悲观锁机制来实现的,为了提供更高的事务并发能力,支持意向锁。
事务需要对集合空间、集合和数据记录三个逻辑分层逐级加锁。对记录进行访问是,在集合空间和集合上需要加意向锁,访问的记录加事务锁。意向锁和事务锁的类别在此不做赘述,详细的描述可以从文档[隔离级别]一节找到。
通过不同的加锁协议,可以实现不同的隔离级别。不同的隔离级别下出现脏读、不可重复读以及幻读的情况也会有差异。
悲观锁实现简单,不需要占用额外的磁盘存储空间和进行复杂的垃圾回收。但是在处理大事务时难免会造成争用、阻塞、内存消耗的问题。SequoiaDB针对大事务下的悲观锁进行了一些优化:
巨杉数据库内部有多个控制线程负责处理控制逻辑,其中最重要的两个控制线程是负责数据持久化的脏页清除线程和日志写入线程。
SequoiaDB中使用MMAP机制将磁盘文件映射到内存,数据修改在内存中进行,数据的落盘时机由操作系统决定。用户也可以通过配置实现固定时间间隔或修改数量后主动触发落盘。
对数据库的操作会产生日志,日志先写入到缓冲区中,由日志持久化线程负责在后台将缓冲区中的日志刷到磁盘。
最后总结,从架构、数据模型和分布式事务实现可以看出,SequoiaDB是一个存算分离的原生分布式架构,具备灵活扩展、高性能及高并发特性。
上层通过与主流协议兼容,在引擎级别提供多模数据统一管理能力,支持灵活的多副本配置。对于金融行业这样存在系统更新换代需求的客户来说,使用SequoiaDB可以有效降低部署、迁移、运维的成本和风险。
高效灵活的分布式事务模型,避免了全局事务管理带来的瓶颈,读写性能可以按需在线扩展。在微服务架构和云平台改造的趋势下,SequoiaDB可以很好地满足上层应用对弹性扩展、高并发、高吞吐量的需求。
[1] 巨杉数据库SequoiaDB文档
[2] 巨杉数据库官网
[3] 巨杉数据库SequoiaDB V5.2发布会回放完整版
欢迎关注我的博客!