文章目录- 一 数据库性能优化
- 数据库性能瓶颈主要原因
- 数据性能优化方案
- 读写分离
- 分库分表
- 垂直拆分
- 水平拆分
- 二 mycat
- 主从复制原理
- 配置主从
- 主从复制的延迟
- mycat 配置文件
- mycat目录
- 1.schema.xml
- 2.server.xml
- rule.xml
- 连续分片
- 连续分片之自定义数字范围分片
- 连续分片之按日期(天,月)分片
- 连续分片之按单月小时分片
- 离散分片
- 离散分片之枚举分片
- 离散分片之十进制取模
- 离散分片之应用指定分片
- 离散分片之字符串截取数字hash分片
- 离散分片之一致性Hash分片
- 理解一致性Hash
- 综合类分片
- 综合分片之范围求模分片
- 综合分片之取模范围约束分片
- 分片取舍
- 分片选择总结
- 三 全局序列
- 四 Mycat之注解
- 五 Mycat命令行监控工具
- 六 Mycat弱XA事务机制
- 七 Mycat之节点扩缩容
- 八 Mycat之mysqldump方式进行快速移植
- 九 mycat之高可用
- 数据库性能瓶颈主要原因
- 数据性能优化方案
- 读写分离
- 分库分表
- 垂直拆分
- 水平拆分
- 主从复制原理
- 配置主从
- 主从复制的延迟
- mycat目录
- 1.schema.xml
- 2.server.xml
- rule.xml
- 连续分片
- 连续分片之自定义数字范围分片
- 连续分片之按日期(天,月)分片
- 连续分片之按单月小时分片
- 离散分片
- 离散分片之枚举分片
- 离散分片之十进制取模
- 离散分片之应用指定分片
- 离散分片之字符串截取数字hash分片
- 离散分片之一致性Hash分片
- 理解一致性Hash
- 综合类分片
- 综合分片之范围求模分片
- 综合分片之取模范围约束分片
- 分片取舍
- 分片选择总结
- 连续分片
一 数据库性能优化
数据库性能瓶颈主要原因
1,数据库连接
2,表数据量(空间存储的问题)
索引
命中不了 全表的扫描
代码语言:javascript复制命中索引
硬盘级索引,它是存储在硬盘里面 IO操作
3,硬件资源限制(QPSTPS)
数据性能优化方案
1,sql优化
2,缓存
3,建好索引
4,读写分离
5,分库分表
读写分离
区别读、写多数据源方式进行数据的存储和加载。 数据的存储(增删改)一般指定写数据源,数据的读取查询指定读数据源(读写分离会基于主从复制)
1,数据库连接
2,硬件资源限制(QPSTPS)
主从形式 有 一主一从 互为主从 一主多从 级联多从
分库分表
对数据的库表进行拆分,用分片的方式对数据进行管理。
按拆分规则分为垂直拆分和水平拆分
垂直拆分
1,数据库连接
2,硬件资源限制(QPSTPS)
水平拆分
1,表数据量大的问题 存储空间也解决了
1,数据库连接
2,硬件资源限制(QPSTPS)
二 mycat
Mycat 是开源的分布式数据库中间件,基于阿里的cobar的开源框架之上。它处于数据库服务与应用服务之间。它是进行数据处理与整合的中间服务。
通俗点讲,应用层可以将它看作是一个数据库的代理(或者直接看成加强版数据库)
逻辑库 db_user db_store
逻辑表
分片表 用户表
全局表 数字字典表
ER表 用户地址表
非分片表 门店表,店员表
分片规则 userID%2
节点
节点主机(写、读节点主机)
主从复制原理
- master将操作记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events)
- Slave通过I/O Thread异步将master的binary log events拷贝到它的中继日志(relay log);
- Slave执行relay日志中的事件,匹配自己的配置将需要执行的数据,在slave服务上执行一遍从而达到复制数据的目的。
配置主从
Master操作:
- 接入mysql并创建主从复制的用户 create user m2ssync identified by ‘Qq123!@#’;
- 给新建的用户赋权 GRANT REPLICATION SLAVE ON . TO ‘m2ssync’@’%’ IDENTIFIED BY ‘Qq123!@#’;
- 指定服务ID,开启binlog日志记录,在my.cnf中加入 server-id=137 log-bin=dbstore_binlog binlog-do-db=db_store
- 通过SHOW MASTER STATUS;查看Master db状态.
Slave操作: 1.指定服务器ID,指定同步的binlog存储位置,在my.cnf中加入
server-id=101
relay-log=slave-relay-bin
relay-log-index=slave-relay-bin.index
read_only=1
replicate_do_db=db_store
2.接入slave的mysql服务,并配置change master to master_host=‘192.168.8.137’, master_port=3306,master_user=‘m2ssync’,master_password=‘Qq123!@#’,master_log_file=‘db_store_binlog’,master_log_pos=0;
3.start slave;
4.show slave statusG ;查看slave服务器状态
主从复制的延迟
延迟是怎么产生的
1,当master tps高于slave的sql线程所能承受的范围
2,网络原因
3,磁盘读写耗时
判断延迟?
1,show slave status G; sends_behind_master 0
2, mk-heartbeat timestamp进行实践搓的判断
我们怎么解决延迟问题
1,配置更高的硬件资源
2,把IOthread 改变成 多线程的方式
mysql5.6 库进行多线程的方式
GTID进行多线程的方式
3, 应用程序自己去判断(mycat有这么方案)
mycat 配置文件
mycat目录
bin 程序目录,存放了 window 版本和 linux 版本可执行文件./mycat {start|restart|stop|status…}
conf 目录下存放配置文件,
server.xml 是 Mycat 服务器参数调整和用户授权的配置文件
schema.xml 是逻辑库定义和表以及分片定义的配置文件
rule.xml 是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在 这个目录下
log4j2.xml配置logs目录日志输出规则
wrapper.conf JVM相关参数调整
lib 目录下主要存放 mycat 依赖的一些 jar 文件
logs目录日志存放日志文件
1.schema.xml
dataHost
balance:
负载/读写分离 均衡类型。
取值为
balance=“0”, 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
balance=“1”,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双
主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载
均衡。
balance=“2”,所有读操作都随机的在 writeHost、readhost 上分发。
switchType
主从切换策略
-1 表示不自动切换
1 默认值,自动切换
2 基于 MySQL 主从同步的状态决定是否切换
心跳语句设置为 show slave status
通过检测 show slave status 中的 “Seconds_Behind_Master”, “Slave_IO_Running” “Slave_SQL_Running” 三个字段以及slaveThreshold 设置的值进行判断是否进行主从切换
usingDecrypt
可加入usingDecrypt属性来指定密码加密。1开启,0不开启
进入lib目录的Mycat-server-1.6-RELEASE.jar 执行
java -cp Mycat-server-1.6-RELEASE.jar io.mycat.util.DecryptUtil 1:host:user:password
1:host:user:password 中 1 为 db 端加密标志,host 为 dataHost 的 host 名称
2.server.xml
sequnceHandlerType
全局序列的方式
firewall
黑白名单设置
user
benchmark 当前端连接达到设置的值,不再允许这个用户进行接入
表级的DML权限控制。4位2进制 顺序为 insert update select delete
rule.xml
连续分片
优点:扩容无需迁移数据,范围条件查询资源消耗小
缺点:数据热点问题,并发能力受限于分片节点
代表:
按日期(天)分片 自定义数字范围分片 自然月分片
连续分片之自定义数字范围分片
自定义数字范围分片,提前规划好分片字段某个范围属于哪个分片
代码语言:javascript复制<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
<property name="defaultNode">0</property>
</function>
defaultNode 超过范围后的默认节点。
此配置非常简单,即预先制定可能的id范围到某个分片 0-500M=0 500M-1000M=1 1000M-1500M=2 或 0-10000000=0 10000001-20000000=1 注意: 所有的节点配置都是从0开始,及0代表节点1
连续分片之按日期(天,月)分片
按日期(天)分片: 从开始日期算起,按照天数来分片
代码语言:javascript复制<function name=“sharding-by-date” class=“io.mycat.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property> <!--日期格式-->
<property name="sBeginDate">2014-01-01</property> <!--开始日期-->
<property name="sPartionDay">10</property> <!--每分片天数-->
</function>
按日期(自然月)分片: 从开始日期算起,按照自然月来分片
代码语言:javascript复制<function name=“sharding-by-month” class=“io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property> <!--日期格式-->
<property name="sBeginDate">2014-01-01</property> <!--开始日期-->
</function>
注意: 需要提前将分片规划好,建好,否则有可能日期超出实际配置分片数
连续分片之按单月小时分片
按单月小时分片:最小粒度是小时,可以一天最多24个分片,最少1个分片,一个月完后下月从头开始循环。
代码语言:javascript复制<function name="sharding-by-hour" class=“io.mycat.route.function.LatestMonthPartion">
<property name="splitOneDay">24</property> <!-- 将一天的数据拆解成几个分片-->
</function>
注意事项:每个月月尾,需要手工清理数据
离散分片
优点:数据分布均匀,并发能力强,不受限分片节点
缺点:移植性差,扩容难
代表: 枚举分片 数字取模分片 字符串数字hash分片 一致性哈希分片 程序指定
离散分片之枚举分片
枚举分片:通过在配置文件中配置可能的枚举id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的
代码语言:javascript复制<function name="hash-int" class=“io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">0</property>
<property name="defaultNode">0</property>
</function>
partition-hash-int.txt 配置: 10000=0 10010=1
mapFile标识配置文件名称 type默认值为0(0表示Integer,非零表示String) 默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
离散分片之十进制取模
十进制求模分片:规则为对分片字段十进制取模运算。数据分布最均匀
代码语言:javascript复制<function name="mod-long" class=“io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property>
</function>
离散分片之应用指定分片
应用指定分片:规则为对分片字段进行字符串截取,获取的字符串即指定分片。
代码语言:javascript复制<function name="sharding-by-substring“ class="io.mycat.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property><!-- zero-based -->
<property name="size">2</property>
<property name="partitionCount">8</property>
<property name="defaultPartition">0</property>
</function>
startIndex 开始截取的位置 size 截取的长度 partitionCount 分片数量 defaultPartition 默认分片
例如 id=05-100000002 在此配置中代表根据 id 中从 startIndex=0,开始,截取 size=2 位数字即 05,05 就是获取的分区,如果没传 默认分配到 defaultPartition
离散分片之字符串截取数字hash分片
截取数字hash分片 此规则是截取字符串中的int数值hash分片
代码语言:javascript复制<function name="sharding-by-stringhash" class=“io.mycat.route.function.PartitionByString">
<property name=length>512</property><!-- zero-based -->
<property name="count">2</property>
<property name="hashSlice">0:2</property>
</function>
length代表字符串hash求模基数,count分区数,其中length*count=1024 hashSlice hash预算位,即根据子字符串中int值 hash运算 0 代表 str.length(), -1 代表 str.length()-1,大于0只代表数字自身 可以理解为substring(start,end),start为0则只表示0 例1:值“45abc”,hash预算位0:2 ,取其中45进行计算 例2:值“aaaabbb2345”,hash预算位-4:0 ,取其中2345进行计算
离散分片之一致性Hash分片
一致性Hash分片: 此规则优点在于扩容时迁移数据量比较少,前提分片节点比较多,虚拟节点分配多些。 虚拟节点少的缺点是会造成数据分布不够均匀 如果实际分片数量比较少,迁移量会比较多
代码语言:javascript复制<function name="murmur" class=“io.mycat.route.function.PartitionByMurmurHash">
<property name="seed">0</property><!-- 创建hash对象的种子,默认0-->
<property name="count">2</property><!-- 要分片的数据库节点数量,必须指定,否则没法分片-->
<property name="virtualBucketTimes">160</property>
</function>
注意: 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍
理解一致性Hash
1.hash(str) { return 0 -> 2^32 },将整个0-2^32的hash值,作为一个hash环。
2.取node唯一标示计算出hash值,该hash结果即node在整个hash环中的位置
3.将数据进行hash计算之后,顺时针找对应的node,改node即为该数据的服务node
综合类分片
兼并二者
代表: 范围求模分片 取模范围约束分片 …
综合分片之范围求模分片
范围求模分片:先进行范围分片计算出分片组,组内再求模。 优点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题 分片组内使用求模可以保证组内数据比较均匀,分片组之间是范围分片可以兼顾范围查询。
最好事先规划好分片的数量,数据扩容时按分片组扩容,则原有分片组的数据不需要迁移。 由于分片组内数据比较均匀,所以分片组内可以避免热点数据问题。
代码语言:javascript复制<function name="rang-mod" class=“io.mycat.route.function.PartitionByRangeMod">
<property name="mapFile">partition-range-mod.txt</property>
<property name="defaultNode">32</property>
</function>
partition-range-mod.txt 以下配置一个范围代表一个分片组,=号后面的数字代表该分片组所拥有的分片的数量。 0-200M=5 //代表有5个分片节点 200M-400M=6 400M-600M=6 600M-800M=8 800M-1000M=7
综合分片之取模范围约束分片
取模范围约束分片: 对指定分片列进行取模后再由配置决定数据的节点分布。
代码语言:javascript复制<function name="sharding-by-pattern" class=“io.mycat.route.function.PartitionByPattern">
<property name="patternValue">256</property>
<property name="defaultNode">2</property>
<property name="mapFile">partition-pattern.txt</property>
</function>
patternValue 即求模基数, defaoultNode 默认节点 partition-pattern.txt配置 1-32=0 33-64=1 65-96=2 97-128=3 128-256=4
配置文件中,1-32 即代表id%6后分布的范围。 如果id非数字,则会分配在defaoultNode 默认节点
分片取舍
数据特点:活跃的数据热度较高规模可以预期,增长量比较稳定
数据特点:活跃的数据为历史数据,热度要求不高。规模可以预期,增长量比较稳定.优势可定时清理或者迁移数据
分片选择总结
1,根据业务数据的特性合理选择分片规则 2,善用全局表、ER关系表解决join操作 3,用好primaryKey让你的性能起飞
三 全局序列
1,本地文件方式
sequnceHandlerType = 0 配置sequence_conf.properties 使用next value for MYCATSEQ_XXX 2,数据库方式 sequnceHandlerType = 1 配置sequence_db_conf.properties 使用next value for MYCATSEQ_XXX或者指定autoIncrement 3,本地时间戳方式 ID= 64 位二进制 (42(毫秒) 5(机器 ID) 5(业务编码) 12(重复累加) sequnceHandlerType = 2 配置sequence_time_conf.properties 指定autoIncrement
4, 程序方式 Snowflake UUID Redis …
四 Mycat之注解
代码语言:javascript复制/*!mycat: sql=select * from users where userID=1*/ select fun() from dual;
/*!mycat: sql=select * from users where userID=1*/ CALL proc_test();
/*!mycat: sql=select * from users where userID=1*/ insert into users(id,name) select id,name from otherUsers;
/*!mycat: db_type=slave*/ select * from employee
/*!mycat: sql=select 1 from users */ create table ttt(id int);
/*!mycat:catlet=io.mycat.catlets.ShareJoin */
select * from users u,employee em on u.phoneNum=em.phoneNum where u.phoneNum ='13633333333' ;
##Mycat关联查询的问题总结
1.用好ER表 2.善用全局表 3.使用注解
代码语言:javascript复制/*!mycat:catlet=io.mycat.catlets.ShareJoin */
select * from users u,employee em on u.phoneNum=em.phoneNum where u.phoneNum ='13633333333' ;
五 Mycat命令行监控工具
重载配置文件 查看运行状态 提供性能数据
代码语言:javascript复制mysql -uuser –ppwd -P9066
show @@help 查看所有命令
reload @@config
reload @@config_all
show @@database
show @@datanode
show @@datasource
show @@cache
show @@connection
show @@connection.sql
show @@backend
kill @@connection id1,id2
show @@heartbeat
show @@sysparam
六 Mycat弱XA事务机制
为什么2PC提交.
- 是2PC才会有事务管理器统一管理的机会;
- 尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶段将是耗时极短,耗时极短意味着操作失败的可能性也就降低
XA 是一个两阶段提交协议,规定事务协调/管理器和资源管理器接口 二阶段提交协议为了保证事务的一致性,不管是事务管理器还是各个资源管理器,每执行一步操作,都会记录日志,为出现故障后的恢复准备依据
Mycat 第二阶段的提交没有做相关日志的记录,所以说他是一个弱XA的分布式事务解决方案
七 Mycat之节点扩缩容
自带的mycat工具进行扩容缩容
mycat 所在环境安装 mysql 客户端程序
mycat 的 lib 目录下添加 mysql 的 jdbc 驱动包
对扩容缩容的表所有节点数据进行备份,以便迁移失败后的数据恢复
编辑newSchema.xml 和 newRule.xml
配置conf/migrateTables.properties
修改bin/dataMigrate.sh,执行dataMigrate.sh
注意前方坑位【坑坑坑】: 1,一旦执行数据是不可逆的 2,只能支持分片表的扩缩容 3,分片规则必须一致,只能节点扩或者缩
八 Mycat之mysqldump方式进行快速移植
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FAJtd1wW-1595724430095)(C:UsershuayuAppDataRoamingTyporatypora-user-imagesimage-20200725201119496.png)]
mysqldump方式
导出数据
mysqldump -uroot -p123456 -h192.168.8.137 -c db_user_old users > users.sql
ER子表
mysqldump -uroot -p123456 -h192.168.8.137 -c --skip-extended-insert db_user_old user_address > userAddress.sql
导入
mysql -h192.168.8.151 -uroot -p123456 -P8066 -f db_user < users.sql
mysql -h192.168.8.151 -uroot -p123456 -P8066 -f db_user < userAddress.sql
九 mycat之高可用
Haproxy四层负载
四层负载均衡
四层负载均衡也称为四层交换机,它主要是通过分析IP层及TCP/UDP层的流量实现的基于IP加端口的负载均衡 LVS,F5是四层负载
七层负载均衡
七层负载均衡器也称为七层交换机,位于OSI( Open System Interconnection ,开放式系统互联)的最高层,即应用层,此时负载均衡器支持多种应用协议,常见的有HTTP、FTP、SMTP等 haproxy Nginx是七层负载
灵魂拷问:
* 单表数据达到多少的时候会影响数据库的查询性能?为什么?
* 主从复制机制的原理概述是怎样的?常见的存在形式有哪些?
* 分库分表中解释一下垂直和水平2种不同的拆分?
* 分库分表中垂直分库方案会带来哪些问题?
* 分布式数据存储中间件如mycat的核心流程是什么?
* 概述一下mycat?
* 解释一下全局表,ER表,分片表?
* Mycat的在分库分表之后,它是怎么支持联表查询的?
* 进行库表拆分时,拆分规则怎么取舍?
* Mycat中全局ID方案有哪些?程序自定义全局ID的方案有哪些?
* 简述一下一致性hash的原理?这样设计的好处是什么?
* 4层负载和7层负载谁性能更高?为什么?这2者区别是什么?
* 讲一讲高可用方案