背景
之前做了一个钱包账户相关的服务,业务逻辑比较复杂,更新账户余额时,使用的方式是先计算好余额,然后使用乐观锁更新,并发情况下乐观锁更新失败的频率较高。经大佬指点,改成了使用复杂SQL更新余额,也就是在SQL中计算并更新,然后出现了新问题,死锁了。异常如下,然后我就开始了漫漫踩坑之路。。。。。。
Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
死锁解决
也是第一次遇到死锁,然后就先网上查了下情况,都是分析死锁日志,然后避免死锁。我就乖乖的去找DBA捞日志了,然后找到了出问题的SQL,发现每次死锁的SQL不尽相同,第一方案想的是优化SQL的编排顺序,然后避免掉死锁。然而悲催的是,业务逻辑比较复杂,SQL的编排也没啥优化空间。经另一位大佬提点,是说数据库的资源是有限的,不应该把压力放到数据库,所以不应该使用复杂的SQL,所以我又改回了乐观锁,那死锁的问题就解决了。
接口的并发支持
并发下乐观锁失败的频率过高,要解决这个问题,首先想到的就是给接口加锁,将并发改成顺序序列。分布式锁,第一想到的就是Redis(Redis实现分布式锁),然后就这样做了,然后就进入了另一坑,高并发下,获取锁成功的失败频率也不低。但是正常业务场景下,并发率不太高,所以就先这样,后面要研究下高并发下数据写入支持。
思考:要避免掉复杂SQL,业务逻辑要放在应用层,不要给数据库增加不必要的压力。
高并发下数据写入支持【TBC】