目标
Ø 掌握数据库的大数据处理方案和HA
Ø 掌握为什么需要数据库中间件,何为数据库中间件
Ø 掌握不同场景所需的数据库中间件特性
Ø 掌握数据库中间件设计要点
海量数据分片之分库分表
大数据处理-回顾分区
应对大数据的处理,在分库分表之前,我们可以用分区,提升数据库的性能
大数据处理-分片理解
随着业务的发展,业务越来越复杂,应用的模块越来越多,总的数据量很大,高并发读写操作均超过单个 数据库服务器的处理能力怎么办?
数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中
数据分片的有效手段是对关系型数据库进行分库和分表
分库又叫垂直拆分,或者纵向拆分,指的是按照业务模块将数据分散到不同的数据库服务器
就是把原本存储于一个库的表拆分存储到多个库上,通常是将表按照功能模块、关系密切程度划分出来, 部署到不同的库上。
如果数据库是因为表太多而造成海量数据,并且项目的各项业务逻辑划分清晰、低耦合,那么规则简单明 了、容易实施的首选就是分库。
大数据处理-分库图例
优点:
Ø 拆分后业务清晰,拆分规则明确;
Ø 系统之间整合或扩展容易;
Ø 数据维护简单。
缺点:
Ø 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度;
Ø 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高;
Ø 事务处理复杂。
大数据处理-分表理解
垂直拆分可以缓冲数据量和访问量带来的问题,但无法根治。
如果单个表的数量很大,超出了单表的存储上限,如电商网站的商品表、订单表等该怎么办?
如果垂直拆分之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。
分表又叫水平切分,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则或逻辑,将一个表的数据拆分成多份,分别存储在多个表结构一样的表中,这多个表可以存在一到多个库中,每个分片仅包含数据的一部分。
大数据处理-分表类型
分表又分成垂直分表和水平分表:
Ø 垂直分表:将本来可以在同一个表的内容,划分为多个表。(按照关系型数据库的第三范式要求,是应该在同一个表的。)
Ø 水平分表:是把一个表复制成同样表结构的不同表,然后把数据按照一定的规则划分,分别存储到这些表中,从而保证单表的容量不会太大,提升性能;当然这些结构一样的表,可以放在一个或多个数据库中。
大数据处理-分表图例
优点:
Ø 拆分规则抽象好,join 操作基本可以数据库做;
Ø 不存在单库大数据,高并发的性能瓶颈;
Ø 应用端改造较少;
Ø 提高了系统的稳定性跟负载能力。
缺点:
Ø 拆分规则难以抽象;
Ø 分片事务一致性难以解决;
Ø 数据多次扩展难度跟维护量极大;
Ø 跨库join 性能较差。
水平拆分—分片规则
水平对数据进行拆分最重要的是分片规则—拆分规则
可以如何来拆分?
Ø 范围:时间、数值;
Ø 列表:按地域、按组织、分类;
Ø 散列:hash(某个字段) % 分片数、一致性hash;
Ø 复合多种方式。
分库分表会带来的挑战
分库分表的技术难点
无论垂直拆分、水平拆分,都有共同的技术难点:
Ø 分布式事务的问题;
Ø 跨节点Join的问题;
Ø 跨节点合并排序分页问题;
Ø 多数据源管理问题。
需要一个这样的东西
Ø 1 要能解析SQL
Ø 2 能支持读写分离
Ø 3 能支持从库读的负载均衡
Ø 4 支持分库操作
Ø 5 支持分表操作
Ø 6 支持跨库关联查询
Ø 7 对事务处理的支持
Ø 8 主键ID生成
Ø 9 数据源管理
数据库中间件的分类和分库分表实战
数据库中间件的两种实现模式
客户端模式,在应用程序中集成数据库中间件模块,通过该模块来配置管理应用需要的一个(或者多个)数据源,以及访问各个数据源,在模块内完成数据的整合。
服务端(代理)模式,通过中间代理层来统一管理所有的数据源,后端数据库集群对前端应用程序透明,同时易于数据库扩展。独立的服务能提供更强的处理能力。适用于大型复杂系统。
常用数据库中间件简介
Mycat是什么
Ø 一个彻底开源的,面向企业应用开发的大数据库集群
Ø 支持事务、ACID、可以替代MySQL的加强版数据库
Ø 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
Ø 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
Ø 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
Ø 一个新颖的数据库中间件产品。
官网地址: http://www.mycat.io
Github地址: https://github.com/MyCATApache
Github上文档地址: https://github.com/MyCATApache/Mycat-doc
Mycat 由来
2013年阿里的Cobar在社区使用过程中发现存在一些比较严重的问题,及其使用限制,经过Mycat发起人第一次改良,第一代改良版——Mycat诞生。 Mycat开源以后,一些Cobar的用户参与了Mycat的开发,最终Mycat发展成为一个由众多软件公司的实力派架构师和资深开发人员维护的社区型开源软件。
Mycat 课程安装
Ø 1 JDK1.7+ Mycat是用java开发
Ø 2 MySQL统一5.7 镜像地址: http://mirrors.163.com/mysql/Downloads/MySQL5.7/mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
Ø 3 Mycat安装包 下载地址: http://dl.mycat.io 当前最新版本:1.6.6.1
Mycat使用说明
Ø 1 源码方式导入到IDE,源码地址: https://github.com/MyCATApache/Mycat-Server.git
Ø 2 安装包方式安装,下载地址: http://dl.mycat.io
核心概念
数据库中间件:对应用,mycat就是数据库服务,mycat是后端数据库集群的代理
schema.xm
<mycat:schema>
<schema name="testdb">
<table name="orders" primaryKey="ID"type="global" dataNode="dn1,dn2" />
</schema>
<dataNode name="dn1" dataHost="dhost1" database="db1" />
<dataHost name="dhost1" ...>
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="localhost:3306"...>
<readHost host="hostS2" url="192.168.1.2:3306".../>
</writeHost>
</dataHost>
</mycat:schema>
逻辑概念:
Ø 逻辑库:mycat数据库服务中定义、管理的数据库
Ø 逻辑表:逻辑库中包含的需分库分表存储的表
Ø dataNode:数据节点(分片节点),逻辑表分片的存放节点。
Ø dataHost: 数据主机(节点主机),数据节点所在的主机。
物理概念
Ø writeHost:写主机,真实的数据库服务主机描述
Ø readHost:读主机,真实的数据库服务主机描述
分库分表的优缺点和原则
大数据处理-分片优点
Ø 解决磁盘系统最大文件限制,比如常见的有:
FAT16(最大分区2GB,最大文件2GB)
FAT32(最大分区32GB,最大容量2TB,最大文件32G)
NTFS(最大分区2TB,最大容量,最大文件2TB)
EXT3(最大文件大小: 2TB,最大文件极限: 仅受文件系统大小限制,最大分区/文件系统大小: 4TB,最大文件名长度: 255 字符)
Ø 减少增量数据写入时的锁对查询的影响,减少长时间查询造成的表锁,影响写入操作等锁竞争的情况,节省排队的时间开支,增加呑吐量。
Ø 由于单表数量下降,常见的查询操作由于减少了需要扫描的记录,使得单表单次查询所需的检索行数变少,减少了磁盘IO,时延变短。
大数据处理-分库原则
基本的思路就是分析业务功能,以及表间的聚合关系,把关系紧密的表放在一起。分库的粒度指的是在做切分时允许几级的关联表放在一起,这个问题对应用程序实现有着很大的影响。关联打断的越多,则受影响的join操作越多。
实际的粒度掌控需要结合“业务紧密程度”和“表的数据量”两个因素综合考虑
Ø 若划归到一起的表关系紧密,且数据量并不大,增速也非常缓慢,则适宜放在一起,不需要再进行水平切分;
Ø 若划归到一起的表的数据量巨大且增速迅猛,则势必要在分库的基础上再进行分表,这就意味着原单一的库还可能会被拆分成多个库,这会导致更多的复杂性,一开始最好就要考虑进去
对于垂直分表,通常是按照业务功能的使用频次,把主要的、热门的字段放在一起做为主要表;然后把不常 用的,按照各自的业务属性进行聚集,拆分到不同的次要表中;主要表和次要表的关系一般都是一对一的。
对于水平分表,通常是按照具体的业务规则和数据的格式,选择能够把数据进行合理拆分的业务数据做为拆 分标准,以此来对数据进行拆分。
水平对数据进行拆分最重要的是分片规则—拆分规则
Ø 范围:时间、数值;
Ø 列表:按地域、按组织、分类;
Ø 散列:hash(某个字段) % 分片数、一致性hash;
Ø 复合多种方式。
数据库拆分原则
第一原则:能不切分尽量不要切分
第二原则:如果要切分一定要选择合适的切分规则,提前规划好。
第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库Join 的可能。
第四原则:由于数据库中间件对数据Join实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表Join。
实验代码
rule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<tableRule name="rule2">
<rule>
<columns>user_id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<tableRule name="sharding-by-intfile">
<rule>
<columns>sharding_id</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
<tableRule name="mod-long">
<rule>
<columns>uuid</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<tableRule name="sharding-by-murmur">
<rule>
<columns>id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
<tableRule name="crc32slot">
<rule>
<columns>id</columns>
<algorithm>crc32slot</algorithm>
</rule>
</tableRule>
<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns>
<algorithm>partbymonth</algorithm>
</rule>
</tableRule>
<tableRule name="latest-month-calldate">
<rule>
<columns>calldate</columns>
<algorithm>latestMonth</algorithm>
</rule>
</tableRule>
<tableRule name="auto-sharding-rang-mod">
<rule>
<columns>id</columns>
<algorithm>rang-mod</algorithm>
</rule>
</tableRule>
<tableRule name="jch">
<rule>
<columns>id</columns>
<algorithm>jump-consistent-hash</algorithm>
</rule>
</tableRule>
<function name="murmur"
class="io.mycat.route.function.PartitionByMurmurHash">
<property name="seed">0</property>
<property name="count">2</property>
<property name="virtualBucketTimes">160</property>
</function>
<function name="crc32slot"
class="io.mycat.route.function.PartitionByCRC32PreSlot">
</function>
<function name="hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
</function>
<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
<function name="func1" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">8</property>
<property name="partitionLength">128</property>
</function>
<function name="latestMonth"
class="io.mycat.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property>
</function>
<function name="partbymonth"
class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2015-01-01</property>
</function>
<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
<property name="mapFile">partition-range-mod.txt</property>
</function>
<function name="jump-consistent-hash" class="io.mycat.route.function.PartitionByJumpConsistentHash">
<property name="totalBuckets">3</property>
</function>
</mycat:rule>
schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="mydb1" checkSQLschema="true" sqlMaxLimit="100">
<table name="t_order" primaryKey="uuid" autoIncrement="true" dataNode="dn1"/>
<table name="t_user" primaryKey="uuid" autoIncrement="true" dataNode="dn2,dn3" rule="mod-long" />
</schema>
<dataNode name="dn1" dataHost="dhost1" database="orderdb" />
<dataNode name="dn2" dataHost="dhost1" database="userdb" />
<dataNode name="dn3" dataHost="dhost2" database="userdb" />
<dataHost name="dhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<writeHost host="myhostM1" url="192.168.100.201:3306" user="root" password="5462837zhu"></writeHost>
</dataHost>
<dataHost name="dhost2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<writeHost host="myhostM2" url="192.168.100.202:3306" user="root" password="5462837zhu"></writeHost>
</dataHost>
</mycat:schema>
server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<user name="user">
<property name="password">user</property>
<property name="schemas">mydb1</property>
<property name="readOnly">false</property>
</user>
</mycat:server>
来源:oschina
链接:https://my.oschina.net/u/3728166/blog/3136607