概述
以前在公司里, 有个牛人对俺说:
事务就是个垃圾, 能不用就尽量不用
当时我刚从传统行业切换到互联网行业, 对这个牛人说的这句话是嗤之以鼻的, 怎么可能不用事务呢? 后来随着开发了多个高并发应用后, 才知道这个牛人说的是对的下面说两个亲身经历的案例来说明这个问题
库存扣减接口 (写事务)
当时我们有个业务, 在购物车阶段的时候, 就开始占用库存了, 这个库存占用接口的流量非常大当时我开发完这个接口后, 测试人员的压测结果是
2500/TPS
我觉得低了, 就开始怀疑测试人员是否不够专业, 测试用的服务端应用服务器和数据库是否不给力, 发起请求的压测客户端机器是否给力, jmeter 用的是否正确全部检查完后, 发现测试手法是完全 OK 的
于是仔细的检查代码, 也没发现啥后来灵光一闪, 想起那个牛人说过得的话, 就尝试把事务去掉我们用的是 Spring 的
@Transactional(rollbackFor = Exception.class)
的开启事务的我把这行代码删除掉后, 压测结果是:
3700/QPS
提高了蛮多, 这个压测结果已经能满足线上流量要求了开了事务为啥性能差这么多, 底层原因目前还没仔细去研究但是从压测结果来看, 去掉事务后, 性能有提升
这里部分网友可能有疑问, 如果线程操作的是多张表的写入和更新操作, 如果不用事务的话, 一致性怎么保证? 好问题当时我是使用逻辑回滚的手段来保证数据的一致性, 是需要自己写代码进行数据回滚的因为当时要操作的表只有两张, 代码写起来还好些
如果很多张表的话, 用逻辑回滚就比较麻烦了对于这种很多张表的, 而流量又不是很大那种的话, 还是使用事务方便一些
读接口 (读事务)
当时有个输出商品的接口, 读取逻辑如下:
先从 memcache 读取, 如果没有读取到, 则从 DB 读取
开发完这个接口后, 做压测时, 我先预热一些数据到 memcache 上, 想看看 memcache 的读取性能压测结果不太理想当时找了很久都没找到原因, 后来我用 top 命令观察了一下, 发现只要一压测, 应用还是会跟 mysql 有交互理论上是不会的, 因为数据都在 memcache 上, 一旦命中就走了, 不会去读取数据库
最后面发现原来用了 Spring 的
@Transactional(readOnly = true)
只要你在接口上面加了这个注解, Spring 还是会跟 Mysql 打交道的并发的量一旦大了, 就开始影响性能了
来源: https://blog.csdn.net/linsongbin1/article/details/79684930