分布式数据库DBLE - Go语言中文社区

分布式数据库DBLE


                                                   分布式数据库DBLE

  • 第一章 绪论
    1. 研究背景

目前,在电商、金融、O2O、零售、电信等行业普遍存在用户基数大,营销活动频繁,核心交易系统响应日益变慢的问题,随着业务数据增长迅速,超过单机数据库的承受极限,制约业务的发展;在电力、气象、农业、智能制造等行业海量的数据远远超过单机数据库的承受极限。

常用的单机数据库的瓶颈包括:单个表数据量越大,读写锁,插入操作重新建立索引效率越低;单个库数据量太大(一个数据库数据量到1T-2T就是极限);单个数据库服务器压力过大;读写速度遇到瓶颈(并发量几百);

针对单机数据库的瓶颈问题,一般做法包括:分区、分表、分库等。

分区,就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的;分表,就是把一张表按一定的规则分解成N个具有独立存储空间的实体表,系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。分库,就是将数据存放到不同的数据库中,可以按照垂直拆分和水平拆分及读写分离的原则,将数据划分到不同的数据库中,分库目的是是为了突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。

对数据进行拆分之后面临一些新的问题包括:事务的支持;分库分表,就变成了分布式事务;进行join时跨库,跨表的问题;分库分表,读写分离使用了分布式,分布式为了保证强一致性,必然带来延迟,导致性能降低,系统的复杂度变高等。

针对以上问题,对于不同的方式之间没有严格的界限,特点不同,侧重点不同。需要根据实际情况,结合每种方式的特点来进行处理,另外还可以考虑选用第三方的数据库中间件(Atlas,Mycat,TDDL,DRDS,TIDB等),同时业务系统需要配合数据存储的升级。

本文主要讨论第三方的数据库中间件TIDB的原理、架构设计及使用。

 

    1. 研究现状
      1. mysql-proxy

mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个mysql-server。

它使用mysql协议,任何使用mysql-client的上游无需修改任何代码,即可迁移至mysql-proxy上。

mysql-proxy最基本的用法,就是作为一个请求拦截,请求中转的中间层:

进一步的,mysql-proxy可以分析与修改请求。拦截查询和修改结果,需要通过编写Lua脚本来完成。

mysql-proxy允许用户指定Lua脚本对请求进行拦截,对请求进行分析与修改,它还允许用户指定Lua脚本对服务器的返回结果

进行修改,加入一些结果集或者去除一些结果集均可。

所以说,根本上,mysql-proxy是一个官方提供的框架,具备良好的扩展性,可以用来完成:sql拦截与修改、性能分析与监控、读写分离、请求路由。

 

mysql主从同步延迟原理

mysql主从同步原理
  主库针对读写操作,顺序写 binlog,从库单线程去主库读"写操作的binlog",从库取到 binlog在本地原样执行(随机写),来保证主从数据逻辑上一致.
mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生 binlog,binlog是顺序写,所以效率很高,slave的Slave_IO_Running线程到主库取日志,效率比较高,下一步问题来了,slave的 slave_sql_running线程将主库的 DDL和DML操作在 slave实施。DML,DDL的IO操作是随即的,不能顺序的,成本高很多,还有可能slave上的其他查询产生 lock,由于 slave_sql_running也是单线程的,所以 一个 DDL卡住了,需求需求执行一段时间,那么所有之后的DDL会等待这个 DDL执行完才会继续执行,这就导致了延迟.由于master可以并发,Slave_sql_running线程却不可以,所以主库执行 DDL需求一段时间,在slave执行相同的DDL时,就产生了延迟.

