在上两讲里分别介绍了使用数据库和纯缓存实现的扣减方案。在需求层面上,上述两者都能实现业务需求。但均存在一些缺陷:
-
数据库方案的性能较差;
-
纯缓存方案虽不会导致超卖,但因缓存不具备事务特性,极端情况下会存在缓存里的数据无法回滚,导致出现少卖的情况。且因“第 13 讲”是异步写库,也可能发生异步写库失败,导致多扣的数据再也无法找回的情况。
因此,本讲将向你介绍一种新的实现方案——使用数据库+缓存的方式规避上述存在的潜在问题。
顺序写的性能更好
本讲的方案是借助了“顺序写要比随机更新性能好”这个特性进行设计的。
在向磁盘进行数据操作时,向文件末尾不断追加写入的性能要远大于随机修改的性能。因为对于传统的机械硬盘来说,每一次的随机更新都需要机械键盘的磁头在硬盘的盘面上进行寻址,再去更新目标数据,这种方式十分消耗性能。而向文件末尾追加写入,每一次的写入只需要磁头一次寻址,将磁头定位到文件末尾即可,后续的顺序写入不断追加即可。
对于固态硬盘来说,虽然避免了磁头移动,但依然存在一定的寻址过程。此外,对文件内容的随机更新和数据库的表更新比较类似,都存在加锁带来的性能消耗。
数据库同样是插入要比更新的性能好。对于数据库的更新,为了保证对同一条数据并发更新的一致性,会在更新时增加锁,但加锁是十分消耗性能的。此外,对于没有索引的更新条件,要想找到需要更新的那条数据,需要遍历整张表,时间复杂度为 O(N)。而插入只在末尾进行追加,性能非常好。
借力顺序写的架构
有了上述的理论基础后,只要对上一讲的架构稍做变更,就可以得到兼具性能和高可靠的扣减架