高并发场景库存同步设计:Redis故障降级与双轨补偿实践

// ... 原有package和import...
import com.google.common.cache.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Service
public class ActivityArmory implements IActivityArmory, IActivityDispatch {
    
    // 新增补偿队列(线程安全)
    private final BlockingQueue<StockCompensation> compensationQueue = new LinkedBlockingQueue<>(10000);
    
    // 本地缓存配置(5秒过期,最大缓存10000个SKU)
    private Cache<Long, AtomicInteger> localStockCache = CacheBuilder.newBuilder()
        .expireAfterWrite(5, TimeUnit.SECONDS)
        .maximumSize(10000)
        .removalListener(notification -> {
            if (notification.getKey() != null) {
                int finalStock = notification.getValue().get();
                compensationQueue.offer(new StockCompensation(
                    (Long) notification.getKey(), 
                    finalStock
                ));
            }
        })
        .build();

    // 初始化补偿任务
    @PostConstruct
    private void initCompensationTask() {
        Executors.newSingleThreadScheduledExecutor()
            .scheduleAtFixedRate(this::processCompensation, 1, 1, TimeUnit.SECONDS);
    }

    // 库存扣减方法改造
    @Override
    public boolean subtractionActivitySkuStock(Long sku, Date endDateTime) {
        String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + sku;
        
        try {
            // 优先尝试Redis扣减
            boolean redisResult = activityRepository.subtractionActivitySkuStock(sku, cacheKey, endDateTime);
            if (redisResult) return true;
        } catch (Exception e) {
            log.warn("Redis操作异常,降级本地处理", e);
        }
        
        // 本地安全扣减
        return safeLocalDecrement(sku, cacheKey);
    }

    // 带补偿的安全扣减
    private boolean safeLocalDecrement(Long sku, String cacheKey) {
        try {
            AtomicInteger stock = localStockCache.get(sku, () -> 
                new AtomicInteger(getRedisStock(cacheKey)));
            
            int current = stock.decrementAndGet();
            if (current >= 0) {
                compensationQueue.offer(new StockCompensation(sku, -1));
                return true;
            }
            stock.incrementAndGet(); // 回滚超扣库存
            return false;
        } catch (Exception e) {
            log.error("本地降级模式异常", e);
            return false;
        }
    }

    // 补偿处理逻辑
    private void processCompensation() {
        while (!compensationQueue.isEmpty()) {
            StockCompensation comp = compensationQueue.poll();
            try {
                String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_COUNT_KEY + comp.sku;
                if (comp.delta < 0) {
                    // 扣减补偿(原子操作)
                    redisTemplate.opsForValue().decrement(cacheKey, -comp.delta);
                } else {
                    // 最终值补偿(覆盖更新)
                    redisTemplate.opsForValue().set(cacheKey, comp.delta);
                }
            } catch (Exception e) {
                log.error("库存补偿失败,重新入队", e);
                compensationQueue.offer(comp);
            }
        }
    }

    // 补偿数据载体
    private static class StockCompensation {
        final Long sku;
        final Integer delta;
        // 构造方法省略...
    }
    
    // ... 其他原有方法保持不变 ...
}

实现方案说明 :

1. 双轨库存机制:Redis主存储 + 本地缓存降级
2. 最终一致性保障:通过补偿队列实现异步同步
3. 异常处理:Redis不可用时自动降级,恢复后自动补偿
4. 线程安全:采用线程安全队列和原子操作类
5. 性能优化:本地缓存5秒过期,补偿任务1秒执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@淡 定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值