在MySQL中当对一行数据进行更新时,通常都要加行锁,直到事务提交或回滚时才释放。同一时段内,对于同一个数据行,只有一个事务能够进行更新,其它事务需要等待。
在电商平台业务中,限购、秒杀是常用的促销手段。在这些场景下,大量对热点行的更新请求在极短时间间隔内到达后台数据库系统,必然造成严重的行锁竞争和等待,影响系统性能。如果一个更新请求等待执行的时间变长,将会对业务层面产生显著负面影响。
写热点解决
热点数据又分为读热点和写热点,通常读热点优化的手段比较多,也容易实现,重点聊聊写热点优化,后面我们讨论热点均表示写热点。
针对热点数据优化,通常会有以下几种解决方案,在实践过程中通常会组合使用这些方案。
MQ+DB方案
这是一种经典的解决方案,所有的操作写写入MQ中,然后异步消费队列中的请求,写入DB中,达到热点优化的效果。
这种方案的缺点主要是:
消费速度不及写入速度,一方面更新DB不及时,消息流延迟较大,另一方面存在消息积压,造成比较严重的长尾效应。
高性能的MQ是以牺牲一致性为代价的,以kafka为例,消息可能存在重复,需要业务端自己去重。
MQ本身是一个复杂的系统,在业务与DB之间增加MQ客观上增加了系统的复杂性。
Redis方案
Redis是一款优秀的内存数据库,单机吞吐可以达到10W TPS,对于小于这个量级的热点数据Redis可以应对,但是如果热点的吞吐超过10W,Redis就没有办法了,同时Redis存在的问题在于它的数据安全性,存在主从之间数据不一致问题,对于很多对数据安全性要求很高的业务场景,使用Redis就不太合适了,比如计费,扣款,库存减扣等场景。
Redis没有事务能力,比如一个item下有多个sku就搞不定了。
客户端聚合方案
客户端聚合也是一种可选的方案,它的核心思路就是在客户端按照一定的时间窗口聚合一定量的请求,比如同时有100个对A字段进行加1的请求,那么就可以合并成一次加100的请求,减少对DB的压力。
这种方案的缺点是客户端数量通常比较多,聚合的窗口太小,合并的请求数量不足,DB的压力仍然很大,如果聚合的窗口太大的话,业务延迟就太高了,也不合适。