# 简单介绍一下解决数据库热点行更新问题的五种思路

热点行更新问题:频繁对某一行数据进行更新操作,出现资源竞争导致性能急剧下降。在电商系统中,开发库存、限购模块都会遇到的经典问题。

简单介绍一下几种常见的解决办法:

# 1.使用乐观锁、判断当前库存的思想

update stock 
set n_available = n_available - #{delta} 
where id = #{id} and version = #{expectVersion};

update stock 
set n_available = n_available - #{delta} 
where id = #{id} and n_available >= #{delta};

还是会占用行锁,大多数情况下占用行锁时间比悲观锁的写法短,但有可能更新失败,需要回滚、重试事务之类的操作。不适用于回滚、重试成本高的场景。

# 2.以Redis等NO-SQL数据库的数据为准,定时同步进数据库。

缺点:牺牲了一定的一致性,Redis挂了、主从切换可能会丢掉一部分数据。

如果之前没有redis的lua脚本开发经验,可能调试时间会占用比较久。

# 3.数据拆分,分散更新压力。

缺点:实现较复杂。存在库存碎片问题,库存在多行数据中调控不方便。

# 4.请求合并,减少更新频率。

  1. 判断商品库存更新频率大于阈值(如200ms内3次更新),则开启请求合并模式。
  2. 把扣减任务放到队列,当队列内任务个数超过10个或者首个任务提交时间超过200ms时,则另起一个线程,处理库存流水insert和库存update。注意先insert库存流水后update库存,减少库存行锁持有时间。
  3. 处理结果响应给请求线程,进行后续处理。

缺点:

实现比较复杂。除正常扣除逻辑外,还需要处理库存不足以扣除时间窗口内的扣除请求的逻辑,一般的逻辑是先满足扣除下单数量大的请求,再尝试满足下单数量少的。

最坏情况下,扣库存的耗时超过设置的时间窗口的时长。

# 5.开启云数据库的热点行优化参数。

Polar db:https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/hot-row-optimization

腾讯云TX SQL: https://cloud.tencent.com/document/product/236/63239

优点:非常简单。

缺点:非所有数据库产品都通用。

推荐使用云数据库,云数据库除了此项特性外,还有数据分片、监控、主从、sql洞察等开箱即用的非常实用的功能。