一、主从复制
mysql主从同步的原理:
master提交完事务后,写入binlog
slave连接到master,获取binlog
master创建dump线程,推送binglog到slave
slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中
slave再开启一个sql线程读取relay log事件并在slave执行,完成同步
slave记录自己的binglog

由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。
全同步复制
主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。
半同步复制
和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
二、分库分表
分表的规则,分垂直分表和水平分表;
垂直分表
指的是拆分数据表的字段为多张数据表,分表的规则是依据冷热字段来进行区分的;例如,假设用户表中包含用户姓名、出生年月、手机号、籍贯、血型、星座、头像、昵称、签名等信息,因为用户的姓名、出生年月、籍贯、血型、星座等字段基本不会变化,而头像、昵称和签名等则会经常发生变化,这样就可以把其拆分成两个数据表;
水平分表
当数据表达到千万基本及以上的数据量后,可以利用水平分表的原理来解决查询变慢的问题;水平分表,通常是根据一个字段按照数据表的数量进行取模操作来实现的,切分数据表的字段,通常称为sharding_key;
假设当前的数据表有6千万条数据,分成32张表,则将用户的 uid%32 得到的数据存到相应的数据表中;
关于分表后的ID怎么保证唯一性的呢?因为我们主键默认都是自增的,那么分表之后的主键在不同表就肯定会有冲突了。有几个办法考虑:
(1)设定步长,比如1-1024张表我们分别设定1-1024的基础步长,这样主键落到不同的表就不会冲突了。
(2)分布式ID,自己实现一套分布式ID生成算法或者使用开源的比如雪花算法这种
(3)分表后不使用主键作为查询依据,而是每张表单独新增一个字段作为唯一主键使用,比如订单表订单号是唯一的,不管最终落在哪张表都基于订单号作为查询依据,更新也一样。
分表后非sharding_key的查询怎么处理呢?
(1)可以做一个mapping表,比如这时候商家要查询订单列表怎么办呢?不带user_id查询的话你总不能扫全表吧?所以我们可以做一个映射关系表,保存商家和用户的关系,查询的时候先通过商家查询到用户列表,再通过user_id去查询。
(2)打宽表,一般而言,商户端对数据实时性要求并不是很高,比如查询订单列表,可以把订单表同步到离线(实时)数仓,再基于数仓去做成一张宽表,再基于其他如es提供查询服务。
(3)数据量不是很大的话,比如后台的一些查询之类的,也可以通过多线程扫表,然后再聚合结果的方式来做。或者异步的形式也是可以的。
(4)除此之外,对于⾮shardingkey的查询可以通过落双份数据和数仓、ES的⽅案来解决,当然,如果分表后数据量很⼩的话,建好索引,扫全表查询其实也不是什么问题。
三、其他问题
3.1 mysql 的sql本身没问题的情况下,没⾛索引原因?
(1)数据量小,全表扫描速度更快
(2)索引字段辨识度不高
(3)索引字段上进行了运算
(4)索引类型的转换
3.2 什么是哈希索引?
除了B+树之外,还有一种常见的是哈希索引。
哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。
哈希索引的局限性:
哈希索引也没办法利用索引完成排序
不支持最左匹配原则
在有大量重复键值情况下,哈希索引的效率也是极低的——>哈希碰撞问题。
不支持范围查询
主流的还是使用B+树索引比较多,对于哈希索引,InnoDB是自适应哈希索引的(hash索引的创建由InnoDB存储引擎引擎自动优化创建,我们干预不了)!
