Redis 分布式锁实现 高并发抢购的问题

在这里插入图片描述


@Service
public class RedisServiceImpl implements RedisService {
    private Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
    /**
     * redis 配置
     */
    @Value("redis://${redis.host}:${redis.port}")
    private String redisAddress;
    @Value("${redis.password}")
    private String redisPassword;
    @Value("${redis.db}")

    private String redisDb;
    private RedissonClient redisson;

    private Map<String, RBucket> buckets = new HashMap<>(16);

    @PostConstruct
    private void init() {
        Config config = new Config();
        config.useSingleServer().setAddress(redisAddress).setPassword(redisPassword);
        redisson = Redisson.create(config);
        logger.info("Redisson initialized");
    }

    private <T> RBucket<T> getBucket(String key) {
        RBucket bucket = buckets.getOrDefault(key, null);
        if (bucket == null) {
            bucket = redisson.getBucket(key);
            buckets.put(key, bucket);
        }
        return bucket;
    }

    @Override
    public <T> void set(String key, T value) {
        set(key, value, 0, null);
    }

    @Override
    public <T> void set(String key, T value, long l, TimeUnit unit) {
        if (l == 0 || unit == null) {
            getBucket(key).set(value);
        } else {
            getBucket(key).set(value, l, unit);
        }
    }

    @Override
    public <T> T get(String key) {
        return ((RBucket<T>) getBucket(key)).get();
    }

    @Override
    public Lock lock(String lockName) {
        return lock(lockName, 0, null);
    }

    @Override
    public Lock lock(String lockName, long l, TimeUnit unit) {
        RLock rLock = redisson.getLock(lockName);
        if (l == 0 || unit == null) {
            rLock.lock();
            logger.info("locked {}", lockName);
        } else {
            rLock.lock(l, unit);
            logger.info("locked {} {} {}", lockName, l, unit);
        }
        return new LockImpl(logger, rLock);
    }

    public static class LockImpl implements Lock {
        private final Logger logger;
        private final RLock rLock;

        LockImpl(Logger logger, RLock rLock) {
            this.logger = logger;
            this.rLock = rLock;
        }

        @Override
        public void unlock() {
            rLock.unlock();
            logger.info("unlocked {}", rLock.getName());
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Redis 分布式锁确实可以解决高并发下的抢购问题,但是会出现死锁问题。为了解决这个问题,可以采用 Redis 事务机制。 在 Redis 中,事务是指一组命令的集合,这些命令将按顺序被执行,但在执行期间不会被其他客户端的命令所打断。在事务中,所有的命令都会被放入一个队列中,等待 EXEC 命令的执行。如果在队列中的命令执行过程中出现了错误,那么所有的命令都将被取消。 下面是一个使用 Redis 事务机制来解决抢购死锁问题的 Java 代码示例: ``` // 获取 Redis 分布式锁 boolean locked = redisClient.tryLock("product:123", "user:456", 10, TimeUnit.SECONDS); // 如果获取锁成功,执行下单逻辑 if (locked) { try { redisClient.multi(); // 开始 Redis 事务 // 执行下单逻辑 boolean success = placeOrder(productId, userId); if (success) { redisClient.exec(); // 提交 Redis 事务 } else { redisClient.discard(); // 回滚 Redis 事务 } } finally { redisClient.unlock("product:123", "user:456"); // 释放 Redis 分布式锁 } } ``` 在上面的代码中,我们首先获取 Redis 分布式锁,如果获取成功,则开启 Redis 事务,执行下单逻辑,在下单逻辑执行完成后,根据下单结果决定是提交事务还是回滚事务。最后,释放 Redis 分布式锁。 需要注意的是,Redis 事务机制并不能完全解决死锁问题,因为在执行事务期间,其他客户端的命令仍然可以被执行,如果在事务期间出现了异常情况,那么可能会造成其他客户端的命令与当前事务产生竞争,从而导致死锁问题。因此,在实际应用中,还需要结合其他技术手段来进一步优化解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值