Redis 工具封装类

   以下工具代码,比较适用于抢单,或者提现,比如校验此人当天的提现次数,用于并发场景等等。

 pom.xml添加依赖 

  <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>2.1.5.RELEASE</version>
            </dependency>

 

   父类如下 : 

/**
 * @author : ws
 * @date Date :  
 */
public interface IExpiredCounter {

    //
    Long increase(String bizCode,String key, Long unit, Date expiredTime);

    //redis increase 判断此刻是否达到某个key的最大值
    Boolean hasIncreaseGreaterThanMaxValue(String bizCode,String key, Long unit, Date expiredTime,Long maxValue);

    //redis increase 判断此刻是否达到某个key的最大值 expiredTime自动失效时间
    Boolean hasIncreaseGreaterThanMaxValue(String bizCode,String key,  Date expiredTime, Long maxValue);
     
    //获取redis内 某个key 当前的单数
    Long getCountValue(String bizCode,String key);
       
    //带失效时间的increase
    Long increaseBySeconds(String key,  Integer senconds);

    // --
    Long decr(String key, Integer startNumber);

    // --
    Long decrByCommon(String bizCode,String key, Integer startNumber);

}

 实现类:

 
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

 
@Service
@Slf4j
public class RedisExpiredCounter implements IExpiredCounter {

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${spring.redis.keyspace}")
    private String keySpace;


    private String counterPoolKeyFormat = ":counterpool:{0}:{1}";

    private String doubleTwelveFormat = ":DOUBLE_TWELVE:{0}";

    @PostConstruct
    public void postConstruct() {
        counterPoolKeyFormat = keySpace + counterPoolKeyFormat;
        doubleTwelveFormat = keySpace + doubleTwelveFormat;
    }
    @Override
    public Long increase(String bizCode,String key, Long unit, Date expiredTime) {
        Date date = new Date();
        String finalKey = MessageFormat.format(counterPoolKeyFormat,bizCode,key);
        BusinessException.check(date.compareTo(expiredTime) <=0,"过期时间不能小于当前时间");
        Long result = redisTemplate.opsForValue().increment(finalKey,unit);

        if(redisTemplate.getExpire(finalKey) < 0) {
            redisTemplate.expireAt(finalKey, expiredTime);
        }

        return result;
    }

    @Override
    public Long getCountValue(String bizCode,String key) {
        String finalKey = MessageFormat.format(counterPoolKeyFormat,bizCode,key);
        //Object resultObj = redisTemplate.opsForValue().get(finalKey);
        Object resultObj = getIncrValue(finalKey);
        Long result = 0L;
        if (resultObj != null && !Strings.isNullOrEmpty(resultObj.toString())) {
             result = Long.valueOf(resultObj.toString());
        }
        return result;
    }

    @Override
    public Long increaseBySeconds(String key,   Integer senconds) {
        String finalKey = MessageFormat.format(doubleTwelveFormat,key); 
        BoundValueOperations<String, String> stringStringBoundValueOperations = redisTemplate.boundValueOps(finalKey);
        Long result = stringStringBoundValueOperations.increment();
        stringStringBoundValueOperations.expire(senconds, TimeUnit.SECONDS);
        return result;
    }

    @Override
    public Long decr(String key, Integer startNumber) {
        String finalKey = MessageFormat.format(doubleTwelveFormat,key);
        BoundValueOperations<String, String> stringStringBoundValueOperations = redisTemplate.boundValueOps(finalKey);
        Long result = stringStringBoundValueOperations.decrement(startNumber);
        return result;
    }

    @Override
    public Long decrByCommon(String bizCode,String key, Integer num) {
        String finalKey = MessageFormat.format(counterPoolKeyFormat,bizCode,key);
        BoundValueOperations<String, String> stringStringBoundValueOperations = redisTemplate.boundValueOps(finalKey);
        Long result = stringStringBoundValueOperations.decrement(num);
        return result;
    }


    public Object getIncrValue(final String key) {

        return redisTemplate.execute((RedisCallback<Long>) connection -> {
            RedisSerializer<String> serializer=redisTemplate.getStringSerializer();
            byte[] rowkey=serializer.serialize(key);
            byte[] rowval=connection.get(rowkey);
            try {
                String val=serializer.deserialize(rowval);
                return Long.parseLong(val);
            } catch (Exception e) {
                return 0L;
            }
        });
    }

    @Override
    public Boolean hasIncreaseGreaterThanMaxValue(String bizCode,String key, Long unit, Date expiredTime, Long maxValue) {
        return increase(bizCode,key,unit,expiredTime).compareTo(maxValue) > 0;
    }

    @Override
    public Boolean hasIncreaseGreaterThanMaxValue(String bizCode,String key,  Date expiredTime, Long maxValue) {
        return hasIncreaseGreaterThanMaxValue(bizCode,key,1L,expiredTime,maxValue);
    }
}

 

提现相关,校验几秒内并发情况


import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.concurrent.TimeUnit;

 
@Service
@Slf4j
public class WithdrawalCacheHandler {


    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${spring.redis.keyspace}")
    private String keySpace;


    private String withdrawalforsnatchHashKeyFormat = ":withdraw:{0,number,#}";


    @PostConstruct
    public void postConstruct() {
        withdrawalforsnatchHashKeyFormat = keySpace + withdrawalforsnatchHashKeyFormat;
    }

    /**
     * 提现接口  校验3秒内是否有并发请求 ,
     * @param fcUserId
     * @param money
     * @return  返回true正常情况,  false代表3秒内有重复请求
     */
    public boolean toCheckRedisWithdrawal(Long fcUserId, BigDecimal money) {

        String key = MessageFormat.format(withdrawalforsnatchHashKeyFormat, fcUserId);

        Boolean hasSnatched = redisTemplate.opsForValue().setIfAbsent(key, money);
        if (hasSnatched)
        {
            redisTemplate.expire(key,3, TimeUnit.SECONDS);
        }
        return hasSnatched;
    }

    /**
     * 移除提现 占用  在finally内 解除3秒占用
     * @param fcUserId
     * @return
     */
    public boolean removeWithdrawal(Long  fcUserId) {
        String key = MessageFormat.format(withdrawalforsnatchHashKeyFormat, fcUserId);
        Boolean delete = redisTemplate.delete(key);
        return delete;
    }

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值