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工具类
代码语言:javascript复制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);
}
}