OceanBase设计规范与数据架构指南v213.docx
- 文档编号:3813803
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:22
- 大小:1.08MB
OceanBase设计规范与数据架构指南v213.docx
《OceanBase设计规范与数据架构指南v213.docx》由会员分享,可在线阅读,更多相关《OceanBase设计规范与数据架构指南v213.docx(22页珍藏版)》请在冰点文库上搜索。
OceanBase设计规范与数据架构指南v213
OceanBase设计规范与数据架构指南
版本0.1
文档修订历史
版本号
作者
备注
修订日期
V0.1
泓影
初稿
2017-06-29
V0.2
泓影
修正细节
2017-07-13
1OceanBase1.0简介
自从E.F.Codd于1970年首次提出关系数据库模型后,关系数据库便以其易于使用的接口、完善的功能和生态而成为了IT领域必需的基础设施,广泛应用在各行各业,包括金融、电信、房地产、农林牧渔、制造业等等。
关系数据库经过了40多年的发展,涌现了Oracle、SQLServer、DB2等优秀的商业数据库产品,开源领域也不乏MySQL、PostgreSQL这样的精品。
但是,随着互联网行业和大数据的兴起,数据量和并发访问量呈现指数级的增长,囿于关系数据库的架构,原先运行良好的关系数据库遭遇了严峻的挑战:
极度高昂的总体拥有成本、捉襟见肘的扩展能力、荏弱无力的大数据处理性能等等。
于是NoSQL应运而生,Hbase、Cassandra等系统如雨后春笋般冒出,这些系统多采取分布式架构,易于扩展及容灾,结合大数据处理系统如Hadoop等,可以很容易处理量级非常大的数据,这一时让NoSQL风光无两,大有取代SQL之势,让人看不清NoSQL系统的边界。
很多公司尝试将核心系统迁移到新兴的NoSQL系统上,比如Facebook就尝试将部份核心系统迁移到Cassandra。
在迁移过程中,人们发现NoSQL所获得针对SQL的优势其实是以牺牲一些非常重要的功能来获取的,如NoSQL一般不支持事务或只支持非常有限的事务,这极大的增加了业务系统的复杂度,在传统的OLTP领域采取NoSQL系统基本上是不可以接受的。
阿里巴巴/蚂蚁金服的关系数据库使用场景极其严苛,有着全球最大的并发量需求,在可靠性方面需要做到单机、机架、机房甚至是地区级别的容灾恢复能力。
早期使用共享存储、小型机等高端硬件也只能部分满足我们在性能和可靠性上的需求,而且随着业务的发展,这种IOE架构很快就成为瓶颈。
我们能不能结合新兴分布式系统和传统关系型数据库的优点,既拥有传统关系型数据库在功能上的优势,同时具备分布式系统的可扩展性、高可靠性等特征?
OceanBase即是以此为出发点,开始打造一个分布式关系型数据库。
OceanBase从2010年6月份立项开始到今天已经发展了六年多的时间,构建在普通服务器组成的分布式集群之上,具备可扩展、高可用、高性能、低成本以及多租户等核心技术优势。
目前已经成功应用于蚂蚁金服的会员、交易、支付、账务、计费等核心系统和网商银行等业务系统。
OceanBase经历了多年(2011-2016)双十一的严格考验,特别是在刚刚过去的2016年双十一,用户每一笔支付订单背后的数据和事务处理都由OceanBase完成,创造了每秒12万笔支付峰值的世界记录。
2OceanBase架构及优势
互联网对传统关系型数据库的挑战主要有两个方面:
一是可扩展性。
传统关系型数据库本质上是单机系统,其扩展方法一般为向上扩展,即换性能更好的机器,阿里巴巴/蚂蚁金服随着业务的发展,也一路扩容到小型机,但这种方式对于互联网行业来说,其扩容周期短,成本很高。
另外一种方法为水平拆分,即分库分表,这也是目前广泛应用的扩展方式,这极大的增加了业务复杂度,相当于将数据库的一部份工作转嫁到业务方,从各大公司都有自己的中间件来处理这一层业务即可见一斑。
二是可靠性。
传统关系型数据库一般采取主备形式来解决高可用的问题。
主备之间数据同步主要有两种方式,一是最大保护模式,需要主备均写入成功后才算成功,这样可以保证数据一致性,但一旦备机宕机或网络抖动即可造成不可用。
另外是最大性能/最大可用模式,这种模式下只要主写入成功即可算成功,此时如果主机宕机,但有数据尚未同步到同机,即可造成数据不一致或丢失。
解决这个问题的传统方案是采取高端商用硬件如共享存储,通过高可靠的硬件来解决软件上的不可靠,但这样也会存在一些问题,比如共享存储无法解决或很难解决机房容灾问题。
OceanBase的目标是要解决这两方面的问题,设计原则:
∙使用普通PC服务器,不使用共享存储、小型机等高端硬件。
∙磁盘、服务器、网络、机房甚至是某个地区的IT基础设施并非持续可用。
∙关系型数据库,支持传统关系型数据库的功能,比如SQL、跨行跨表事务。
∙可水平扩展,扩展时对应用透明。
∙高可靠、数据强一致,单机、机房甚至地区故障时可自动恢复。
∙高性能。
根据目标,OceanBase需要解决三个方面的问题:
一是传统关系型数据库的功能。
传统关系数据库经过多年的发展,功能极其丰富,SQL的表达能力、事务支持等对应用非常友好,并且形成了自己的生态。
OceanBase需要从头开始实现,一个可能的选择是基于某个开源数据库来实现,但经过分析,基于控制力、架构等原因,我们最终没有选择这条路,而是完全自主研发。
二是分布式一致性问题。
分布式系统往往通过多个副本来实现数据高可靠以及高可用,如何保证多个副本之间的数据一致性是一个非常复杂的问题。
最大保护模式的基础是高可用的硬件及网络链路,这些在OceanBase中都不存在。
三是分布式事务的问题。
很多分布式系统都弱化了这个功能,只支持单行事务,这样的选择一方面是工程实现难度较高,另外一方面是对性能影响较大,OceanBase如何支持跨机分布式事务并保证性能是一个很大的问题。
OceanBase解决这些问题也并非一蹴而就,而是着眼于业务需求,通过六年的发展,才逐步解决了这些问题,OceanBase总体架构:
如上图所示,一个OceanBase集群由多台分布在不同机房的ObServer组成,每台ObServer都是对等关系,图中分布在三个IDC,意味着存储了三个副本,每个IDC是镜像的关系,可抵御少数派IDC失败。
每个表可以以分区表(即createtable中的partitionby子句)的形式分成多个分区,图中一个表被分成了P1~P88个分区,每个分区可以分布在不同的ObServer上,每个分区的三个副本分布在不同IDC的不同ObServer上,其中一个副本被选举为Leader,如图中P2,P3的Leader在IDC1的第一台ObServer上。
只有分区的Leader才可以对外提供查询和更新服务。
ObProxy是一个无状态服务,它接收应用的请求并根据应用请求中的分区字段来判断这个请求属于哪个分区,然后将其路由到这个分区Leader所在的服务器。
让用户无需关心数据分片的细节,数据所在的具体位置,对外的表现仍然是一个单机的数据库。
OceanBase兼容MySQL协议,通过ObProxy,用户可以使用任意语言的MySQL客户端来连接OceanBase。
经过六年多的发展,OceanBase初步实现了当初定下的目标,在架构上具有诸多优势:
2.1.1高效的存储引擎
OceanBase采用的是share-nothing的分布式架构,每个OBServer都是对等的,管理不同的数据分区。
单机的存储引擎采取读写分离的架构,将当前更新的动态数据存入内存称为MemTable,存量的基线数据存在磁盘,称为SSTable。
一个Partition的所有数据(基线数据+增量数据+事务日志)都放在一个OBServer中,因此针对一个Partition的读写操作不会有跨机的操作,数据的写入也分布到多点并行执行。
读写分离的存储结构带来很多好处,因为有大量的静态基线数据,可以很方便对其进行压缩,减少存储成本;另外做行级缓存也不用担心写入带来的缓存失效问题。
缺点是读的路径变长,数据需要实时合并可能带来性能问题,OceanBase采用了很多的优化手段,比如bloomfiltercache对不存在的行做过滤(insertrow判断行是否存在无需IO操作),尽量优先读取更新的内容(ActiveMemTable),如果发现用户读取的列已经读取到,则无需进一步读取基线数据进行合并。
由于增量数据写在内存中,所以内存写到一定量后需要和基线数据合并而生成新的基线,这个过程我们称之为合并,合并会造成一些额外的压力,可能对客户的请求有影响,所以我们采取一种称之为轮转合并的策略,即将OceanBase的多个IDC中的其中一个IDC的流量切走,进行合并,待合并完成后再将流量切到已合并的IDC上,这样可以避免对业务的影响,同时这种策略也可以用在升级维护中,当需要进行版本升级的时候,可以将其中一台ObServer的流量切走进行升级,升级完成后逐步灰度切流,一旦出现问题即可快速无损回滚。
2.1.2可扩展性
分布式系统通过数据分区来实现可扩展性,主流数据分区方法有两种:
哈希分区和范围分区。
分布式Key-Value系统、数据库分库分表本质上都是哈希分区;而主流的分布式表格系统,如Bigtable、开源的HBase往往采用范围分区。
范围分布很容易出现分区不均匀的情况,因此,需要支持分区动态分裂与合并。
关系数据库的数据分布方法则更为灵活,以Oracle分区表为例,除了支持简单的哈希分区、范围分区,还支持list分区、Interval分区,以及二级组合分区。
另外,关系数据库还支持单个分区的操作,例如删除某个分区,构建针对单个分区的局部索引、设置压缩方法,等等。
OceanBase引入了传统关系型数据库中的数据分区表的方法,语法上也兼容传统数据库创建分区表的方法,这种设计兼具分布式系统的扩展性和关系数据库的易用性和灵活性,符合DBA的使用习惯。
OceanBase支持在线线性扩展,当集群存储容量或是处理能力不足时,可以随时加入新的OBServer,系统会自动进行数据迁移,根据机器的处理能力,将合适的数据分区迁移到新加入的机器上;同样在系统容量充足和处理能力富余时,也可以将机器下线,降低成本;在类似于双11大促之类的活动中,可以提供良好的弹性伸缩能力。
对一个数据分区所有读写操作都在其所在的OBServer完成,涉及多个数据分区的事务,会采用两阶段提交的方式在多个OBServer上执行。
在OceanBase中,事务分为几种类型:
∙单分区事务。
和传统的关系数据库一样,属于单机事务,不需要走两阶段提交协议。
∙单机多分区事务。
需要走两阶段提交协议,且针对单机做了专门的优化。
∙多机多分区事务。
需要走完整的两阶段提交协议。
分布式事务会增加事务的延时,OceanBase采取了很多措施来尽量避免分布式事务,比如支持表格组(tablegroup)来尽可能地减少分布式事务。
表格组用于聚集经常一起访问的多张表格。
例如,有用户基本信息表(user)和用户商品表(user_item),这两张表格都按照用户编号哈希分布,只需要将二者设置为相同的表格组,系统后台就会自动将同一个用户所在的user表分区和user_item表分区调度到同一台服务器。
这样,即使操作某个用户的多张表格,也不会产生跨机事务。
2.1.3高可靠
OceanBase系统中的每个分区都维护了多个副本,一般为三个,且部署到三个不同的数据中心(Zone)。
整个系统中有成百上千万个分区,这些分区的多个副本之间通过Paxos协议进行日志同步。
每个分区和它的副本构成一个独立的Paxos复制组(PaxosReplicationGroup),其中一个副本为主(Leader),其它副本为备(Follower)。
每台ObServer服务的一部分分区为Leader,一部分分区为Follower。
当ObServer出现故障时,Follower分区不受影响,Leader分区的写服务短时间内会受到影响,直到通过Paxos协议将该分区的某个Follower选为新的Leader为止,整个过程大约持续30秒左右。
通过引入Paxos协议,可以保证在数据强一致的情况下,具有极高的可用性及性能。
2.1.4多租户
OceanBase1.0系统作为一个扩展性很强的集群系统,设计的目标就包括使用一个集群支持多个业务系统,也就是通常所说的多租户特性。
数据库多租户概念,Oracle是从12C版本开始支持的,在Oracle里面,最重要的两个概念是CDB(ContainerDB)和PDB(PluggableDB)。
对于OceanBase1.0来说,多租户同样是一个非常重要的特性,是数据库对象管理和资源管理的基础;对于系统运维,尤其是对于将来的云数据库的运维也有着重要的影响。
OceanBase1.0的多租户特性,主要包含如下几点:
∙将多个数据库实例管理和运维的成本和复杂性降低到和一个数据库实例相当。
1.0的其中一个优势就是大集群的规模优势,取得这个优势的一个重要原因就是原先的多个数据库实例,在1.0版本中管理的成本相当于一个实例。
o充分利用系统资源,使得同样的资源可以服务更多的业务。
通过将波峰、波谷期不同的业务系统部署到一个集群,以实现对系统资源最大限度的使用。
o租户之间的隔离性:
在数据安全方面,不允许跨租户的数据访问,确保用户的数据资产没有泄露的风险;在资源使用方面表现为租户“独占”其资源配额,该租户对应的前端应用,无论是响应时间还是TPS/QPS都比较平稳,不会受到其他租户负载轻重的影响。
OceanBase所采取的隔离方式,既能充分利用资源,又可以获取非常高的资源整合度。
多租户的特性使得OceanBase非常适合云计算。
2.1.5MySQL兼容
关系数据库经过多年的发展,其周边生态十分重要,大量的现有业务都构建在现有的关系型数据库上,OceanBase采取和MySQL兼容的方式来让基于MySQL的应用程序可以不经修改就能运行在OceanBase之上。
OceanBase在兼容性方面做了大量的工作:
∙接口层面:
主流的数据库产品都支持标准的接口如JDBC、ODBC、.netProvider。
OceanBase广泛使用的接口主要是JDBC和ODBC。
通过不断增强在前后台协议上和MySQL的兼容性,目前,使用MySQL的驱动就可以无障碍地访问OceanBase。
∙数据模式层面:
完整地支持了数据库(database)、表(table)、视图(view)、自增列(autoincrement)等SQL标准的以及MySQL专有的数据模式,并且在数据库系统中实现了多租户(multi-tenant)。
原先基于不同MySQL实例的业务可以无缝地迁移到一个OceanBase集群。
∙语句层面:
目前的主流产品在SQL语句层面大多遵守ISO/IEC9075标准定义的一系列规范,最新的版本是SQL2011。
对比之前的版本,1.0版本大幅度增加了对标准SQL语句的支持,同时扩展了支持了MySQL中有但非标准的语句。
∙数据类型层面:
数据类型是基础设施,对兼容性的影响非常大,涉及的细节非常多。
在1.0版本的开发过程中,为了使得表达式计算的表现和MySQL一致,我们在数据类型的兼容性方面投入了大量的人力,也帮助MySQL产品纠正了不少错误的表现。
∙事务层面:
系统支持的事务隔离级别以及并发控制方面的表现。
OceanBase采用的是多版本的并发控制协议,读写不等待,支持ReadCommitted隔离级别。
3OceanBase1.0开发设计规约
数据库开发设计规约在新系统上线初期启到了举足轻重的作用。
正犹如制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全。
试想如果没有限速,没有红绿灯,没有靠右行驶条款,谁还敢上路。
OB的开发规约的目标:
∙防患未然,降低故障率和维护成本。
∙标准统一,提升协作效率。
∙追求卓越的工匠精神,打磨精品代码。
3.1.1建表规约
1.【强制】表达是与否概念的字段,数据类型是unsignedtinyint(1表示是,0表示否),值的内容要统一,所有应用值要统一。
正例:
表达逻辑删除的字段名is_deleted,1表示删除,0表示未删除。
2.【强制】表名、字段名必须使用小写字母或数字。
禁止出现数字开头,禁止两个下划线中间只出现数字。
数据库字段名的修改代价很大,所以字段名称需要慎重考虑。
说明:
MySQL在Windows下不区分大小写,但在Linux下默认是区分大小写。
因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。
正例:
getter_admin,task_config,level3_name
反例:
GetterAdmin,taskConfig,level_3_name
3.【强制】表名不使用复数名词。
说明:
表名应该仅仅表示表里面的实体内容,不应该表示实体数量
4.【强制】禁用保留字,如desc、range、match、delayed等,OB1.0的保留字见
5.【强制】唯一索引名为uk_字段名;普通索引名则为idx_字段名。
说明:
uk_即uniquekey;idx_即index的简称。
6.【强制】小数类型为decimal,禁止使用float和double。
说明:
float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。
7.【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过256K,如果存储长度大于此值,目前OB1.0暂不支持。
需要考虑字段的拆分方案。
一张表的列总长度(rowsize)不能超过512K
8.【强制】表必备两字段:
gmt_create,gmt_modified。
说明:
gmt_create,gmt_modified的类型均为datetime(6)类型。
(最佳实践记到微秒)
9.【强制】表的命名最好是加上“业务名称_表的作用”。
正例:
tiger_task/tiger_reader/mpp_config
10.【推荐】库名与应用名称尽量一致。
11.【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。
12.【推荐】字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况。
冗余字段应遵循:
1)不是频繁修改的字段。
2)不是varchar超长字段。
13.【强制】单分表行数可能超过10亿行或者单分表容量超过2000GB,才推荐进行分区表。
说明:
如果预计三年后的数据量根本达不到这个级别,请不要在创建表时使用分区表。
反例:
某业务三年总数据量才2万行,却在上线初期就规划使用分区表,由于业务模型的改变,很可能面临需要调整分区键的问题,这个需要等业务稳定成熟后考虑分区表的模式。
后续OB也会支持非分区表转换成分区表的功能。
14.【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
正例:
无符号值可以避免误存负数,且扩大了表示范围:
对象
年龄区间
类型
表示范围
人
150岁之内
unsignedtinyint
无符号值:
0到255
龟
数百岁
unsignedsmallint
无符号值:
0到65535
恐龙化石
约数千万年
unsignedint
无符号值:
0到约43亿
太阳
约50亿年
unsignedbigint
无符号值:
0到约10的19次方
3.1.2索引规约
SQL开发完成后,需要汇集所有语句提交给DBA进行sqlreview
1.【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
说明:
不要以为唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验和控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
2.【强制】超过三个表禁止join。
需要join的字段,数据类型保持绝对一致;多表关联查询时,保证被关联的字段需要有索引。
说明:
即使双表join也要注意表索引、SQL性能。
3.【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
说明:
索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
4.【推荐】如果有orderby的场景,请注意利用索引的有序性。
orderby最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
正例:
wherea=?
andb=?
orderbyc;索引:
a_b_c
反例:
索引中有范围查找,那么索引有序性无法利用,如:
WHEREa>10ORDERBYb;索引a_b无法排序。
5.【强制】利用覆盖索引来进行查询操作,来避免回表操作。
说明:
如果一本书需要知道第11章是什么标题,会翻开第11章对应的那一页吗?
目录浏览一下就好,这个目录就是起到覆盖索引的作用。
6.【强制】利用延迟关联或者子查询优化超多分页场景。
说明:
OB1.0并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。
正例:
先快速定位需要获取的id段,然后再关联:
SELECTa.*FROM表1a,(selectidfrom表1where条件LIMIT100000,20)bwherea.id=b.id
反例:
“服务市场”某交易分页超过1000页,用户点击最后一页时,数据库基本处于半瘫痪状态。
7.【推荐】建组合索引的时候,区分度最高的在最左边。
正例:
如果wherea=?
andb=?
,a列的几乎接近于唯一值,那么只需要单建idx_a索引即可。
说明:
存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。
如:
wherea>?
andb=?
那么即使a的区分度更高,也必须把b放在索引的最前列。
8.【参考】创建索引时避免有如下极端误解:
1)
误认为一个查询就需要建一个索引。
2)
误认为索引会消耗空间、严重拖慢更新和新增速度。
3)
误认为唯一索引一律需要在应用层通过“先查后插”方式解决。
3.1.3SQL规约
1.【强制】不要使用count(列名)或count(常量)来替代count(*),count(*)就是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。
说明:
count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
2.【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
说明:
(概念解释)学生表中的student_id是主键,那么成绩表中的student_id则为外键。
如果更新学生表中的student_id,同时触发成绩表中的student_id更新,则为级联更新。
外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
3.【强制】OB1.0目前不支持存储过程
4.【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。
5.【参考】所有的字符存储与表示,均以utf-8mb4编码,
6.【推荐】在业务cache表场景中,比如频繁insert/delete,数据生命周期较短的场景,需要添加HINT指定
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OceanBase 设计规范 数据 架构 指南 v213