redis锁定商品解决并发售卖问题 RedisUtil工具类 redis数据类型
redis锁定商品解决并发售卖问题 RedisUtil工具类
redis数据类型介绍:
//伪代码,基本思路
//1.出redis,每次在选定商品之后,先检查redis是否已经锁定该商品,避免超卖。
Set<String> cacheList = redisUtilService.getSetValue(redisMapKey);
if(CollectionUtils.isNotEmpty(cacheList)) {
//判断商品等属性,比如租期是否已经重叠等,商品是否已经锁定卖出等,避免重复售卖。
}
//2.入redis,售卖成功,增加到redis中
redisUtilService.setSetValue(redisMapKey, redisMapValueStr);
redisUtilService.expireMinute(redisMapKey, RENTER_TIME_OVERLAPPING_REDIS_EXPIRE_MINUTE);
//RedisUtilService.java工具类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ZSetOperations.TypedTuple; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @Service public class RedisUtilService { @Autowired private StringRedisTemplate redis; /** * 从redis缓存中取值 * @param key * @return */ public String getValue(String key) { return redis.opsForValue().get(key); } /** * 往redis缓存存zset值 * @param key * @param customerId * @param inviterCounts */ public void setZsetValue(String key,String customerId,double inviterCounts){ redis.opsForZSet().add(key, customerId, inviterCounts); } /** * Set无序集合赋值 * @param key * @param customerId */ public void setSetValue(String key,String customerId){ redis.opsForSet().add(key, customerId); } /** * Set无序集合获取 * @param key * @return */ public Set<String> getSetValue(String key){ return redis.opsForSet().members(key); } /** * 倒序根据score下标取zset值 * @param key * @param start * @param end * @return */ public Set<TypedTuple<String>> getZsetValue(String key,long start, long end ){ return redis.opsForZSet().reverseRangeWithScores(key, start, end); } /** * 获取value对应的socre * @param key * @param o * @return */ public Double getZsetScore(String key,Object o){ return redis.opsForZSet().score(key, o); } /** * 获取value对应的排名(倒序) * @param key * @param o * @return */ public Long getZsetRank(String key,Object o){ return redis.opsForZSet().reverseRank(key, o); } /** 获取redis元素数量 * @param key * @return */ public Long getZsetLength(String key){ return redis.opsForZSet().size(key); } /** * 有时间期限的往缓存中设值 * @param key * @param value * @param second */ public void setValue(String key, String value, Long second) { redis.opsForValue().set(key, value, second, TimeUnit.SECONDS); } /** * 有时间期限的往缓存中设值 * @param key * @param value * @param day */ public void setValueWithDayTTL(String key, String value, Long day) { redis.opsForValue().set(key, value, day, TimeUnit.DAYS); } /** * 删除制定key值得缓存 * @param key */ public void removeKey(String key) { redis.delete(key); } public void setObjectValue(String key,Object obj){ redis.opsForValue().set(key, GsonUtils.toJson(obj)); } public void setObjectValue(String key,Object obj,Long second){ redis.opsForValue().set(key, GsonUtils.toJson(obj),second,TimeUnit.SECONDS); } /** * 入队(可用作消息队列) * @param key * @param value * @return */ public Long in(String key, String value) { return redis.opsForList().rightPush(key, value); } /** * 出队 (可用作消息队列) * @param key * @return */ public String out(String key) { return redis.opsForList().leftPop(key); } /** * 队列长 * @param key * @return */ public Long length(String key) { return redis.opsForList().size(key); } /** * 对指定key值 +1,key不存在,默认返回1 * * @Title: increaseByOne * @Description:对指定key值 +1 * @param key * @return Long 返回类型 * @throws */ public Long incrementOne(String key){ return redis.opsForValue().increment(key, 1L); } /** * 对指定key值 +1,key不存在,默认返回1 * * @Title: increaseByOne * @Description:对指定key值 +1 * @param key * @return Long 返回类型 * @throws */ public Long decrementOne(String key){ return redis.opsForValue().increment(key, -1L); } /** * 对指定key值加减计算 ,key不存在,默认返回1 * * @Title: increaseByNum * @Description:对指定key值加减计算 * @param key * @return Long 返回类型 * @throws */ public Long incrementByNum(String key,Long nums){ return redis.opsForValue().increment(key, nums); } /** * 按指定的key进行上锁,true-加锁成功(名字为key的锁,并设置超时),false-加锁失败(表明已存在对应key的锁,加锁失败应停止后续业务操作) * * @Title: setIfAbsent * @Description: 设定指定key的值,若key值已经存在,设置不成功并返回false,key不存在,设置成功,返回true * @param key * @param second 过期时间 * @return Boolean true-加锁成功(名字为key的锁,并设置超时),false-加锁失败(表明已存在对应key的锁) * @throws */ public Boolean checkAndSetLock(String key,long second){ String lockValue = "Lock"; boolean res = redis.opsForValue().setIfAbsent(key,lockValue); if(res){ redis.opsForValue().set(key,lockValue,second,TimeUnit.SECONDS); } return res; } public void deleteLock(String key){ redis.delete(key); } public Long getExpire(String key) { return redis.getExpire(key, TimeUnit.SECONDS); } public boolean expire(String key,long second) { return redis.expire(key, second, TimeUnit.SECONDS); } public boolean expireDay(String key,long day) { return redis.expire(key, day, TimeUnit.DAYS); } public boolean expireMinute(String key,long minute) { return redis.expire(key, minute, TimeUnit.MINUTES); } public void setValueHash(String key,String hashKey,String value) { redis.opsForHash().put(key, hashKey, value); } public List<String> getValuesHash(String key) { HashOperations<String, String, String> hashOperations = redis.opsForHash(); List<String> values = hashOperations.values(key); return values; } public void deleteHashKey(String key,String ...hashKeys){ redis.opsForHash().delete(key, hashKeys); } public void deleteSetKey(String key){ redis.opsForSet().remove(key); } }