想象一下,如果你现在刚好在 word 上写需求文档,电脑突然重启。等待开机完成,你可能会发现写了一个小时文档没有保存,就这么没了。。。 一个正在运行 Java 应用如果突然将其停止,影响不止数据丢失,还会造成其他影响。比如: 请求丢失:内存队列中等待执行请求丢失 数据丢失:处于内存缓存中数据未持久化到磁盘 文件损坏:正在写的文件没有没有更新完成,导致文件损坏 业务中断:处理一半的业务被强行中断,如支付成功了,却没有更新到数据库中 服务未下线:上游服务依然往停止节点发送请求 所以在关闭服务之前,我们需要先做好善后工作,比如保存数据,清理资源,下线服务,然后才退出应用。这种有计划平滑的关闭应用相对直接停止应用,就显得非常『优雅』。 ps: 仔细品味,优雅停机这个词真好~ ShutdownHook Java 语言提供一种 ShutdownHook(钩子)进制,当 JVM 接受到系统的关闭通知之后,调用 ShutdownHook 内的方法,用以完成清理操作,从而平滑的退出应用。 ShutdownHook代码如下: Runtime.getRuntime().addShutdownHoo.... 有更新! ShutdownHook- Java 优雅停机解决方案 Java
背景 现有一个交易系统,每次交易都会更新余额。出账扣减余额,入账增加余额。为了保证资金安全,余额发生扣减时,需要比较现有余额与扣减金额大小,若扣减金额大于现有余额,扣减余额不足,扣减失败。 余额表(省去其他字段)结构如下: CREATE TABLE `account` ( `id` bigint(20) NOT NULL, `balance` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_bin; 更新余额方法语序如下: 由于存在并发更新余额的情况,在 t3 时刻,使用写锁锁住该行记录。这样就能保证事务执行期间不会有其他事务提交变更。 现在我们假设有两个事务正在发执行该语序,执行顺序如图所示。 假设 id=1 记录 balance=1000,事务隔离等级为 RR。小伙伴们可以根据这个执行时序可以先思考下 t3,t5,t6,t7 结果。 注: 以上时序,顺序执行。但是事务 1 执行到 t3 时刻,t4 时刻,事务 .... 有更新! 锁住余额,为何还会更新异常? mysql