reidis分布式锁做接口防重放

需求:
随着项目的发展壮大,也会引起一些外围的大神,帮助测测并发,挑挑系统漏洞,以及宕机测试。这时候接口做防重放势在必行,选用redis做锁在合适不过,nosql数据库
单线程的redis为什么这么快
(一)纯内存操作
(二)单线程操作,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
redis的过期策略以及内存淘汰机制 redis采用的是定期删除+惰性删除策略。

===========================分割线===========================

redis的数据类型,以及每种数据类型的使用场景

(一)String
这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。

(二)hash
这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。

(三)list
使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。

(四)set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。
另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

(五)sorted set

sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外,参照另一篇《分布式之延时任务方案解析》,该文指出了sorted set可以用来做延时任务。最后一个应用就是可以做范围查找。

(六)redis做消息服务器

 spring-redis  redisTemplate.convertAndSend(channel, message);

 

用SETNX实现分布式锁

【java代码参考】:

    static final Log log = LogFactory.getLog(RedisServiceImpl.class);
	
	
	/**
	spring-redis 设置分布式锁并设置锁的有效期
	*/
    @Autowired
    private RedisTemplate<String, ?> redisTemplate;
    public boolean setNXAndExpire(final String key, final String value, long expiredSeconds) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
//                log.info("Before RedisServiceImpl.setNXAndExpire()  " + key + ":" + value);
                boolean success = connection.setNX(serializer.serialize(key), serializer.serialize(value));
                if (success) {
                    connection.expire(serializer.serialize(key), expiredSeconds);
                }
                return success;
            }
        });
        log.info("after RedisServiceImpl.setNXAndExpire() :" + result);

        return result;
    }

   
    
    
    /**
	spring-redis 还可以做消息服务器 发送topic消息
	*/
    @Override
    public void sendRedisMsg(String channel, String message) {
        redisTemplate.convertAndSend(channel, message);
    }


   @Override
    public boolean del(final String key) {
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.del(serializer.serialize(key));
                return true;
            }
        });

        return result;
    }
   
	
	
	
	
    @Override
    public String getset(final String key, final String value) {
        String result = redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                log.info("RedisServiceImpl.getset():" + key);
                byte[] value1 =  connection.getSet(serializer.serialize(key), serializer.serialize(value));
                return serializer.deserialize(value1);
            }
        });
        return result;

    }

 

===========================分割线===========================

把参数md5一下setnx存为key并设置有效期60s,只要在接口拦截器 或者切面拦截下url, 然后每次请求检查key是否存在 以及过期,则过滤掉接口,否则通过校验,这样就避免每次都请求连接数据库,

缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常;
减少了并发,削减了峰值;

避免了ddos攻击;这样在一定程度上缓解了系统宕机风险。

 

总结

本文对redis的常见问题做了一个总结。大部分是自己在工作中遇到,以及以前面试别人的时候,爱问的一些问题。另外,不推荐大家临时抱佛脚,真正碰到一些有经验的工程师,其实几下就能把你问懵。最后,希望大家有所收获吧。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值