1. 程式人生 > >reidis分散式鎖做介面防重放

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的常見問題做了一個總結。大部分是自己在工作中遇到,以及以前面試別人的時候,愛問的一些問題。另外,不推薦大家臨時抱佛腳,真正碰到一些有經驗的工程師,其實幾下就能把你問懵。最後,希望大家有所收穫吧。