1. 程式人生 > 資訊 >力帆科技汽車業務重啟:首款換電型純電動 B 級 MPV 車型量產下線

力帆科技汽車業務重啟:首款換電型純電動 B 級 MPV 車型量產下線

redis

redis 資料型別以及應用場景

  • string:驗證碼
  • list:訂單列表
  • hash:購物車
  • set:訂單列表
  • Sorted Set:排行榜

redis 持久化方式

  1. RDB持久化是指在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,實際操作過程是fork一個子程序,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存。

在這裡插入圖片描述

  1. AOF持久化以日誌的形式記錄伺服器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以開啟檔案看到詳細的操作記錄。

在這裡插入圖片描述
RDB持久化配置

Redis會將資料集的快照dump到dump.rdb檔案中。此外,我們也可以通過配置檔案來修改Redis伺服器dump快照的頻率,在開啟6379.conf檔案之後,我們搜尋save,可以看到下面的配置資訊:

save 900 1              #在900(15分鐘)之後,如果至少有1個key發生變化,則dump記憶體快照。
save 300 10             #在300(5分鐘)之後,如果至少有10個key發生變化,則dump記憶體快照。
save 60
10000 #在60(1分鐘)之後,如果至少有10000個key發生變化,則dump記憶體快照。

AOF持久化配置

在Redis的配置檔案中存在三種同步方式,它們分別是:

appendfsync always     #每次有資料修改發生時都會寫入AOF檔案。
appendfsync everysec   #每秒鐘同步一次,該策略為AOF的預設策略。
appendfsync no         #從不同步。高效但是資料不會被持久化。

參考資料:點選這裡

redis 記憶體淘汰策略

過期策略

我們set key的時候,都可以給一個expire time,就是過期時間,指定這個key比如說只能存活1個小時,我們自己可以指定快取到期就失效。如果假設你設定一個一批key只能存活1個小時,那麼接下來1小時後,redis是怎麼對這批key進行刪除的?

答案是:定期刪除+惰性刪除

  • 所謂定期刪除,指的是redis預設是每隔100ms就隨機抽取一些設定了過期時間的key,檢查其是否過期,如果過期就刪除。注意,這裡可不是每隔100ms就遍歷所有的設定過期時間的key,那樣就是一場效能上的災難。
    實際上redis是每隔100ms隨機抽取一些key來檢查和刪除的。

  • 但是,定期刪除可能會導致很多過期key到了時間並沒有被刪除掉,所以就得靠惰性刪除了。這就是說,在你獲取某個key的時候,redis會檢查一下
    ,這個key如果設定了過期時間那麼是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。並不是key到時間就被刪除掉,而是你查詢這個key的時候,redis再懶惰的檢查一下

通過上述兩種手段結合起來,保證過期的key一定會被幹掉。但是實際上這還是有問題的,如果定期刪除漏掉了很多過期key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期key堆積在記憶體裡,導致redis記憶體塊耗盡了,怎麼辦?

答案是:走記憶體淘汰機制。

記憶體淘汰機制:

如果redis的記憶體佔用過多的時候,此時會進行記憶體淘汰,有如下一些策略:

  • noeviction:當記憶體不足以容納新寫入資料時,新寫入操作會報錯,這個一般沒人用吧
  • allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key(這個是最常用的)
  • allkeys-random:當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個key,這個一般沒人用吧
  • volatile-lru:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的key(這個一般不太合適)
  • volatile-random:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個key
  • volatile-ttl:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的key優先移除

redis 快取穿透、擊穿、雪崩問題

  1. 快取穿透:key對應的資料在資料來源並不存在,每次針對此key的請求從快取獲取不到,請求都會到資料來源,從而可能壓垮資料來源。比如用一個不存在的使用者id獲取使用者資訊,不論快取還是資料庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮資料庫。
  2. 快取擊穿:key對應的資料存在,但在redis中過期,此時若有大量併發請求過來,這些請求發現快取過期一般都會從後端DB載入資料並回設到快取,這個時候大併發的請求可能會瞬間把後端DB壓垮。
  3. 快取雪崩:當快取伺服器重啟或者大量快取集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如DB)帶來很大壓力。

解決方式:使用setnx,配合雙重鎖的機制程式碼如下:

package com.redis.lock;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

/**
 * setNx 悲觀鎖 解決雪崩 擊穿 穿透問題
 * 事物+監聽  解決秒殺 庫存賣超問題。
 */
@Component
public class RedisLockTest extends Thread {


    @Override
    public void run() {
        try {
            setNx();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    public String setNx() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"開始獲取快取資料");
        String key = stringRedisTemplate.opsForValue().get("order");
        if (StringUtils.isNotBlank(key)){
            System.out.println(Thread.currentThread().getName()+"開始獲取快取資料成功,返回");
            return  key;
        }
        System.out.println(Thread.currentThread().getName()+"獲取快取資料失敗");
        Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent("lock", "1");

        if (aBoolean){
            System.out.println(Thread.currentThread().getName()+"拿到鎖成功,重新設定快取");
            stringRedisTemplate.expire("lock",1, TimeUnit.MINUTES);
            //處理業務邏輯
            key = stringRedisTemplate.opsForValue().get("order");
            if (StringUtils.isNotBlank(key)){
                System.out.println(Thread.currentThread().getName()+"---------返回快取資料");
                stringRedisTemplate.delete("lock");
                return  stringRedisTemplate.opsForValue().get("order");
            }
            //模擬查詢資料庫
            Thread.sleep(2000);
            stringRedisTemplate.opsForValue().set("order","訂單號為123456");
            stringRedisTemplate.delete("lock");
            System.out.println(Thread.currentThread().getName()+"。。。。。。返回快取資料");
            return  stringRedisTemplate.opsForValue().get("order");
        }else {
            Thread.sleep(500);
            setNx();
        }
        return null;
    }
}

redis 叢集模式,以及cluster叢集

參考資料:點選這裡

redis 應用場景

  • 登入鎖定
  • 驗證碼生成
  • springSecurity token
  • 分散式事務
  • 限流令牌桶

Redis哨兵怎麼實現的-主節點掛掉後從節點怎麼實現轉為主節點的

參考資料 : 點選這裡

redis 叢集的三種模式優缺點

參考資料:點選這裡