巧解Redis主从切换引发的库存同步地狱

举报
赵KK日常技术记录 发表于 2023/09/22 23:28:23 2023/09/22
【摘要】 一、问题复现​我们知道,Redis主从复制可以实现读写分离,通过使从节点提供读取服务,来分担主节点的读取压力。但是主从切换时,可能会导致严重的库存同步问题。以下用Java代码模拟一个商品售卖的场景,看看主从切换会引发什么问题:java// 初始化商品库存数量int inventory = 10;// 主节点代码public void sellItemOnMaster(){inventory...

一、问题复现

我们知道,Redis主从复制可以实现读写分离,通过使从节点提供读取服务,来分担主节点的读取压力。但是主从切换时,可能会导致严重的库存同步问题。

以下用Java代码模拟一个商品售卖的场景,看看主从切换会引发什么问题:

java

// 初始化商品库存数量

int inventory = 10;

// 主节点代码

public void sellItemOnMaster(){

inventory–;

System.out.println(“主节点卖出库存,剩余:”+inventory);

}

// 从节点代码

public void sellItemOnSlave(){

// 从节点读取主节点的inventory值

int inventory = getInventoryFromMaster();

inventory–;

System.out.println(“从节点卖出库存,剩余:”+inventory);

}

假设主从节点间复制是异步的,如果在主节点处理请求“sellItemOnMaster”后,还没来得及同步到从节点,此时从节点也处理了“sellItemOnSlave”的请求,读取到的库存仍是10,那么从节点执行结束后,实际的库存数量会变成8,小于记录的9,出现超卖情况。

二、问题原因

引发这个问题的原因在于:

1. 主从节点的数据存在同步延迟

Redis的主从复制是异步的,主节点写入新数据后,需要一定的时间同步到从节点,这段时间内,从节点的数据是旧的。

2. 从节点可以处理写请求

默认情况下,Redis的从节点同时处理读写请求,这当主从数据不同步时,可能导致从节点的处理逻辑错误。

3. 缺乏必要的业务校验逻辑

从节点在处理写请求时,没有考虑主从数据可能存在时间窗口,直接使用了主节点旧数据,导致逻辑错误。

三、解决方案

知道了引发问题的原因,我们来看看解决方案:

1. 尽量减少主从延迟

可以适当减小主节点写入批量大小,加快主从同步频率,缩小主从数据同步的时间窗口。

2. 使从节点只读

设置Redis从节点为只读模式,不处理写命令,可以避免直接在从节点写数据带来的问题。

3. 加入业务层校验机制

在从节点处理读请求时,加入必要的业务校验,例如再次检查库存数量,避免直接使用存在时差的旧数据。

4. 主从切换后重建索引

主从切换后,可以重建索引,保证主从数据强一致性。

5. 队列承接强一致性写入

使用消息队列来承接需要强一致性的写入操作,顺序写入主从节点,确保数据一致性。

以上这些方法各有优劣,可以根据实际业务需求进行选用。我们来看一个改进后的代码示例:

// 初始化库存数量
int inventory = 10;// 主节点代码
public void sellItemOnMaster(){
  // 从Redis主节点减库存
  decreaseInventoryInRedisMaster();
  // 将减库存请求发送到消息队列
  sendDecreaseInventoryMsgToMQ(productId);
}
// 从节点代码
public void sellItemOnSlave(){
  // 从Redis从节点读取库存
  int inventory = getInventoryFromRedisSlave();
  // 校验库存数量
  if(inventory > 0){
    // 售卖商品逻辑 
    System.out.println("从节点卖出商品");
  }else{
    // 没有库存,返回售罄
    System.out.println("商品售罄");
  }
}
// 消息队列消费端代码
public void handleDecreaseInventoryMsg(Message msg){
   // 从消息队列中获取商品减库存请求
   String productId = msg.getProductId();
   // 在从节点减库存
   decreaseInventoryInRedisSlave(productId); 
}

通过消息队列顺序写入Redis主从,并加上必要的业务校验,可以避免库存数量的错误。

四、小结

通过对Redis主从切换问题的剖析,我们可以得出以下结论:

  1. 明确问题根源,才能有针对性地解决问题。
  2. 采取技术手段缩小主从延迟,是治标不治本。
  3. 从业务层面设计如“不在从节点写数据”、“多层校验”等机制,才是根本解决之道。
  4. 综合运用多种手段,才能构建一个稳定可靠的分布式系统。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。