记Redis的开发应用

maven依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

控制余量


private RedisTemplate<Object, Object> redisTemplate;
ListOperations<Object, Object> listRedis = redisTemplate.opsForList();

//采用Redis的list类型处理该业务场景,一开始通过leftPushAll方法放进值都为1总数量n个的value,key为所需控制余量的对象;
//设置总量
String[] strs = new String[n];
for (int i = 0; i < n; i++) {
	strs[i] = "1";
}
listRedis.leftPushAll(key,strs);

//判断目标是否还有余量
if(!Strings.isNullOrEmpty(listRedis.rightPop(key))){
	//业务代码
	...
	if(
		//业务正常,没出现问题
		...
	){
		//业务代码
		...
	}else{
		//业务出现问题,回滚库存
		listRedis.leftPushAll(key, 1);
	}
}

排行榜


private RedisTemplate<Object, Object> redisTemplate;
ZSetOperations<Object, Object> zSetRedis = redisTemplate.opsForZSet();
//sorted set类型的add方法加入数据
zSetRedis.add(key,value,score);
//reverseRank获取排名
zSetRedis.reverseRank(key,value)+1;
//获取前100名的排行榜
Set<Object> zrevrange = zSetRedis.reverseRange(key, 0L, 99L);
if(zrevrange.isEmpty()){
	return;
}
List<Object> list = new ArrayList<>(zrevrange);
List<T> tlist = new ArrayList<>();
Iterator iterator=list.iterator();
while(iterator.hasNext()){
	Long teamId = Long.parseLong((String) iterator.next());
    T t = new T();
    //业务代码,数据处理存储排名信息
    ...
   tlist.add(t);
}

简易的分布式锁

分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。

「互斥性」: 任意时刻,只有一个客户端能持有锁。 「锁超时释放」:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁。
「可重入性」:一个线程如果获取了锁之后,可以再次对其请求加锁。
「高性能和高可用」:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效。
「安全性」:锁只能被持有的客户端删除,不能被其他客户端删除


private RedisTemplate<Object, Object> redisTemplate;
ValueOperations<Object, Object> stringOps = redisTemplate.opsForValue();
//setnx如果为空就set值,并返回1,如果存在(不为空)不进行操作,并返回0,调用String类型的setIfAbsent方法。注:最好封装下
if(!stringRedis.setIfAbsent(key, "1", seconds, TimeUnit.SECONDS)){
	//该资源在被占用,作相应的业务代码处理,eg. log.info("操作过快/请求重复");
	...
}

但上诉方案存在2个问题,①线程a的锁过期释放了,但业务代码未结束,线程b就进来;②线程a的锁过期释放了,然后b线程进来,此时a业务代码结束了开始释放锁,但此时这个锁是b线程的锁
对于①有想过延长过期时间去解决或者开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放;对于②曾想过value值设置一个标记当前线程唯一的随机数,校验再进行删除避免出现误删的情况,但判断行为和释放锁行为不是同一个原子性操作,只能采用lua脚本实现;
还有一种方案是多机实现的分布式锁Redlock+Redisson

锁重试场景

   final String lock = MessageFormat.format(Constant.LOCK, Id);
        int count = 0;
        while(!stringRedis.setIfAbsent(key, "1", seconds, TimeUnit.SECONDS)){
            try {
                Thread.sleep(200L);
            }catch (Exception e) {
                Thread.currentThread().interrupt();
            }
            count++;
            if(count>10){
                return null;
            }
        }

附:访问链接的重试

 Boolean s = false;
        int i = 0;
        while (true){
            s = this.访问第三方接口();
            if (s || i > 10){
                break;
            }
            ++i;
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值