数据库
mysql性能评测
处理速率跟cpu、磁盘io有关、宽带有关(如果业务和数据库在同一台服务器,也就减少了宽带传输所占用的部分时间)
一核一G 一个线程单次插入:
mysql 服务插入1万条数据需要157378ms==>157秒 两分37秒
两个线程1万数据:82295ms==》1分23秒
四个线程2万数据:78354ms==》1分18秒
八个线程4万数据:120944ms==》两分钟
12个线程6万数据:94474ms==》1分34秒
12个线程6万数据:98902ms==》1分38秒
阿里云服务
12个线程6万数据:33203ms==》33秒
12个线程6万数据:27228ms==》27秒
查询优化:
查询优化:将数据库与项目放在同一台服务器可以减少数据传输所消耗的时间,在数据量比较的大的情况下,效果明显
缓存
读写分离(主从架构、主备架构)
数据库读写分离的优点:https://www.cnblogs.com/xyfds/articles/8659170.html
数据库读写分离这个坑:https://www.cnblogs.com/goodAndyxublog/archive/2020/12/09/14106692.html
分库分表:https://www.cnblogs.com/butterfly100/p/9034281.html
1.优点与缺点(解决的问题以及带来的问题)
2.分库分表原则
分表
1.分表原则
2.读写分表
分库:根据业务分库,如订单、商品、活动等等
1.分库原则
工具:sharding-jdbc
实例:springboot+mybatis+sharding-jdbc整合分库分表实战:https://blog.csdn.net/dhj199181/article/details/108073182
分库->分布式事务
分布式事务(通关篇):https://zhuanlan.zhihu.com/p/437577902
常用的分布式事务解决方案有哪些?:https://www.zhihu.com/question/64921387/answer/225784480
微服务分布式事务4种解决方案实战:https://zhuanlan.zhihu.com/p/100279671
分布式事务TCC模式的空回滚和业务悬挂问题:https://cloud.tencent.com/developer/article/2048776
如何解决TCC中悬挂问题?
悬挂就是对于一个分布式事务,其二阶段Cancel接口比Try接口先执行。
出现原因是在调用分支事务Try时,由于网络发生拥堵,造成了超时,TM就会通知RM回滚该分布式事务,可能回滚完成后,Try请求才到达参与者真正执行,而一个Try方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预留的业务资源就再也没有人能够处理了,对于这种情况,我们就称为悬挂,即业务资源预留后无法继续处理。
解决思路是如果二阶段执行完成,那一阶段就不能再继续执行。在执行一阶段事务时判断在该全局事务下,判断分支事务记录表中是否已经有二阶段事务记录,如果有则不执行Try。
实例:TCC 强一致性 实时 DEMO 下单(创建订单,扣除库存,增加积分,扣除余额) https://blog.csdn.net/oQiuQian/article/details/78023560
seat支持at事务模式、tcc事务模式、sage事务模式、xa事务模式
seata示例:http://seata.io/zh-cn/docs/user/quickstart.html
注意:seata不支持mysql.8.x (新版已支持)
sql限制
http://seata.io/zh-cn/docs/user/sqlreference/sql-restrictions.html
不支持 SQL 嵌套
不支持多表复杂 SQL
不支持存储过程、触发器
部分数据库不支持批量更新,在使用 MySQL、Mariadb、PostgreSQL9.6+作为数据库时支持批量,批量更新方式如下以 Java 为例
示例:
一.微服务,但不涉及第三方接口:如下单扣款扣商品库存,采用tcc事务模式
用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:
仓储服务:对给定的商品扣除仓储数量。
订单服务:根据采购需求创建订单。
帐户服务:从用户帐户中扣除余额。
需求:都成功或者都失败
触发:用户点击下单
下发一个orderCode,用于去重
本地:
本地业务服务同步检查(调用远程服务是否可以扣除库存ifReduceStock(orderCode,reduceNumber), 远程服务是否可以扣除余额ifReduceBalance(orderCode,sum),其他)
调用远程服务是否可以扣除库存ifReduceStock(orderCode,reduceNumber)说明:
首先,要调用补充服务把日志中超过timeOut时间的记录状态设置为失效Cancel。
其次,要把日志状态为锁住Try库存从剩余库存剪掉
Try
同步调用远程服务Try
1.锁库存 lock(String orderCode, String commodityCode, int count); 这里也校验了库存
数据记录:远程添加此次扣除日志(三种方式:数据库,Redis,MongoDB),其他判断是否可以扣除库存务必减去这个库存数量(从扣除日志找orderCode相同,状态为锁住Try的操作库存数)
数据记录主要字段,值:
orderCode(用于去重)
原库存,值1000
此次操作库存,值1
操作时间(一个用途,用于计算超过某个值timeOut后,把此条记录状态设置为失效Cancel)
状态(锁住Try,确认Confirm,失效Cancel),值锁住Try
2.锁余额 lock(String orderCode, String userId, int money); 这里也校验了余额
数据记录:具体同库存
3.下单 空处理即可
4.exception Cancel
Confirm
同步调用远程服务Confirm
1.减库存 void deduct(String orderCode, String commodityCode, int count);、 并 释放库存锁(删除记录)
2.扣余额 void debit(String orderCode, String userId, int money);、并释放余额锁(删除记录)
3.下单 orderService.create(userId, commodityCode, orderCount);
orderDAO.insert(order);
Cancel
1.取消占有资源:库存
2.取消占有资源:余额
回滚本地事务,结束
return 下单失败;
细节:
1.如何锁资源? 删除表对应资源记录
2.秒杀活动等高并发怎么办?秒杀情况下,应在下单前的购买和加入购物车操作做限制。添加一个队列,队列中请求已把库存买光,就不允许进入队列走下单。只有进入队列的才可以下单。使用Redis实现。
注意点:
1.TM首先发起所有的分支事务Try操作,任何一个分支事务的Try操作执行失败,TM将会发起所有分支事务的Cancel操作,若Try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中Confirm/Cancel操作若执行失败,TM会进行重试。
2.幂等处理 Confirm/Cancel,因为Confirm/Cancel失败,会重试,直到成功
3.空回滚:一些分支事务还未开始执行try,就收到Cancel命令
解决:每个分支事务在try成功后,branch_table新增一条记录。在进行Cancel时,先查询是否有记录,有则回滚;否则不
4.资源悬挂
解决:在进行Cancel后,branch_table新增一条记录。如果要进行try,先查询是否有记录,有则不try
总结:每个分支事务在开始前都在branch_table新增一条记录,并用status记录当前事务的状态:init/try/confirm/cancel,在成功或者回滚后删除
二.涉及第三方接口:钱包充值,采用sage事务模式:正向模式、反向模式
1.支付宝、微信扣除资金
2.应用钱包余额新增
普通模式:直接调第三方接口扣款,判断是否成功,成功直接新增余额,否则失败
因为只涉及一个第三方接口,不需要用到分布式事务
代购物网站:1.本地下单;2.远程下单;3.微服务扣款
只能使用反向模式:只要2、3一者失败就直接失败,进行反向补偿
实战:
1.在事务中的其他事务怎么解决锁超时,在哪些场景下遇到了?
首先这个不属于分布式事务。
在oauth2系统更新用户节点,在iiot系统给用户生成证书时,发生了锁等待超时,原因用户系统修改用户节点,而标识系统修改用户企信码,锁了同一条记录,互相等待超时。
解决方案:标识系统不修改企信码,而是直接返回给用户系统,让用户系统同时修改。
数据库优化
于 2023-02-14 15:52:33 首次发布