【工具类】RedisUtil 操作相关

发布于:2025-02-11 ⋅ 阅读:(70) ⋅ 点赞:(0)

目标

一行代码调用

安装

redis

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

配置

spring:
  data:
    redis:
      host: xxx
      port: 6379
      password: xxx
      database: x

工具类

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

/**
 * Redis 操作工具类
 *
 * @author jason
 */
@Slf4j
@Component
public class RedisUtil {
    private static RedisUtil instance;

    @PostConstruct
    private void init() {
        instance = this;
    }

    private static RedisUtil getInstance() {
        return instance;
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * set
     */
    public static void set(String key, Object value) {
        getInstance().stringRedisTemplate.opsForValue().set(key, StrUtil.toStringOrNull(value));
    }

    /**
     * get
     */
    public static String get(String key) {
        return getInstance().stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * decr 扣减
     */
    public static Long decrement(String key) {
        return getInstance().stringRedisTemplate.opsForValue().decrement(key);
    }

    /**
     * incr 增加
     */
    public static Long increment(String key) {
        return getInstance().stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * 无锁:decr 扣减 + incr 回滚
     */
    public static boolean decrementCouponId(String couponId) {
        // 库存 - 1
        Long decrementNum = RedisUtil.decrement(couponId);
        log.info("优惠券扣减后库存:{}", decrementNum);

        // 库存 + 1
        if (decrementNum < 0) {
            Long incrementNum = RedisUtil.increment(couponId);
            log.info("优惠券回滚后库存:{}", incrementNum);
            return false;
        }
        return true;
    }

    /**
     * 无锁:lua + decr 扣减
     */
    public static Boolean luaDecrCid(String couponId) {
        // Lua 脚本
        String script = """
                local couponId = KEYS[1]
                local value = tonumber(redis.call('GET', couponId))

                if value > 0 then
                    redis.call('DECR', couponId)
                    return true
                else
                    return false
                end
                """;
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);
        return getInstance().stringRedisTemplate.execute(redisScript, CollectionUtil.newArrayList(couponId));
    }

    /**
     * 无锁:lua + decr 扣减
     * <p>
     * 限制:1个用户,1张券
     */
    public static Boolean luaUserCid(String userId, String couponId) {
        // Lua 脚本
        String script = """
                local userId = KEYS[1]
                local couponId = KEYS[2]
                local isUserSuccess = redis.call('GET', userId)
                local value = tonumber(redis.call('GET', couponId))

                if isUserSuccess ~= "true" and value > 0 then
                    redis.call('DECR', couponId)
                    redis.call('SET', userId, "true")
                    return true
                else
                    return false
                end
                """;
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);
        return getInstance().stringRedisTemplate.execute(redisScript, CollectionUtil.newArrayList(userId, couponId));
    }

}


网站公告

今日签到

点亮在社区的每一天
去签到