1 集中式数据库与分布式数据库
1.1 集中式数据库缺点
- 成本高
- 有性能上线
- 无法横向扩展
- 横向扩展:变成多个,即加服务器
- 纵向扩展:单个变大,即加cpu、硬盘
1.2 分库分表缺点
- 应用侵入性
- 某些SQL不支持
- 无法保证数据一致性
1.3 OceanBase优点
- 高可用+数据一致
- 依赖工业级Paxos协议实现
- PRO=0:Recovery Point Objective,可靠性的指标,不丢失数据,
- RTO<30:Recovery Time Objective,可用性的指标,30s内恢复
- 便于横向扩容
- 成本低
- 支持复杂SQL
- 部署灵活
- 无应用侵入,即对业务透明
2 简介
- 自助研发,不需求助开源社区
- 高性能
- LSM Tree
- 高透明
- 高兼容:支持Oracle租户和Mysql租户
- 通过了TPC-C
- 在阿里的系统中得到广泛应用
3 相关产品
- OCP:OceanBase Cloud platform
- 图形化界面
- 集群管理、租户管理、集群监控、性能监控
- ODC:Oceanbase Developer Center
- 相当于plsql devloper
- 可以清晰直观查看修改当前数据库支持的变量
- OceanBase数据库内核
- 兼容Mysql+Oracle
- 支持OLTP+OLAP,即支持HTAP
- T:Transactional
- A:Analytical
- HTAP:Hybrid Transactional/Analytical Processing
- 需要三台服务器
- OMS:数据库迁移平台
- 可以将数据从OceanBase导出到Kafka、大数据
- 可以将数据从Oracle、Mysql、DB2导入
- 支持国产CPU和操作系统
4 客户端支持
- OBClient:OceanBase自带黑屏客户端。支持租户Oracle+Mysql
- Mysql客户端:支持租户Mysql
- ODC、OCP:支持租户Mysql+Oracle
5 基本概念
-
ZONE
- 对集群内一批机器打同一个tag,则属于同一个Zone
- 一个Zone包含多个OBServer
- 一个集群Zone个数一般>=3,建议奇数个(Paxos 协议)
- 一般一个城市或一个机房对应一个Zone,单个Zone坏不影响业务
- 每一份数据在各个 Zone 上有且只有一份副本
-
RootService
- 也称RS,总控服务,用于处理OBServer上下线和Zone上下线、管理如何分区、控制合并MemTable和SS Table之前先将本zone全部分区的Leader切到其它zone,等到合并完成后再切回来、执行DDL操作
- 每个Zone中有一个,可以和某个OBServer在同一台机器,某个Zone中RootService宕了,另一个Zone中的接管
-
资源池
- 集群多个服务器组成了一个大的资源池,包括指定规格的 CPU、内存、存 储、TPS、QPS 等
-
Unit
- 表示某一个OBServer上的一部分资源
- U1=2C8G:表示Unit1有2cpu和8g内存,还有一部分硬盘,最终数据的副本就存放在Unit中
-
租户
-
类似数据库实例
-
创建租户时,需指定Mysql模式还是Oracle模式
-
创建租户时,需要指定分配资源池中多少资源(Unit)给该租户
- 一个租户,在同一个Zone的同一个OBServer上,最多有一个Unit
- Unite=U1,Unite Num=2,表示分配给租户2个Unit,即同一个Zone中,有两个OBServer中的一部分资源给这个租户
-
创建租户语句
--创建Unit CREATE RESOURCE UNIT unit1 max_cpu = 4, max_memory = 10737418240, -- 10GB min_memory = 10737418240, -- 10GB max_iops = 1000, min_iops = 128, max_session_num = 300, max_disk_size = 21474836480 -- 20GB ; --创建资源池 CREATE RESOURCE POOL pool1 UNIT = 'unit1', UNIT_NUM = 1, ZONE_LIST = ('zone1', 'zone2', 'zone3') ; --将资源池分配给租户 CREATE TENANT mysql_tenant RESOURCE_POOL_LIST = ('pool1'), primary_zone = 'zone1,zone2,zone3' set ob_tcp_invited_nodes = '%', ob_compatibility_mode = 'mysql', recyclebin = off, ob_timestamp_service = 'GTS’ ;
-
8 集群技术架构
8.1 数据分区与分区副本
- 分区:hash、list、range
- 副本:每个分区的数据在物理上存储多份,每一份叫做分区的一个副本,每个 副本会存储在一个Zone 中,且一个 Zone 只能有一个副本
- 以分区为单位,组成Paxos组,,自动选出谁是主,谁是从,只有主副本提供服务。图中黄色为主副本,其他为从副本
8.2 副本类型
类型 | 事务日志 | MemTable(内存中未写入硬盘的数据) | SSTable(硬盘中的数据) | 数据安全 | 参与投票/作为leader |
---|---|---|---|---|---|
全能型 | 有 | 有 | 有 | 高 | 是/是 |
日志型 | 有 | 无 | 无 | 低 | 是/否 |
只读型 | 有 | 有 | 有 | 中 | 否/否 |
- 全能型副本:我们通常只使用这种副本
- 日志型副本:消耗CPU、内存、硬盘更少,一般用于最后一个副本,可以有效降低成 本
- 只读型:可以在对读取数据要求一致性不是特别高时,提供读服务,由于其不参与选举,因此不会由于其存在,影响选举效率,也因此同一个分区,在同一个Zone中可以存在多个只读型的副本
8.3 自动负载均衡与智能路由
- 应用的请求发送给OB Proxy,由其对SQL进行轻量解析,判断数据的主副本在哪个OBServer中,然后自动发送到那台OBServer
- 如果没找到主副本在哪,随机分配给一个OB Server,但当语句执行完毕后,OB Proxy会将主副本位置信息更新自己的Location Cache中,加快后续解析速度
- OBProxy不需要独占一台服务器
- 可以使用F5或DNS完成OBProxy的负载均衡
- 如果应用需要访问的数据不在同一个OBServer中,由最开始承接业务的OBServer,从其他OBServer中取数据
- 此过程对客户端透明
8.4 副本间确保数据一致性
- Redo Log
- 修改数据库某一行数据时,需要先把数据从磁盘读取到内存,然后在内存中修改该数据,此时内存中数据与磁盘中数据就存在了差异,我们称这种有差异的数据为脏页,不是每次生成脏页就将脏页刷新回磁盘,因为这样会产生海量的IO操作,但如果在脏页刷新回磁盘之前,数据宕机,脏页中数据会丢失,Redo log就用来解决这个问题
- Redo Log中存储了数据被修改后的值,当我们提交一个事务时,会先去把要修改的数据写入Redo Log,然后再修改内存中数据,因为Redo Log是顺序写,效率非常高,不用担心影响效率
- 需要写入主副本时,主副本会将请求发送给从副本,多数从副本写入Redo Log后,主副本就认为该写入操作完成,无需等所有从副本反馈
- 如果某个从副本由于故障,没有记录Redo Log成功,恢复后只需比对,并从主副本追平数据即可
8.5 设置Primary Zone
- (z1,z2,z3):表示zone1 = zone2 = zone3,即zone1、zone2、zone3中主副本个数尽量相同,适用于批处理场景,不关注某个SQL执行时间,期望任务整体尽快完成
- (z1;z2;z3):表示zone1 > zone2 > zone3,即主副本都在zone1中,适用于联机交易,可以避免跨服务器访问带来的网络延时
- (z1,z2;z3):表示zone1 = zone2 > zone3,即主副本均匀分配在zone1和zone2,从副本在zone3,将业务汇聚到距离较近的城市的OBServer上
8.6 Primary Zone优先级
- 表、数据库、租户,都可以设置Primary Zone
- 表 > 数据库 > 租户
- 对于小租户(unit_num=1),OceanBase默认不会将分区打散到各个zone
8.7 Table Group
- 如果多个表分区方式相同(分区类型、分区健个数、分区数量),也就是说,这几个表,可能频繁对同一分区键进行关联查询,那么可以将它们分配到同一个Table Group中
- 同一个Table Group中的所有表的同一个分区ID(partition_id),它们的主副本在同一个OBServer中,这样可以有效较少分布式事务引起的跨机访问开销
- 如果Primary Zone设置的只有一个zone存放主副本,且这个租户Zone中只有一个unit,那就意味着,本身数据就都在同一个OBServer中,也就没必要设置Table Group
8.8 OBServer进程异常后的处理策略
- OBServer的临时下线:从其他zone副本中,将当前OBServer所在Zone中缺失的数据复制到该Zone剩余的机器中
- 如果OBServer宕机时间超过server_permanent_offline_time,就认为可能很长时间恢复不了,就进行临时下线,不超过不做处理,从而避免临时下线带来的频繁数据迁移,但有可能再有副本所在OBServer宕机造成整体服务挂掉
- 被临时下线的OBServer如果想上线,必须先从其所在Zone或其他Zone中将副本迁移回来
8.9 传统数据实现高可用的问题
- 可能丢失数据
- 最大保护模式:主和备记录Redo Log都成功,发起的业务查询才成功,因此备数据库宕机,主数据无法发送Redo Log,就一直等待其恢复,无法对外提供服务,基本生产环境没有使用最大保护模式的
- 最大性能模式:主数据库Redo Log记录成功,业务即返回成功,如果主成功,备没成功,但此时主宕机,那么备中缺失了一部分数据
- 最大可用模式:备可用时使用最大保护,备不可用时使用最大性能,一般生产环境属于这种
- 无法自动切换
- 因为只有主和备,当二者联系不上,无法知道到底是谁宕机了,OceanBase可以通过Paxos协议判断
8.10 OceanBase容灾
- 同城三机房:每个机房一个Zone
- 三地五中心五副本
- 3个城市,5个Zone,每个城市最多2个Zone,保证任意城市有灾难,其他两个城市的副本能构成多数派
- 城市1和城市2尽可能近,来降低同步Redo Log的延时
- 城市3可以只提供日志型副本,降低成本
- 同城两机房:建两套集群,注意不是两个Zone,两套集群间使用传统数据库的最大性能或最大保护模式
- 两地三中心
- 两个地区建立3个中心,主城市两个中心,备用城市一个中心
- 主城市的两个中心,每个中心两个Zone,备用城市的一个中心有一个Zone
- 备用城市再建立一个三Zone的集群,从主集群同步,也是使用最大性能或最大保护模式
- 任何中心遇到IDC故障,另两个还能继续提供服务,如果主城市整体IDC故障,备用城市的备用集群可以接管
8.11 扩容与缩容
- 扩容流程
- 为每个Zone添加新物理机
- 新机器上启动OBServer
- 新OBServer执行
alter system add server
,将自身添加到集群 - 执行
alter resource pool<pool name> unit_num=<bigger number>
扩充资源池中unit个数 - OceanBase自动rebalance,即,将部分数据从旧unit在线复制到新unit
- 复制完成后,自动将服务切换到新unit,并删除旧unit中数据
- 缩容流程
- 减少资源池中unit个数
- OceanBase自动rebalance,即,将部分数据从旧unit在线复制到同Zone内其他机器的unit中
- 复制成功后将服务切换到新unit上,之后删除待下线机器的unit中分区上的数据
- 执行
alter system delete server
完成机器下线 - 将下线机器关机
8.12 OceanBase保证ACID
8.12.1 两类一致性协议
- 2PC:Two-Phase Commit,用于保证属于多个数据分片上的操作的原子性,即保证多台服务器上的操作要么全部成功,要么全失败
- 阶段1:投票
- 事务询问:协调者向所有参与者发送事务内容(insert、update),询问是否可以执行事务提交操作
- 执行事务:各参与者节点执行事务操作(insert、update),并将Undo和Redo信息计入事务日志中
- 返回响应:参与者将执行事务结果返回给协调者,Yes或No
- 阶段2:执行
- 协调者向所有参与者节点发出Commit请求
- 参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源
- 参与者在完成事务提交之后,向协调者发送ACK信息
- 协调者接收到所有参与者反馈的ACK消息后,完成事务
- 如果阶段1有参与者返回No,或协调者在超时时间内无法获取所有参与者的响应,就会中断事务
- 协调者向所有参与者节点发出Rollback请求
- 参与者接收到rollback请求后,会利用其在阶段一中记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放整个事务执行期间占用的资源
- 参与者在完成事务回滚之后,向协调者发送ACK信息
- 协调者接收到所有参与者反馈的ACK信息后,完成事务中断
- 阶段1:投票
- Paxos:用于保证同一个数据分片的多个副本之间的数据一致性
8.12.2 ACID保证
- A(原子性):依赖2PC协议
- 数据库中间件架构:中间件是协调者,下面的数据库是参与者,参与者只知道协调者而不知道其他参与者的存在,一旦中间件故障,很难恢复事务
- OceanBase:所有的参与者和协调者都是OB Server,且所有协调者和参与者都高可用,协调者宕机,其他服务器的从副本通过 Paxos协议也可以很快的自动选举新的主副本,来作为新的协调者,新的主副本可以通过Redo Log知晓之前事务的存在,因此可以将事务恢复到宕机之前的状态,不会有状态和数据的丢失
- C(一致性):通过保证主键唯一和全局快照保证
- I(隔离性):通过MVCC,MVCC就是一种解决读写互斥的技术,保证读不影响写,写也不影响读
- Read-Committed
- Serializable
- D(持久性):通过Redo Log保证
9 存储引擎
9.1 传统数据库
- 磁盘上有表空间,表空间中划分出不同的段(Extend),每个段划分为若干页(Block),段和页会随着数据不断插入来不停分配,内存中的Buffer Pool和硬盘上的表空间一一对应,数据从哪读出来,最终就会写回到哪里
- 读数据:如果内存有数据,从内存(buffer pool)读,内存没有数据,先从硬盘读到内存
- 写数据
- 先写入内存,定期check point,将脏数据写入硬盘,但由于数据在硬盘中位置不同,因此会造成随机写。所谓随机写不是指随机写入一个位置,而是写入硬盘不同的位置,效率远低于顺序写
- SSD上大量的随机写会造成写放大
- 且由于数据的读写,都是以页或者段为单位,即使要修改的数据很少,比如只是修改了1个页内的几个字节,也需要把整页更新到硬盘的表空间中,造成写放大
9.2 OceanBase
- OceanBase将内存分为两块,MemTable用于写,热点缓存用于读
- 写数据
- 脏数据写入MemTable
- MemTable并不定期进行check point落盘,而是在内存快满、固定时间、人工触发时,将内存中一大批脏数据先进行合并,再写到硬盘,这个过程叫转储,转储数据就是在硬盘上的增量数据,之后转储数据会和硬盘的SS Table的基线数据合并后,形成新的基线数据
- 避免随机写
- 提升存储利用率,传统数据库delete后会造成磁盘碎片,OceanBase使用LSM Tree架构,数据在磁盘上默认按主键有序排列,当内存里的大量的 增量数据和磁盘基线数据合并时,会重新排序,然后以批量写的形式顺序写到硬盘上,可以很 容易的把原有的碎片去掉,减少磁盘碎片,提升存储利用率
- 提供压缩率
- 内存占用率达到一定阈值后,冻结MemTable,并执行转储、合并等操作来释放内存
- 内存增量数据批量合并到磁盘,以顺序写替代随机写
- 读数据:从热点缓存、MemTable、SS Table中读取数据,保证数据一致
- LSM Tree存储
- 是一种分层,有序,面向磁盘的数据结构
- 这种结构的写入,全部都是以Append的模式追加,不存在删除和修改
- 大大提升了数据的写入能力,却是以牺牲部分读取性能为代价
- 内存中增量数据,分多级,批量归并到硬盘,级层越多,系统越稳定,但数据查询路径越长
- mini freeze:异步合并,合并为minor freeze
- minor freeze:实时合并,合并为major freeze
- major freeze:合并为基线数据,也就是sstable
- OcaenBase会对存储的数据进行两次压缩,第一次为encoding,第二次为通用压缩,使用lz4、lzo等压缩算法,最终Mysql中100T迁移到OceanBase只需33T
10 备份与恢复
- 备份支持阿里云OSS存储和普通的NFS
- 备份速度能达到网卡上线,约等1G/s
- 恢复速度为500M/s
- 备份最小粒度为租户
- 支持全量备份(备份sstable)和增量备份(备份redolog)
11 JDBC连接
- 使用jdbc连接时,如果为mysql租户,可以使用标准mysql协议,如果oracle租户,必须使用OceanBase开发的jdbc驱动
12 参数管理
-
参数分动态生效和重启生效,大部分动态生效
-
参数分集群级别和租户级别,集群级别会覆盖租户级别
-
集群级别参数无法通过普通租户设定,也无法通过系统租户指定普通租户设定,只能由系统租户来设定
-
系统租户可以查看和设置其他租户参数,普通租户只能设置自己的参数
--查看系统租户参数,tenant表示租户,t1是系统租户,查询中的列scope表示角色,CLUSTER为集群级参数,TENANT为租户级参数,edit_level表示生效方式,dynamic-effective表示动态生效,static-effective表示重启生效 show parameters like '%sql_work_area%' tenant=t1 --查看普通租户参数 show parameters like 'sql_work_area'
13 变量
-
会话变量:session级,当前session生效
-
全局变量:global级,也叫租户级,当前已打开的session无效
show variables like '%<pattern>%' set @@session.<name> = <value> set @@global.<name> = <value>
14 OceanBase告警级别
- Info<Caution<Alert<Cirtical<Down