主从同步延迟产生原因
当主库的TPS并发较高时,产生的DDL数量超过Slave一个 sql线程所能承受的范围,那么延迟就产生了,当然还有就是可能与 slave的大型 query语句产生了锁等待
首要原因:数据库在业务上读写压力太大,CPU计算负荷大,网卡负荷大,硬盘随机IO太高
次要原因:读写 binlog带来的性能影响,网络传输延迟
主从同步延迟解决方案
架构方面
1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展分散压力
2.单个库读写分离,一主多从,主写从读,分散压力。
3.服务的基础架构在业务和mysql之间加放 cache层
4.不同业务的mysql放在不同的机器
5.使用比主加更了的硬件设备作slave
反正就是mysql压力变小,延迟自然会变小

 

硬件方面:
采用好的服务器

mysql主从同步加速
1、sync_binlog在slave端设置为0
2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
3、直接禁用slave端的binlog
4、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2

 

      1. Atlas

Atlas是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。
Altas架构:
   Atlas是一个位于应用程序与MySQL之间,它实现了MySQL的客户端与服务端协议,作为服务端与应用程序通讯,同时作为客户端与MySQL通讯。它对应用程序屏蔽了DB的细节,同时为了降低MySQL负担,它还维护了连接池。

以下是一个可以参考的整体架构,LVS前端做负载均衡,两个Altas做HA,防止单点故障。

Altas的一些新特性:
1.主库宕机不影响读
   主库宕机,Atlas自动将宕机的主库摘除,写操作会失败,读操作不受影响。从库宕机,Atlas自动将宕机的从库摘除,对应用没有影响。在mysql官方的proxy中主库宕机,从库亦不可用。
2.通过管理接口,简化管理工作,DB的上下线对应用完全透明,同时可以手动上下线。
   图1是手动添加一台从库的示例。

3.自己实现读写分离
(1)为了解决读写分离存在写完马上就想读而这时可能存在主从同步延迟的情况,Altas中可以在SQL语句前增加 /*master*/ 就可以将读请求强制发往主库。
(2)如图2中,主库可设置多项,用逗号分隔,从库可设置多项和权重,达到负载均衡。
图2

4.自己实现分表(图3)
(1)需带有分表字段。
(2)支持SELECT、INSERT、UPDATE、DELETE、REPLACE语句。
(3)支持多个子表查询结果的合并和排序。
图3

这里不得不吐槽Atlas的分表功能,不能实现分布式分表,所有的子表必须在同一台DB的同一个database里且所有的子表必须事先建好,Atlas没有自动建表的功能。
5.之前官方主要功能逻辑由使用lua脚本编写,效率低,Atlas用C改写,QPS提高,latency降低。
6.安全方面的提升
(1)通过配置文件中的pwds参数进行连接Atlas的用户的权限控制。
(2)通过client-ips参数对有权限连接Atlas的ip进行过滤。
(3)日志中记录所有通过Altas处理的SQL语句,包括客户端IP、实际执行该语句的DB、执行成功与否、执行所耗费的时间 ,如下面例子(图4)。
图4

7.平滑重启
  通过配置文件中设置lvs-ips参数实现平滑重启功能,否则重启Altas的瞬间那些SQL请求都会失败。该参数前面挂接的lvs的物理网卡的ip,注意不是虚ip。平滑重启的条件是至少有两台配置相同的Atlas且挂在lvs之后。

      1. Cobar

Cobar是阿里巴巴(B2B)部门开发的一种关系型数据的分布式处理系统,它可以在分布式的环境下看上去像传统数据库一样为您提供海量数据服务。那么具体说说我们为什么要用它,或说cobar--能干什么?以下是我们业务运行中会存在的一些问题:
1.随着业务的进行数据库的数据量和访问量的剧增,需要对数据进行水平拆分来降低单库的压力,而且需要高效且相对透明的来屏蔽掉水平拆分的细节。
2.为提高访问的可用性,数据源需要备份。
3.数据源可用性的检测和failover。
4.前台的高并发造成后台数据库连接数过多,降低了性能,怎么解决。
     针对以上问题就有了cobar施展自己的空间了,cobar中间件以proxy的形式位于前台应用和实际数据库之间,对前台的开放的接口是mysql通信协议。将前台SQL语句变更并按照数据分布规则转发到合适的后台数据分库,再合并返回结果,模拟单库下的数据库行为。


