目标
一行代码调用
安装
redis
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
hutool 工具类
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency>
配置
spring:data:redis:host: xxxport: 6379password: xxxdatabase: x
配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** 方便获取 Spring IOC 实例** @author jason*/
@Configuration
@Import(cn.hutool.extra.spring.SpringUtil.class)
public class BeanConf {
}
工具类
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
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 {@Autowiredprivate StringRedisTemplate stringRedisTemplate;public static RedisUtil instance() {return SpringUtil.getBean(RedisUtil.class);}/*** set*/public static void set(String key, Object value) {instance().stringRedisTemplate.opsForValue().set(key, StrUtil.toStringOrNull(value));}/*** get*/public static String get(String key) {return instance().stringRedisTemplate.opsForValue().get(key);}/*** decr 扣减*/public static Long decrement(String key) {return instance().stringRedisTemplate.opsForValue().decrement(key);}/*** incr 增加*/public static Long increment(String key) {return instance().stringRedisTemplate.opsForValue().increment(key);}/*** 无锁:decr 扣减 + incr 回滚*/public static boolean decrementCouponId(String couponId) {// 库存 - 1Long decrementNum = RedisUtil.decrement(couponId);log.info("优惠券扣减后库存:{}", decrementNum);// 库存 + 1if (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 thenredis.call('DECR', couponId)return trueelsereturn falseend""";DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);return instance().stringRedisTemplate.execute(redisScript, CollectionUtil.newArrayList(couponId));}/*** 无锁:lua + decr 扣减** 限制: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 thenredis.call('DECR', couponId)redis.call('SET', userId, "true")return trueelsereturn falseend""";DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);return instance().stringRedisTemplate.execute(redisScript, CollectionUtil.newArrayList(userId, couponId));}}