项目技术总结
零、多数据源管理方案1、核心是使用Spring提供的AbstractRoutingDataSource抽象类注入多个数据源。2、使用MyBatis注册多个SqlSessionFactory3、dynamic-datasource是MyBaits-plus作者设计的一个多数据源开源方案。使用这个框架需要引入对应的pom依赖一、分库分表、读写分离1. 对于前端的重复点击造成的订单问题前端进入确认订单界面的时候就先生成一个订单号ID。在订单点击提交的时候订单号和商品一起提交提交的按钮就置灰防止重复点击。由于网络的不可靠后端通过前端提交的订单号校验是否重复提交是非常有必要的。可以用布隆过滤器校验。2. 对于订单的ABA问题使用版本号解决。3. 对于分库分表来说能不分就不分。如果单表数据量太大就分表如果并发请求量高就分库。阿里给出参考建议对于单表在短期内会超过500万做分表处理。或者所有表加起来超过2GB则考虑分库。分表一般取2的幂次方关联的信息表绑定同步的分片表比如订单分表1对应订单详情分表1。订单的分片键要如何划分——》订单可以根据订单号用户ID的后两位做组合取模。这样同一个用户的数据不用跨表在一个表内就可以完成根据订单号查询订单详情或者根据用户查询订单信息的需求。比如在后续的对账过程中根据用户下的订单金额和银行的流水金额是否匹配。4. 对于读多写少的要做读写分离提高数据库的并发能力。读写分离分数据库层面和应用层面数据库层面做主从备份的机制。在应用层面要做路由控制主节点写从节点读减轻数据库的压力。5. 读写分离的数据不一致问题主从同步延迟带来的读写不一致问题尽量规避更新数据后立即去从库查询刚刚更新的数据。如果一定要查这两个步骤可以放到一个数据库事务中同一个事务中的查询操作也会被路由到主库这样就可以规避主从不一致的问题了还有一种解决方式则是对查询部分单独指定进行主库查询。常规做法是增加了一个支付完成页面这个页面其实没有任何新的有效信息就是告诉你支付成功的信息。如果想再查看一下刚刚支付完成的订单需要手动选择这样就能很好地规避主从同步延迟的问题。6. 如何在代码中实现读写分离和分库分表呢使用像Sharding-JDBC 这些组件集成在应用程序内用于代理应用程序的所有数据库请求并把请 求自动路由到对应的数据库实例上。7. 超过一定时间的历史订单归档的问题这里面涉及到分布式事务的问题。定时迁移——》XXL Job。停止迁移以及恢复迁移的问题。如何防止mysql和mangoDB的数据对不上的问题。迁移前一定会做备份。8. 使用RocketMQ的事务消息优化订单超时取消流程并基于业务做对应的正向、反向通知最后采取定时任务做兜底。二、分布式事务三、全局唯一性ID分库分表之后数据库的自增 ID 已经无法满足需求需要有一个唯一 ID 来标识一条数据或消息。此时一个能够生成全局唯一 ID 的系统是非常必要的。全局唯一性不能出现重复的 ID 号既然是唯一标识这是最基本的要求。趋势递增、单调递增保证下一个 ID 一定大于上一个 ID。无序性可能会引起数据位置频繁变动严重影响性能。信息安全如果 ID 是连续的恶意用户的扒取工作就非常容易做了直接按照顺序下载指定 URL 即可如果是订单号就更危险了竞对可以直接知道我们 一天的单量。所以在一些应用场景下会需要 ID 无规则、不规则。常见方法介绍1. UUID优点 性能非常高本地生成没有网络消耗。缺点不易于存储UUID 太长16 字节 128 位通常以36 长度的字符串表示 很多场景不适用。信息不安全基于 MAC 地址生成 UUID 的算法可能会造成MAC 地址泄露 这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。ID作为主键时在特定的环境会存在一些问题比如做DB主键的场景下UUID 就非常不适用① MySQL官方有明确的建议主键要尽量越短越好[4]36个字符长度的UUID 不符合要求。② 对 MySQL索引不利如果作为数据库主键在 InnoDB 引擎下UUID 的 无序性可能会引起数据位置频繁变动严重影响性能。在 MySQL InnoDB 引擎中使用的是聚集索引由于多数 RDBMS 使用 B-tree 的数据结构来存储索引数据 在主键的选择上面我们应该尽量使用有序的主键保证写入性能。2. 雪花算法及其衍生长度64-bit刚好表示一个long类型的数字。第 0 位 符号位标识正负始终为 0没有用不用管。第 1~41 位 一共 41 位用来表示时间戳单位是毫秒可以支撑 2 ^41 毫秒约 69 年。时间戳就是64-bit如何压缩到42位——》当前时间减去一个时间的起点位第 42~52 位 一共 10 位一般来说前 5 位表示机房 ID后 5 位表 示机器 ID实际项目中可以根据实际情况调整这样就可以区分不同集群/机 房的节点这样就可以表示 32 个 IDC每个 IDC 下可以有 32 台机器。第 53~64 位 一共 12 位用来表示序列号。 序列号为自增值代表单 台机器每毫秒能够产生的最大 ID 数(2^12 4096),也就是说单台机器每毫秒最 多可以生成 4096 个 唯一 ID。优点 毫秒数在高位自增序列在低位整个 ID 都是趋势递增的。 不依赖数据库等第三方系统以服务的方式部署稳定性更高生成 ID 的性能也是非常高的。 可以根据自身业务特性分配 bit 位非常灵活。缺点 强依赖机器时钟如果机器上时钟回拨会导致发号重复或者服务会处于不可用状态。时钟回拨问题——》如果当前时间小于之前的时间就休眠一段时间再去获取。也可以抛异常之后再获取。时间相同则sequence自增。时间往前正常走但是sequence为0在分库分表数据取模会导致数据分布不均如何解决——》加一个震荡方法这样取模会自增让数据分片分表更友好。3. 数据库生成MySQLredis4. 分布式 ID 微服务——》美团 Leaf 方案实现四、分布式Session五、分布式链路跟踪六、日志收集与展示七、商品搜索八、分布式锁九、服务降级/限流/熔断/隔离十、页面静态化十一、分布式任务调度十二、数据迁移方案十三、数据同步方案十四、多级缓存、缓存预热十五、高并发秒杀系统实现秒杀系统的商详页静态化、秒杀系统的隔离、秒杀的削峰和限流等等十六、互联网思维1. 自定义实现MyBatis-Plus逆向工程2. 使用Freemarker模板引擎实现一键开发模式springboot可以结合freemarker根据一个表生成对应的controllerservicedaomapperpojo以及统一的前端界面。3. 结合CBoard报表工具实现拖拽式报表开发