Cobar应用举例
应用架构:

应用介绍:
1.通过Cobar提供一个名为test的数据库,其中包含t1,t2两张表。后台有3个MySQL实例(ip:port)为其提供服务,分别为:A,B,C。
2.期望t1表的数据放置在实例A中,t2表的数据水平拆成四份并在实例B和C中各自放两份。t2表的数据要具备HA功能,即B或者C实例其中一个出现故障,不影响使用且可提供完整的数据服务。
cabar优点总结:
1.数据和访问从集中式改变为分布:
(1)Cobar支持将一张表水平拆分成多份分别放入不同的库来实现表的水平拆分
(2)Cobar也支持将不同的表放入不同的库
(3) 多数情况下,用户会将以上两种方式混合使用
注意!:Cobar不支持将一张表,例如test表拆分成test_1,test_2, test_3.....放在同一个库中,必须将拆分后的表分别放入不同的库来实现分布式。
2.解决连接数过大的问题。
3.对业务代码侵入性少。
4.提供数据节点的failover,HA:
(1)Cobar的主备切换有两种触发方式,一种是用户手动触发,一种是Cobar的心跳语句检测到异常后自动触发。那么,当心跳检测到主机异常,切换到备机,如果主机恢复了,需要用户手动切回主机工作,Cobar不会在主机恢复时自动切换回主机,除非备机的心跳也返回异常。
(2)Cobar只检查MySQL主备异常,不关心主备之间的数据同步,因此用户需要在使用Cobar之前在MySQL主备上配置双向同步。
cobar缺点:
开源版本中数据库只支持mysql,并且不支持读写分离。

      1. tddl

淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer 外号:头都大了 ©_Ob)框架,主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个基于集中式配置的 jdbc datasource实现,具有主备,读写分离,动态数据库配置等功能。
TDDL所处的位置(tddl通用数据访问层,部署在客户端的jar包,用于将用户的SQL路由到指定的数据库中):

淘宝很早就对数据进行过分库的处理, 上层系统连接多个数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。DBRoute对数据进行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。但是随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32个……直到1024个、2048个。好,分成这么多,数据能够存放了,那怎么查询它?这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询在几毫秒内完成),TDDL就承担了这样一个工作。在外面有些系统也用DAL(数据访问层) 这个概念来命名这个中间件。
下图展示了一个简单的分库分表数据查询策略:
 

主要优点:
1.数据库主备和动态切换
2.带权重的读写分离
3.单线程读重试
4.集中式数据源信息管理和动态变更
5.剥离的稳定jboss数据源
6.支持mysql和oracle数据库
7.基于jdbc规范,很容易扩展支持实现jdbc规范的数据源
8.无server,client-jar形式存在,应用直连数据库
9.读写次数,并发度流程控制,动态变更
10.可分析的日志打印,日志流控,动态变更
   TDDL必须要依赖diamond配置中心(diamond是淘宝内部使用的一个管理持久配置的系统,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理,同时diamond也已开源)。

      1. Mycat分布式数据库

ServiceComb是2017年5月份华为开源的微服务框架,是华为云微服务框架引擎重要的一个组成部分。

如果服务调用的过程中抛出异常,Omega会将终止事件发送到Alpha端,Alpha的后台进程会定时做扫描,扫描过程中会发现有需要恢复的事件。Alpha会向Omega发消息调用相关的恢复操作,来保证整个Saga事务的原子性。目前Omega也开始提供重试功能,也就是事务调用如果失败了, Omega会根据设置进行重试尝试。

      1. TIDB

TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。

TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。

TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。

  1. TiDB、TiKV、Placement Driver (PD) 的主要作用

TiDB 是 Server 计算层,主要负责 SQL 的解析、制定查询计划、生成执行器。

