最后总结
ActiveMQ+Kafka+RabbitMQ学习笔记PDF
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
3.1.2 建新表&迁移数据&binlog同步
1) 新表字符集建议是utf8mb4,支持表情符。新表建好后索引不要漏掉,否则可能会导致慢sql!从经验来看索引被漏掉时有发生,建议事先列计划的时候将这些要点记下,后面逐条检查;
2) 使用全量同步工具或者自己写job来进行全量迁移;全量数据迁移务必要在业务低峰期时操作,并根据系统情况调整并发数;
3) 增量同步。全量迁移完成后可使用binlog增量同步工具来追数据,比如阿里内部使用精卫,其它企业可能有自己的增量系统,或者使用阿里开源的cannal/otter:https://github.com/alibaba/canal?spm=5176.100239.blogcont11356.10.5eNr98
https://github.com/alibaba/otter/wiki/QuickStart?spm=5176.100239.blogcont11356.21.UYMQ17
增量同步起始获取的binlog位点必须在全量迁移之前,否则会丢数据,比如我中午12点整开始全量同步,13点整全量迁移完毕,那么增量同步的binlog的位点一定要选在12点之前。
位点在前会不会导致重复记录?不会!线上的MySQL binlog是row 模式,如一个delete语句删除了100条记录,binlog记录的不是一条delete的逻辑sql,而是会有100条binlog记录。insert语句插入一条记录,如果主键冲突,插入不进去。
3.1.3 联表查询sql改造
现在主键已经接入全局唯一id,新的库表、索引已经建立,且数据也在实时追平,现在可以开始切库了吗?no!
考虑以下非常简单的联表查询sql,如果将B表拆分到另一个库里的话,这个sql怎么办?毕竟跨库联表查询是不支持的!
因此,在切库之前,需要将系统中上百个联表查询的sql改造完毕。
如何改造呢?
1) 业务避免
业务上松耦合后技术才能松耦合,继而避免联表sql。但短期内不现实,需要时间沉淀;
2) 全局表
每个应用的库里都冗余一份表,缺点:等于没有拆分,而且很多场景不现实,表结构变更麻烦;
3) 冗余字段
就像订单表一样,冗余商品id字段,但是我们需要冗余的字段太多,而且要考虑字段变更后数据更新问题;
4) 内存拼接
4.1)通过RPC调用来获取另一张表的数据,然后再内存拼接。1)适合job类的sql,或改造后RPC查询量较少的sql;2)不适合大数据量的实时查询sql。假设10000个ID,分页RPC查询,每次查100个,需要5ms,共需要500ms,rt太高。
4.2)本地缓存另一张表的数据
适合数据变化不大、数据量查询大、接口性能稳定性要求高的sql。
3.1.4切库方案设计与实现(两种方案)
以上步骤准备完成后,就开始进入真正的切库环节,这里提供两种方案,我们在不同的场景下都有使用。
a)DB停写方案
优点:快,成本低;
缺点:
1)如果要回滚得联系DBA执行线上停写操作,风险高,因为有可能在业务高峰期回滚;
2)只有一处地方校验,出问题的概率高,回滚的概率高
举个例子,如果面对的是比较复杂的业务迁移,那么很可能发生如下情况导致回滚:
sql联表查询改造不完全;
sql联表查询改错&性能问题;
索引漏加导致性能问题;
字符集问题
此外,binlog逆向回流很可能发生字符集问题(utf8mb4到gbk),导致回流失败。这些binlog同步工具为了保证强最终一致性,一旦某条记录回流失败,就卡住不同步,继而导致新老表的数据不同步,继而无法回滚!
b)双写方案
第2步“打开双写开关,先写老表A再写新表B”,这时候确保写B表时try catch住,异常要用很明确的标识打出来,方便排查问题。第2步双写持续短暂时间后(比如半分钟后),可以关闭binlog同步任务。
优点:
1)将复杂任务分解为一系列可测小任务,步步为赢;
2)线上不停服,回滚容易;
3)字符集问题影响小
缺点:
1)流程步骤多,周期长;
2)双写造成RT增加
3.1.5 开关要写好
不管什么切库方案,开关少不了,这里开关的初始值一定要设置为null!
如果随便设置一个默认值,比如”读老表A“,假设我们已经进行到读新表B的环节了。这时重启了应用,在应用启动的一瞬间,最新的“读新表B”的开关推送等可能没有推送过来,这个时候就可能使用默认值,继而造成脏数据!
3.2 拆分后一致性怎么保证?
以前很多表都在一个数据库内,使用事务非常方便,现在拆分出去了,如何保证一致性?
1)分布式事务
性能较差,几乎不考虑。
2)消息机制补偿(如何用消息系统避免分布式事务?)
3)定时任务补偿
用得较多,实现最终一致,分为加数据补偿,删数据补偿两种。
3.3 应用拆分后稳定性怎么保证?
一句话:怀疑第三方,防备使用方,做好自己!
1**)怀疑第三方**
a)防御式编程,制定好各种降级策略;
- 比如缓存主备、推拉结合、本地缓存……
b)遵循快速失败原则,一定要设置超时时间,并异常捕获;
c)强依赖转弱依赖,旁支逻辑异步化
- 我们对某一个核心应用的旁支逻辑异步化后,响应时间几乎缩短了1/3,且后面中间件、其它应用等都出现过抖动情况,而核心链路一切正常;
d)适当保护第三方,慎重选择重试机制
2**)防备使用方**
a)设计一个好的接口,避免误用
-
遵循接口最少暴露原则;很多同学搭建完新应用后会随手暴露很多接口,而这些接口由于没人使用而缺乏维护,很容易给以后挖坑。听到过不只一次对话,”你怎么用我这个接口啊,当时随便写的,性能很差的“;
-
不要让使用方做接口可以做的事情;比如你只暴露一个getMsgById接口,别人如果想批量调用的话,可能就直接for循环rpc调用,如果提供getMsgListByIdList接口就不会出现这种情况了。
-
避免长时间执行的接口;特别是一些老系统,一个接口背后对应的可能是for循环select DB的场景。
-
…
b)容量限制
-
按应用优先级进行流控;不仅有总流量限流,还要区分应用,比如核心应用的配额肯定比非核心应用配额高;
-
业务容量控制。有些时候不仅仅是系统层面的限制,业务层面也需要限制。举个例子,对saas化的一些系统来说,”你这个租户最多1w人使用“。
3**)做好自己**
a)单一职责
b)及时清理历史坑
- 例:例如我们改造时候发现一年前留下的坑,去掉后整个集群cpu使用率下降1/3
c) 运维SOP****化
- 说实话,线上出现问题,如果没有预案,再怎么处理都会超时。曾经遇到过一次DB故障导致脏数据问题,最终只能硬着头皮写代码来清理脏数据,但是时间很长,只能眼睁睁看着故障不断升级。经历过这个事情后,我们马上设想出现脏数据的各种场景,然后上线了三个清理脏数据的job,以防其它不可预知的产生脏数据的故障场景,以后只要遇到出现脏数据的故障,直接触发这三个清理job,先恢复再排查。
d)资源使用可预测
-
应用的cpu、内存、网络、磁盘心中有数
-
- 正则匹配耗cpu
-
耗性能的job优化、降级、下线(循环调用rpc或sql)
-
慢sql优化、降级、限流
-
tair/redis、db调用量要可预测
-
例:tair、db
举个例子: 某一个接口类似于秒杀功能,qps非常高(如下图所示),请求先到tair,如果找不到会回源到DB,当请求突增时候,甚至会触发tair/redis这层缓存的限流,此外由于缓存在一开始是没数据的,请求会穿透到db,从而击垮db。
这里的核心问题就是tair/redis这层资源的使用不可预测,因为依赖于接口的qps,怎么让请求变得可预测呢?
如果我们再增加一层本地缓存(guava,比如超时时间设置为1秒),保证单机对一个key只有一个请求回源,那样对tair/redis这层资源的使用就可以预知了。假设有500台client,对一个key来说,一瞬间最多500个请求穿透到Tair/redis,以此类推到db。
再举个例子:
比如client有500台,对某key一瞬间最多有500个请求穿透到db,如果key有10个,那么请求最多可能有5000个到db,恰好这些sql的RT有些高,怎么保护DB的资源?
可以通过一个定时程序不断将数据从db刷到缓存。这里就将不可控的5000个qps的db访问变为可控的个位数qps的db访问。
4 总结
1**)做好准备面对压力!**
2**)复杂问题要拆解为多步骤,每一步可测试可回滚!**
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-HGCkt99I-1715234704108)]