TiKV 是分布式 Key-Value 存储引擎,用来存储真正的数据,简而言之,TiKV 是 TiDB 的存储引擎。

PD 是 TiDB 集群的管理组件,负责存储 TiKV 的元数据,同时也负责分配时间戳以及对 TiKV 做负载均衡调度。

  1. TIDB的特点
  • TiDB 使用起来很简单,可以将 TiDB 集群当成 MySQL 来用,你可以将 TiDB 用在任何以 MySQL 作为后台存储服务的应用中,并且基本上不需要修改应用代码,同时你可以用大部分流行的 MySQL 管理工具来管理 TiDB。
  • TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法
  • TiDB 天然具备高可用特性,TiDB、TiKV、PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。
  • TiDB 使用 Raft 在多个副本之间做数据同步,从而保证数据的强一致,单个副本失效时,不影响数据的可靠性。
  • TiDB 支持 ACID 分布式事务,事务模型是以 Google 的 Percolator 模型为基础,并做了一些优化。这个模型需要一个时间戳分配器,分配唯一且递增的时间戳。在 TiDB 集群中,PD 承担时间戳分配器的角色。
  • 只要支持 MySQL Client/Driver 的编程语言,都可以直接使用 TiDB。
    1. 研究内容

2017年10月24日,国内知名的云数据库产品供应商上海爱可生信息技术股份有限公司在上海正式开源其MySQL分布式中间件—DBLE。DBLE是爱可生基于MySQL的高可扩展性的分布式中间件,重点提升功能和性能优化,支持复杂查询,增强了如分布式事务,SQL支持度等核心功能,DBLE正适用于高并发及TB级海量数据处理场景。

DBLE是基于开源项目MyCat的,其授权协议为GPL,采用java语言进行开发。DBLE是一个开源的分布式数据库系统,实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信。DBLE实现了MySQL从单机到集群的扩展,能够满足有更大存储需求的业务,同时又使用户业务不会受到单节点故障的影响。

 

DBLE解决了哪些问题

  • 数据水平拆分

当单个MySQL实例成为业务发展瓶颈,可使用DBLE来替换原始的MySQL实例,实现数据水平拆分;

  • 与MySQL协议兼容

可以直接用它替换MySQL来为你的应用程序提供新的存储,而无需更改任何代码;

  • SQL支持

支持SQL 92标准和MySQL方言。我们支持复杂的SQL查询,如group by,order by,distinct,join,union,sub-query等等。

  • 查询优化

优化复杂查询,包括但不限于全局表连接分片表,ER关系表,子查询,简化选择项等。

  • 分布式事务支持

使用两阶段提交协议实现了分布式事务,在确保系统性能的前提条件下,保证了分布式事务的数据一致性。

 

 

  • 第二章 相关技术介绍
    1. 分区

分区就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的

  1. 什么时候考虑使用分区

当一张表的查询速度已经慢到影响使用的时候,此时sql经过优化,并且数据量很大,表中的数据是分段的,对数据的操作往往只涉及一部分数据,而不是所有的数据,此时可以考虑对数据库中的表进行分区操作。分区可以提升查询效率。

  1. 分区的实现方式

mysql5 开始支持分区功能。建表语句如下:

CREATE TABLE sales (

    id INT AUTO_INCREMENT,

    amount DOUBLE NOT NULL,

    order_day DATETIME NOT NULL,

    PRIMARY KEY(id, order_day)

) ENGINE=Innodb

PARTITION BY RANGE(YEAR(order_day)) (

    PARTITION p_2010 VALUES LESS THAN (2010),

    PARTITION p_2011 VALUES LESS THAN (2011),

    PARTITION p_2012 VALUES LESS THAN (2012),

PARTITION p_catchall VALUES LESS THAN MAXVALUE);

mysql支持的分区类型包括Range、List、Hash、Key,其中Range比较常用:打开mysql的数据目录

https://images2015.cnblogs.com/blog/602490/201612/602490-20161219161002541-2111385686.png

可以看见多了user#P#user_1.ibd 和user#P#user_2.ibd  这两个文件

如果表使用的存储引擎是MyISAM类型,就是:

user#P#user_1.MYD,user#P#user_1.MYI和user#P#user_2.MYD,user#P#user_2.MYI

由此可见,mysql通过分区把数据保存到不同的文件里,同时索引也是分区的。相对于未分区的表来说,分区后单独的数据库文件索引文件的大小都明显降低,效率则明显的提升。

RANGE分区

基于属于一个给定连续区间的列值,把多行分配给分区。

该模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980's)的数据,90年代(1990's)的数据以及任何在2000年(包括2000年)后的数据。

CREATE TABLE users ( 

       id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 

       usersname VARCHAR(30) NOT NULL DEFAULT ''

       email VARCHAR(30) NOT NULL DEFAULT '' 

PARTITION BY RANGE (id) ( 

       PARTITION p0 VALUES LESS THAN (3000000

       DATA DIRECTORY = '/data0/data' 

       INDEX DIRECTORY = '/data0/index'

 

       PARTITION p1 VALUES LESS THAN (6000000

       DATA DIRECTORY = '/data1/data' 

       INDEX DIRECTORY = '/data1/index'

 

       PARTITION p2 VALUES LESS THAN (9000000

       DATA DIRECTORY = '/data2/data' 

       INDEX DIRECTORY = '/data2/index'

 

       PARTITION p3 VALUES LESS THAN MAXVALUE    

       DATA DIRECTORY = '/data3/data'  

       INDEX DIRECTORY = '/data3/index' 

);

LIST分区

类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

该模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA根据用户的类型进行分区。

CREATE TABLE user (  
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
     name VARCHAR(30) NOT NULL DEFAULT '' ,
     user_type   int not null
PARTITION BY LIST (user_type ) (  
     PARTITION p0 VALUES IN (0,4,8,12) , 
     PARTITION p1 VALUES IN (1,5,9,13) ,  
     PARTITION p2 VALUES IN (2,6,10,14),  
     PARTITION p3 VALUES IN (3,7,11,15)   
); 

HASH分区

基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

该模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,例如DBA可以建立一个对表主键进行分区的表。 

CREATE TABLE user (  
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
     username VARCHAR(30) NOT NULL DEFAULT '',  
     email VARCHAR(30) NOT NULL DEFAULT ''  
PARTITION BY HASH (id) PARTITIONS 4 (  
     PARTITION p0 ,  
     PARTITION p1,  
     PARTITION p2,
     PARTITION p3  
); 

KEY分区

类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。是上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。

CREATE TABLE user (  
     id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
     name VARCHAR(30) NOT NULL DEFAULT '',  
     email VARCHAR(30) NOT NULL DEFAULT ''  
PARTITION BY KEY (id) PARTITIONS 4 (  
     PARTITION p0,  
     PARTITION p1,  
     PARTITION p2,  
     PARTITION p3
); 
    1. 分表

分表,就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。

  1. 什么时候考虑分表

当一张表的查询速度已经慢到影响使用的时候;sql经过优化的时候;数据量大的时候;当频繁插入或者联合查询时,速度变慢的时候。

  1. 分表解决的问题

分表后,单表的并发能力提高了,磁盘I/O性能也提高了,写操作效率提高了,查询一次的时间短了,数据分布在不同的文件,磁盘I/O性能提高,读写锁影响的数据量变小,插入数据库需要重新建立索引的数据减少。

  1. 分表的实现方式(复杂)

需要业务系统配合迁移升级,工作量较大

  1. 分区和分表的区别与联系

分区和分表的目的都是减少数据库的负担,提高表的增删改查效率。分区只是一张表中的数据的存储位置发生改变,分表是将一张表分成多张表。当访问量大,且表数据比较大时,两种方式可以互相配合使用。当访问量不大,但表数据比较多时,可以只进行分区。

  1. 常见分区分表的规则策略(类似)
  • Range(范围)
  • Hash(哈希)
  • 按照时间拆分
  • Hash之后按照分表个数取模
  • 在认证库中保存数据库配置,就是建立一个DB,这个DB单独保存user_id到DB的映射关系
    1. 分库

分库,一旦分表,一个库中的表会越来越多

将整个数据库比作图书馆,一张表就是一本书。当要在一本书中查找某项内容时,如果不分章节,查找的效率将会下降。而同理,在数据库中就是分区。

  1. 什么时候考虑使用分库

单台DB的存储空间不够;随着查询量的增加单台数据库服务器已经没办法支撑。

  1. 分库解决的问题

其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。 

  1. 垂直拆分

将系统中不存在关联关系或者需要join的表可以放在不同的数据库不同的服务器中。

按照业务垂直划分。比如:可以按照业务分为资金、会员、订单三个数据库。

需要解决的问题:跨数据库的事务、join查询等问题。

  1. 水平拆分

例如,大部分的站点。数据都是和用户有关,那么可以根据用户,将数据按照用户水平拆分。

按照规则划分,一般水平分库是在垂直分库之后的。比如每天处理的订单数量是海量的,可以按照一定的规则水平划分。需要解决的问题:数据路由、组装。

  1. 读写分离

对于时效性不高的数据,可以通过读写分离缓解数据库压力。需要解决的问题:在业务上区分哪些业务上是允许一定时间延迟的,以及数据同步问题。

  1. 思路

垂直分库-->水平分库-->读写分离

 

第三章 DBLE原理

    1. 架构设计

 

描述:

    1. DBLE核心特性

dble是上海爱可生信息技术股份有限公司基于mysql的高可扩展性的分布式中间件,存在以下几个优势特性:

  1. 数据水平拆分

随着业务的发展,您可以使用dble来替换原始的单个MySQL实例。

  1. 兼容Mysql

与MySQL协议兼容,在大多数情况下,您可以用它替换MySQL来为你的应用程序提供新的存储,而无需更改任何代码。

  1. 高可用性

Ndble服务器可以用作集群,业务不会受到单节点故障的影响。

  1. SQL支持

支持SQL 92标准和MySQL方言。我们支持复杂的SQL查询,如group by,order by,distinct,join,union,sub-query等等。

  1. 复杂查询优化

优化复杂查询,包括但不限于全局表连接分片表,ER关系表,子查询,简化选择项等。

  1. 分布式事务支持

使用两阶段提交的分布式事务。您可以为了性能选择普通模式或者为了数据安全采用XA模式。当然,XA模式依赖于MySQL-5.7的XA Transaction,MySQL节点的高可用性和数据的可靠性。

    1. DBLE实现分表/分库
      1. 分区算法

分表算法大致分为以下几类:

  • sharding-by-enum:按照枚举方式,执行分表操作。
  • sharding-by-range:按照区间范围,执行分表操作。
  • sharding-by-hash:按照hash算法,执行分表操作。
  • sharding-by-hash2:按照hash算法,执行分表操作。
  • sharding-by-hash3:按照hash算法,执行分表操作。
  • sharding-by-mod:按照计算取模,执行分表操作。
  • sharding-by-hash-str:按照字符串hash算法,执行分表操作。
  • sharding-by-date:按照日期,执行分表操作。
  • sharding-by-pattern:按照分片字段值进行模运算,执行分表操作。
  • sharding-by-string-jump:按照计算概率分布的方式,执行分表操作。

 

分表规则

规则函数及使用描述

<tableRule name="sharding-by-enum">

     <rule>

         <columns>id</columns>

         <algorithm>enum</algorithm>

     </rule>

 </tableRule>

<function name="enum"  class="Enum">

     <property name="mapFile">partition-hash-int.txt</property>

      <propertyname="defaultNode">0</property>        <property name="type">0</property>   

</function>

mapFile:指定配置文件名。其格式将在下面做详细说明。
defaultNode:指定默认节点号。默认值为-1, 不指定默认节点。
type:指定配置文件中key的类型。0:整型; 其它:字符串。

 

partition-hash-int.txt文件配置

 a. type值为0时,

10000=0

10010=1

b. type值为非0时,

string1=node0
string2=node1

<tableRule name="sharding-by-range">

     <rule>

         <columns>id</columns>

         <algorithm>rangeLong</algorithm>

     </rule>

 </tableRule>

<function name="rangeLong"

              class="NumberRange">

        <property name="mapFile">autopartition-long.txt</property>

        <property name="defaultNode">0</property>    </function>

autopartition-long.txt文档描述

# range start-end ,data node index

# K=1000,M=10000.

0-500M=0

500M-1000M=1

1000M-1500M=2

<tableRule name="sharding-by-hash">

     <rule>

         <columns>id</columns>

         <algorithm>hashLong</algorithm>

     </rule>

 </tableRule>

<function name="hashLong" class="Hash">

        <property name="partitionCount">8</property>

        <property name="partitionLength">128</property>

 

        <!-- <property name="partitionCount">2,3</property>

        <property name="partitionLength">4,5</property>-->

</function>

 

例如,配置F1

<property name="partitionCount">2,3</property>

<property name="partitionLength">100,50</property>

将划分如下的分区: [0 , 100)  [100, 200)  [200, 250)  [250, 300)
[300, 350)

再如,配置F2:

<property name="partitionCount">2</property>

<property name="partitionLength">1000</property>

将划分如下的分区:[0 , 1000)  [1000, 2000)

 <tableRule name="sharding-by-hash2">

     <rule>

         <columns>id</columns>

         <algorithm>hashLong2</algorithm>

     </rule>

 </tableRule>

<function name="hashLong2" class="Hash">

        <property name="partitionCount">2</property>

        <property name="partitionLength">512</property>

 

        <!-- <property name="partitionCount">2,3</property>

        <property name="partitionLength">4,5</property>-->

    </function>

<tableRule name="sharding-by-hash3">

     <rule>

         <columns>id</columns>

         <algorithm>hashLong3</algorithm>

     </rule>

 </tableRule>

<function name="hashLong3" class="Hash">

        <property name="partitionCount">2,1</property>

        <property name="partitionLength">256,512</property>

 

        <!-- <property name="partitionCount">2,3</property>

        <property name="partitionLength">4,5</property>-->

    </function>

<tableRule name="sharding-by-mod">

     <rule>

         <columns>id</columns>

         <algorithm>hashmod</algorithm>

     </rule>

 </tableRule>

<function name="hashmod" class="Hash">

        <property name="partitionCount">4</property>

        <property name="partitionLength">1</property>

</function>

这里选择的hashmod就是将数据平均拆分为4份,在rule.xml中hashmod对应的partitionCount为4。

<tableRule name="sharding-by-hash-str">

     <rule>

         <columns>id</columns>

         <algorithm>hashString</algorithm>

     </rule>

 </tableRule>

<function name="hashString" class="StringHash">

        <property name="partitionCount">8</property>

        <property name="partitionLength">128</property>

        <property name="hashSlice">0:2</property>

 

        <!--<property name="hashSlice">-4:0</property> -->

</function>

 

 

<tableRule name="sharding-by-date">

     <rule>

         <columns>calldate</columns>

         <algorithm>partbydate</algorithm>

     </rule>

 </tableRule>

<function name="partbydate"

              class="Date">

        <property name="dateFormat">yyyy-MM-dd</property>

        <property name="sBeginDate">2015-01-01</property>

        <property name="sEndDate">2015-01-31

        </property>

        <property name="sPartionDay">10</property>

        <property name="defaultNode">0</property>

</function>

dateFormat:指定日期的格式。
sBeginDate:指定日期的开始时间。
sEndDate:指定日期的结束时间。该性质可以不配置或配置为空("")
sPartionDay:指定分区的间隔,单位是天。
defaultNode:指定默认节点号。默认值为-1 不指定默认节点。

该算法有两种工作模式:
模式1:不配置sEndDate或者将sEndDate配置为""
在这种模式下, 该算法将时间以sBeginDate为开始, sPartionDay为间隔,进行区间划分, 每个区间对应一个数据节点。
在进行区间查找时,分区字段值落在的区间对应的数据节点既是目的数据节点。如果分区字段值小于sBeginDate:如果配置了defaultNode,则defaultNode既是目的数据节点, 否则出错。
模式2:配置sEndDate且不为""
在这种模式下, 该算法将时间以sBeginDate为开始, sPartionDay为间隔,以sEndDate为终点, 进行区间划分,划分为N个区间, 每个区间对应一个数据节点。
在进行区间查找时: 如果分区字段值小于等于sEndDate,则计算过程和结果等同于模式1。如果分区字段值大sEndDate,则分片查找公式为:index=((key - sBeginDate)/sPartionDay)%N, 其中key为分片字段值, index为映射到的数据节点索引。这等同于一个环形映射。

<tableRule name="sharding-by-pattern">

     <rule>

         <columns>id</columns>

         <algorithm>pattern</algorithm>

     </rule>

 </tableRule>

<function name="pattern"

              class="PatternRange">

        <property name="mapFile">partition-pattern.txt</property>

        <property name="patternValue">1024</property>

        <property name="defaultNode">0</property>    </function>

mapFile:指定配置文件名。其格式将在下面做详细说明。
patternValue:指定模值, 默认为1024。
defaultNode:指定默认节点号。默认值为-1, 不指定默认节点。

配置文件格式如下:
#comment
//comment
this line will be skiped
start1-end1=node1
start1-end2=node2

 

例如:partition-pattern.txt文档

#begin - end = nodeid

0 - 10 = 0

11 - 20 = 1

该分区算法类似于numberrange分区算法。但在进行分片查找时先对分片字段值进行模patternValue运算,然后将得到的模数进行等同于numberrange分区算法的分区查找。

<tableRule name="sharding-by-string-jump">

     <rule>

         <columns>id</columns>

         <algorithm>jumphash</algorithm>

     </rule>

 </tableRule>

<function name="jumphash"

              class="jumpStringHash">

        <property name="partitionCount">2</property>

        <property name="hashSlice">0:2</property>

</function>

partitionCount:分片数量
hashSlice:分片截取长度

其核心思想是通过概率分布的方法将一个hash值在每个节点分布的概率变成1/n,并且可以通过更简便的方法可以计算得出,而且分布也更加均匀。

分片字段值为NULL时,数据恒落在0号节点之上

 

      1. 分表分库实现

配置如下:

Schema中定义了逻辑数据库lunch,在192.168.0.2、192.168.0.3均有数据库lunch,定义了两个分片节点dn1和dn2。

逻辑数据库中表lunchmenu、restaurant、userlunch、users这都只写入节点dn1,也就是192.168.0.2这台服务器,而dictionary写入了dn1、dn2两个节点,也就是192.168.0.2、192.168.0.3这两台服务器。分片的规则为:mod-long。

rule属性的内容来源于rule.xml这个文件,DBLE支持10种分表分库的规则,基本能满足你所需要的要求。

    1. 读写分离

模拟一主两从的架构,模拟服务分布在3台服务器上,需要创建9个实例,每个实例上有3个db需要分别拆分。

配置如下:

这样的配置与前一个示例配置改动如下:

删除了table分配的规则,分片datanode只有一个,datahost也只有一台,但是writehost中添加了readhost,balance改为1,表示读写分离。以上配置达

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u010882691/article/details/82256955
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-27 23:43:34
  • 阅读 ( 1334 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