天天看點

Redis基礎學習Redis學習

文章目錄

  • Redis學習
    • 一、介紹
      • 資料庫發展史
      • 簡介
      • 資料庫使用情景(以電商平台為例)
      • NoSQL的四大分類
    • 二、安裝
      • Windows
      • Linux
    • 三、測試
      • redis-benchmark
    • 四、基礎知識
      • 資料庫
      • 五大資料類型
      • 三種特殊資料類型
      • 事務
      • 樂觀鎖
    • 五、Jdeis
      • 介紹
      • 使用
      • 使用事務
    • 六、整合Spring Boot
      • 建立項目
      • 使用
      • 序列化
    • 七、Redis配置檔案
      • 介紹
      • 内容
    • 八、RDB
      • 簡介
    • 九、AOF
      • 簡介
    • 十、訂閱釋出
      • 介紹
      • 使用
      • 原理
    • 十一、主從複制
      • 介紹
      • 環境搭建
      • 總結
    • 十二、哨兵模式
      • 介紹
      • 使用
      • 配置檔案詳細内容
    • 十三、緩存穿透、擊穿、雪崩
      • 介紹
      • 緩存穿透解決方案
      • 緩存擊穿解決方案
      • 緩存雪崩解決方案

Redis學習

一、介紹

  • 資料庫發展史

    • 單機資料庫
      • Redis基礎學習Redis學習
      • 網站通路量小,單個資料庫足夠小;
      • 靜态網頁,伺服器基本沒有壓力;
      • 資料庫讀寫混合;
    • Memcached(緩存)+MySQL+垂直拆分
      • Redis基礎學習Redis學習
      • 網站絕大部分都是在讀資料,是以加了個緩存用來減輕資料庫的壓力;
      • 資料庫讀寫分離;
    • 分庫分表+水準拆分+資料庫叢集
      • Redis基礎學習Redis學習
      • 将一個資料庫的内容拆分成多個資料庫叢集;
    • 微服務時代
      • Redis基礎學習Redis學習
  • 簡介

    • 什麼是NoSQL資料庫?
      • NoSQL(Not Only SQL)僅僅是一個概念,泛指非關系型的資料庫,差別于關系資料庫,它們不保證關系資料的ACID特性;
      • NoSQL是一項全新的資料庫革命性運動,其擁護者們提倡運用非關系型的資料存儲,相對于鋪天蓋地的關系型資料庫運用,這一概念無疑是一種全新的思維的注入;
      • 沒有固定的查詢語言;
      • 鍵值對存儲,列存儲,文檔存儲,圖形資料庫;
      • 可以一秒寫8萬次,讀取11萬次,性能高。
    • NoSQL資料庫的優點
      • 易擴充,NoSQL資料庫種類繁多,但是一個共同的特點都是去掉關系資料庫的關系型特性;
      • 資料之間無關系,這樣就非常容易擴充,也在架構的層面上帶來了可擴充的能力;
      • 大資料量,高性能,NoSQL資料庫都具有非常高的讀寫性能,尤其在大資料量下,同樣表現優秀。
    • 大資料時代的3V
      • 海量Volume;
      • 多樣Variety;
      • 實時Velocity。
    • 大資料時代的3高
      • 高并發;
      • 高可托;
      • 高性能。
    • 公司的技術選擇
      • 新浪:Redis;
      • 美團:Redis+Tair;
      • 阿裡、百度:Redis+Memecache;
    • 什麼是Redis?
      • Redis(Remote Dictionary Server ),即遠端字典服務。
      • Redis是一個開源的使用ANSI C語言編寫、支援網絡、可基于記憶體亦可持久化的日志型、Key-Value資料庫,并提供多種語言的API;
    • Redis的功能
      • Redis 是一個高性能的key-value資料庫;
      • Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器;
      • 記憶體存儲、持久化;
      • 釋出訂閱系統、地圖資訊分析、計時器、計數器(浏覽量)。
  • 資料庫使用情景(以電商平台為例)

    • 商品的基本資訊
      • 關系型資料庫;
      • MySQL、Oracle、…;
    • 商品的描述、評論(文字較多)
      • 文檔型資料庫;
      • MongoDB;
    • 圖檔
      • 分布式檔案系統;
      • FastDFS、TFS、Gooale、Hadoop;
    • 商品的關鍵字
      • 搜尋引擎;
      • solr、elasticsearch、Isearch;
    • 商品熱門的波段資訊
      • 記憶體資料庫
      • Redis、Tair、Memache;
    • 商品的交易】外部的支付接口
      • 三方應用;
  • NoSQL的四大分類

    • KV鍵值對
      • Redis、Oracle BDB;
    • 文檔型資料庫
      • MongoDB
        • 基于分布式檔案存儲的資料庫,C++編寫,主要用來處理大量的文檔;
        • 介于關系型資料庫和非關系資料庫的中間産品;
        • 非關系資料庫中功能最豐富;
      • ConthDB;
    • 列存儲
      • HBase;
      • 分布式檔案系統;
    • 圖關系資料庫
      • Redis基礎學習Redis學習
      • 存放的不是圖,是圖關系,如朋友圈社交網絡;
      • Neo4j、InfoGrid;

二、安裝

  • Windows

    • Redis下載下傳位址
    • 解壓打開,并輕按兩下啟動檔案
      Redis基礎學習Redis學習
    • 啟動界面
      Redis基礎學習Redis學習
    • 不建議在windows環境下使用

  • Linux

    • 官網下載下傳位址
    • 将壓縮包上傳到伺服器的opt目錄下并解壓
      tar -zxvf redis-x.x.x.tar.gz
                 
      Redis基礎學習Redis學習
    • 進入安裝目錄,檢視檔案
      Redis基礎學習Redis學習
    • 安裝Redis
      yum install gcc- c++
                 
      Redis基礎學習Redis學習
    • 檢視版本
      gcc -v
                 
      Redis基礎學習Redis學習
    • 基本環境安裝
      make
                 
      Redis基礎學習Redis學習
      make install
                 
      Redis基礎學習Redis學習
    • Redis的預設安裝路徑:usr/local/bin
      Redis基礎學習Redis學習
    • 将Redis配置檔案複制到自己的配置檔案夾中
      Redis基礎學習Redis學習
    • Redis預設不是背景啟動的,修改配置檔案
      vim redis.conf
                 
      Redis基礎學習Redis學習
      Redis基礎學習Redis學習
      Redis基礎學習Redis學習
    • 啟動Redis服務
      redis-server redis.conf
                 
      Redis基礎學習Redis學習
    • 連接配接Redis,使用基本指令
      redis-cli -p 6379
                 
      Redis基礎學習Redis學習
    • 檢視Redis服務是否開啟
      ps -ef|grep redis
                 
      Redis基礎學習Redis學習
    • 關閉Redis服務
      shutdown
      exit
                 
      Redis基礎學習Redis學習

三、測試

  • redis-benchmark

    • 介紹
      • redis-benchmark是一個壓力測試工具,官方自帶的性能工具;
    • 指令
      • redis-benchmark 指令參數
      • 參數 描述 預設值
        -h 指定伺服器主機名 127.0.0.1
        -p 指定伺服器端口 6379
        -s 指定伺服器socket
        -c 指定并發連接配接數 50
        -n 指定請求數 1000
        -d 以位元組的形式指定SET/GET值的資料大小 2
        -k 1=keep alive; 0=reconnect 1
        -r SET/GET/INCR 使用随機key,SADD使用随機值
        -P 通過管道傳輸 1
        -q 強制退出Redis,僅顯示query/sec值
        -csv 以CSV格式輸出
        -l 生成循環,永久執行測試
        -t 僅運作以逗号分隔的測試指令令牌
        -I Idle模式,僅打開N的idle連接配接并等待
    • 簡單測試
      • 啟動Redis服務
      • 100個并發連接配接 100000個請求
        redis-benchmark -h localhost -p 6379 -c 100 -n -100
                   
      • 測試結果
        Redis基礎學習Redis學習

四、基礎知識

  • 資料庫

    • 總共16個資料庫,預設使用第一個資料庫
      Redis基礎學習Redis學習
    • 切換資料庫
      SELECT 3
                 
      Redis基礎學習Redis學習
    • 檢視資料庫大小
      DBSIZE
                 
      Redis基礎學習Redis學習
    • 指派、取值、檢視所有值、清空目前資料庫資料、清空所有資料庫資料
      # 指派
      set keyName value
      # 取值
      get keyName
      # 檢視所有值
      key *
      # 清空目前資料庫資料
      flushdb
      # 清空所有資料庫資料
      flushall
                 
      Redis基礎學習Redis學習
    • 是否存在key
      # 0:不存在;1:存在
      EXISTS keyName
                 
      Redis基礎學習Redis學習
    • 設定某個key存儲時間、檢視key的剩餘時間、檢視key的類型
      EXPIRE keyName seconds
      ttl keyName
      type keyName
                 
      Redis基礎學習Redis學習
    • 官網指令集合
  • 五大資料類型

    • String
      • 使用場景:計數器、統計數量、緩存存儲等
      • # 設定值
        set keyName value
        
        # 擷取值
        get keyName
        
        # 是否存在keyName
        EXISTS keyName
        
        # 向key追加值,若key不存在則等于set指令
        APPEND keyName content
        
        # 擷取字元串長度
        STRLEN keyName
        
        # 讓keyName自增一 == i++
        incr keyName
        
        # 讓keyName自增num  == i += n
        incrby keyName num
        
        # 截取keyName字元串(閉區間),若beginIndex endIndex分别為0 -1則截取全部字元串
        GETRANGE keyName beginIndex endIndex
        
        # 從keyName字元串的第beginIndex個字元開始替換,替換長度為content的長度
        SETRANGE keyName beginIndex content
        
        # 設定有效時間
        setex keyName seconds
        
        #若keyName不存在,則設定成功,否則設定失敗
        setnx keyName value
        
        #批量設定值
        mset keyName1 value1 keyName2 value2 ...
        
        #批量設定值(原子操作,要麼都成功,要麼都失敗)
        msetnx keyName1 value1 keyName2 value2 ...
        
        # 批量擷取多個值
        mget keyName1 keyName2
        
        #key的進階用法,連續使用多個key設計
        set keyName1:keyName2:keyName3 value
        
        #設定對象類型(用JSON字元串指派)
        set user:1 {name:wjr,age:22}
        
        #先擷取值,擷取完再設定新的值
        getset keyName value
                   
    • List
      • List裡的值是可以重複的;
      • 所有關于List的指令都是L開頭的;
      • List的存在情況可以想象成水準擺放的雙向連結清單,可以從左邊插入值,也可以從右邊插入值;
      • # 向左邊插入值;若listName存在,則追加value;若不存在,則建立一個并追加;傳回目前List的長度
        LPUSH listName value
        
        # 向右邊插入值;若listName存在,則追加value;若不存在,則建立一個并追加;傳回目前List的長度
        RPUSH listName value
        
        # 檢視listName的資料(閉合,從左至右顯示);若beginIndex=0,endIndex=-1,則檢視全部資料
        LRANGE listName beginIndex endIndex
        
        # 彈出listName最左邊的值
        LPOP listName
        
        # 彈出listName最右邊的值
        RPOP listName
        
        # 從左至右取出listName第index的值
        LINDEX listName index
        
        # 檢視listName的長度
        LLEN listName
        
        # 移除listName中num個value值;若listName中value值的數量小于num,則删除全部value
        LREM listName num value
        
        # listName截取從beginIndex到endIndex的值(閉合,從左至右截取)
        LRTIM listName beginIndex endIndex
        
        # 移除listName1最右端的值,放入listName2最左邊,若listName2不存在,則建立後再移入
        RPOPLPUSH listName1 listName2
        
        # 将listName中index下标中值替換為value;index必須小于listName長度
        LSET listName index value
        
        # 從左至右,在listName的existedValue左邊(before)/右邊(after)插入newValue
        LINSERT listName before/after existedValue newValue
                   
      • 根據list的指令,可以

        将list轉換為棧或隊列使用

    • Set
      • Set是一個無序不重複集合;
      • Set集合裡的

        值不可以重複

      • Set的指令都是以S開頭的;
      • # 若setName存在,則追加value;若setName不存在,則建立并追加value
        SADD setName value
        
        # 檢視setName全部元素
        SMEMBERS setName
        
        # 随機彈出setName中的一個元素
        SPOP setName
        
        # 檢視setName裡是否存在value
        SISMEMBER setName value
        
        # 檢視setName的長度
        SCARD setName
        
        # 移除setName中的value
        SREM setName value
        
        # 随機抽出一個元素
        SRANDMEMBER setName
        
        # 将setName1中的value移到setName2中,若setName2不存在,則建立後再移入
        SMOVE setName1 setName2 value
                   
      • 并、交集
        #檢視setName1和 setName2的并集(粉絲和關注兩個集合,求并集得到互關使用者)
        SUNION setName1 setName2 
        
        # 檢視setName1和setName2的交集(共同好友)
        SINTER setName1 setName2
                   
    • Hash
      • Hash相當于Map,key為Map的名,value為Map裡的鍵值對;
      • Hash的所有指令都是H開頭;
      • # 若hashName存在,則添加鍵值對;若hashName不存在
        HSET hashName key value
        
        # 擷取hashName中key對應的值
        HGET hashName key
        
        # 一次檢視hashName多個key對應的值
        HMGEt hashName key1 key2 ...
        
        # 檢視hashName所有的鍵值對
        HGETALL hashName
        
        # 删除hashName中key
        HDEL hashName key
        
        # 檢視hashName的長度
        HLEN hashName
        
        # 檢視hashName中key是否存在
        HEXISTS hashName key
        
        # 隻擷取hashName中所有的key
        HKEYS hashName
        
        # 值擷取hashName中所有的field
        HVALS hashName
        
        # 将hashName中key對應的值自增num
        HINCRBY hashName key num
        
        # 将hashName中key對應的值自增num
        HINCRBY hashName key num
        
        # 若hashName中key存在,則指派失敗;若不存在,則指派成功
        HSETNX hashName key value
                   
      • 可以用來儲存使用者資訊
        # HSET user:1 name wjr
        HSET user:{id} key value
                   
    • Zset
      • Zset是一個有序集合,每一個元素都關聯一個數字;
      • 所有Zset的指令都是Z開頭的;
      • # 若zsetName存在,則添加value1(關聯num1),value2(關聯num2);若不存在,則建立後再添加
        ZADD zsetName num1 value1 num2 value2...
        
        # 将zsetName在lowerLimit和upperLimit範圍内從小到大排序(隻顯示value);-inf表示負無窮,+inf表示正無窮
        ZRANGEBYSCORE zsetName lowerLimit upperLimit
        
        # 隻顯示zsetName在lowerLimit和upperLimit範圍内的value的升序(既顯示value,又顯示score);-inf表示負無窮,+inf表示正無窮
        ZRANGEBYSCORE zsetName lowerLimit upperLimit withscores
        
        # 升序檢視zsetName中排序為第beginIndex到endIndex的value;若beginIndex=0,endIndex=-1,則檢視全部資料
        ZRANGE zsetName beginIndex endIndex
        
        # 移除zsetName中value值
        ZREM zsetName value
        
        # 檢視zsetName的長度
        ZCARD zsetName
        
        # 降序檢視zsetName中排序為第beginIndex到endIndex的value;若beginIndex=0,endIndex=-1,則檢視全部資料
        ZREVRANGE zsetName beginIndex endIndex
        
        # 檢視socre在lowerLimit和upperLimit範圍内的value個數
        ZCOUNT zsetName lowerLimit upperLimit
                   
    • 官方文檔
  • 三種特殊資料類型

    • Geospatial地理位置
      • 使用場景:朋友的定位、附件的人、打車距離計算…;
      • # 添加地理位置
        GEOADD key longitude latitude place
        
        # 擷取地理位置
        GEOPOS key place
        
        # 檢視place1和place2的直線距離距離,unit表示機關長度(m:米,預設;km:千米;mi:英裡;ft:英尺)
        GEODIST key place1 place2 unit
        
        # 将二維的經緯度轉換為以為的字元串(11個字元的GeoHash字元串),兩個字元串越接近,表明兩個地點越接近
        GEOHASH key place1 place2
        
        # 顯示在以longitude和latitude為原點,radius為半徑範圍内的地點,unit表示機關長度,withdist表示顯示距離原點的直線長度,withcoord表示顯示經緯度,num表示顯示的最大個數
        GEORADIUS key longitude latitude radius unit withdist withcoord count num
        
        # 顯示以place為原點,radius為半徑範圍内的地點
        GEORADIUSBYMEMBER key place radius unit
                   
      • GEO底層原理
        • 底層是通過ZSet實作的,可以直接使用ZSet指令操作GEO;
    • Hyperloglog
      • 基數統計算法,0.81%的錯誤率,可以接受,

        是一種資料結構

      • 使用場景:可以用來統計網站使用者通路人數;
      • # 往key中添加資料
        PFADD key value1 value2 value3 ...
        
        # 檢視key中資料的個數
        PFCOUNT key
        
        #合并oldKey1和oldKey2(并集),
        PFMERGE newKey oldKey1 oldKey2
        
        
                   
    • BitMaps
      • 位存儲(0 1 0 0 0),

        是一種資料結構

        ,隻适合兩種狀态的資料;
      • 使用場景:登陸/未登入;打卡/未打開;…;
      • # 往key的第index位置添加資料(0/1)
        SETBIT key index 0/1
        
        # 擷取key的第index位置的資料
        GETBIT key index
        
        # 統計key中value為1的個數
        BITCOUNT key
                   
  • 事務

    • Redis單條指令符合原子性,但事務不保證原子性也沒有隔離級别

    • Redis事務的本質:

      一組指令的集合!一個事務中的所有指令都會被序列化,在事務執行過程中,會按照順序執行

      (一次性、順序性、排他性);
      ________________
      指令入隊 -> set set get get ->指令執行
      		  ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
                 
    • # 開啟事務模式,接着輸入一系列指令
      MULTI
      
      # 輸入完一系列指令,使用EXEC指令執行這些指令
      EXEC
      
      # 取消事務(輸入一些列事務,不想執行使用DISCARD取消事務)
      DISCARD
                 
    • 若指令錯誤,事務中所有的指令都不會被執行

    • 若執行過程邏輯錯誤,則抛出異常,且繼續執行其他指令

  • 樂觀鎖

    • 悲觀鎖:很悲觀,什麼操作都加鎖;
    • 樂觀鎖:很樂觀,什麼操作都不加鎖,

      更新資料的時候判斷一下,在此期間是否有人修改過這個資料,version

    • # 監控key,若在事務過程中key被其他程序修改了,則key的值修改失敗(之後可以使用MULTI事務)
      WATCH key
      
      # 解除監控,使key擷取到最新的值
      UNWATCH
                 

五、Jdeis

  • 介紹

    • Jedis是Redis官方推薦的Java連接配接開發工具;
    • 要在Java開發中使用好Redis中間件,必須對Jedis熟悉才能寫成漂亮的代碼。
  • 使用

    • 建立普通Maven項目
    • 引入依賴
      <!-- Jedis -->
      <dependency>
          <groupId>redis.clients</groupId>
          <artifactId>jedis</artifactId>
          <version>3.3.0</version>
      </dependency>
      <!-- FASTJASON -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.73</version>
      </dependency>
                 
    • public class TestPing {
          public static void main(String[] args) {
              //連接配接Redis資料庫
              Jedis jedis = new Jedis("119.23.231.254",6379);
              //Jedis的指令和Redis指令名是一樣的
              System.out.println(jedis.ping());
              jedis.set("name","wjr");
              System.out.println(jedis.get("name"));
              System.out.println(jedis.keys("*"));
          }
      }
                 
  • 使用事務

    • public class TestTX {
          public static void main(String[] args) {
              Jedis jedis = new Jedis("119.23.231.254",6379);
              JSONObject jsonObject = new JSONObject();
              jsonObject.put("name","wjr");
              jsonObject.put("age",22);
      
              //開啟事務
              Transaction multi = jedis.multi();
              String jsonString = jsonObject.toJSONString();
      
              try {
                  multi.set("user:a",jsonString);
                  multi.set("user:b",jsonString);
      
                  //執行事務
                  multi.exec();
              }catch (Exception e){
                  //放棄事務
                  //若代碼出現異常,則放棄全部操作
                  multi.discard();
                  e.printStackTrace();
              }finally {
                  System.out.println(jedis.get("user:a"));
                  System.out.println(jedis.get("user:b"));
                  //關閉連接配接
                  jedis.close();
              }
      
          }
      }
                 

六、整合Spring Boot

  • 建立項目

    • 勾選如下依賴

      [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-qPoIWuVN-1600165722767)(SpringBoot學習/image-20200904183724071.png)]

    • SpringBoot2.x之後Jedis被替換為Lettuce;
      • Jedis采用的直連,多個線程操作的話,不安全,若要避免不安全,需使用Jedis Pool連接配接池(類似BIO);
      • Lettuce采用的Netty,執行個體可以在多個線程中進行共享,不存線上程不安全的情況(類似NIO)。
  • 使用

    • 根據源碼得知,可以自己重寫RedisTemplate類[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-E7kwtNDW-1600165722768)(SpringBoot%E5%AD%A6%E4%B9%A0/image-20200904185048848.png)]
    • Redis的屬性配置類[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-F4FhByyx-1600165722770)(SpringBoot%E5%AD%A6%E4%B9%A0/image-20200904185416887.png)]
    • 在application.yaml配置檔案中填寫配置資訊
      spring:
        redis:
          host: 119.23.231.254
          port: 6379
                 
    • 測試
      @SpringBootTest
      class SpringbootRedisApplicationTests {
          @Autowired
          private RedisTemplate redisTemplate;
          @Test
          void contextLoads() {
              //opsForValue:操作字元串
              //opsForList:操作List
              redisTemplate.opsForValue().set("name","JAY");
              System.out.println(redisTemplate.opsForValue().get("name"));
              
              //還可以直接通過RedisTemplate進行一些常用操作
              redisTemplate.delete("name");
      //        redisTemplate.discard();
          }
      
      }
                 
  • 序列化

    • 源碼
      • [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-KlPSHPAx-1600165722771)(F:\work\myBlogs\study\SpringBoot學習\image-20200904191131161.png)]
      • [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-D9IgPzf2-1600165722773)(F:\work\myBlogs\study\SpringBoot學習\image-20200904191404883.png)]
    • POJO的類必須序列化才可以使用
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @Accessors(chain = true)
      public class User implements Serializable {
          private String name;
          private int age;
      }
                 
      @Test
      void testSerializable() throws JsonProcessingException {
      	//必須序列化才可以
          User user = new User()
      					.setName("wjr")
      					.setAge(22);
      	redisTemplate.opsForValue().set("user:wjr",user);
      	System.out.println(redisTemplate.opsForValue().get("user:wjr"));
      }
                 
    • 自定義redisTemplate
      @Configuration
      public class RedisConfig {
          //編寫自定義redisTemplate
          @Bean
          public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
                  throws UnknownHostException {
              //改為<String,Object>
              RedisTemplate<String, Object> template = new RedisTemplate<>();
              template.setConnectionFactory(redisConnectionFactory);
      
              //序列化設定
              Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
              ObjectMapper objectMapper = new ObjectMapper();
              objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
      //        該方法已過時
      //        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
              objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
              objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
      
      
              //String的序列化
              StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
      
              //key采用String的序列化方式
              template.setKeySerializer(stringRedisSerializer);
              //hash的key也采用String的序列化方式
              template.setHashKeySerializer(stringRedisSerializer);
              //value序列化方式采用Jackson
              template.setValueSerializer(objectJackson2JsonRedisSerializer);
              //hash的value序列化方式也采用Jackson
              template.setHashValueSerializer(objectJackson2JsonRedisSerializer);
              return template;
          }
      }
                 
    • 自動裝配
      @Autowired
          @Qualifier("redisTemplate")
          private RedisTemplate redisTemplate;
                 
    • 可以自己編寫RedisUtils簡化代碼

七、Redis配置檔案

  • 介紹

    • 配置檔案名
      • redis.config
    • 作用
      • 啟動Redis的時候,是

        通過redis.config配置檔案啟動的

  • 内容

    • unit機關大小寫不敏感
      Redis基礎學習Redis學習
    • INCLUDES(引入)
      • 可以引入其他配置檔案
        Redis基礎學習Redis學習
    • NETWORK(網絡)
      • 允許哪些ip位址可以通路
        Redis基礎學習Redis學習
      • 使用的端口号
        Redis基礎學習Redis學習
      • 保護模式(遠端連接配接時可能會需要修改設定)
        Redis基礎學習Redis學習
    • GENERAL(通用)
      • 運作方式
        Redis基礎學習Redis學習
      • pidfile(守衛程式(背景)運作時需指定)
        Redis基礎學習Redis學習
      • 日志輸出級别
        Redis基礎學習Redis學習
      • 日志生成的檔案名
        Redis基礎學習Redis學習
      • 資料庫數量(預設16)
        Redis基礎學習Redis學習
      • 是否總顯示logo
        Redis基礎學習Redis學習
    • SNAPSHOTTING(快照)
      • 持久化,在規定時間内,執行了多少次操作,則會持久化到.rdb檔案和.aof檔案,可以自定義持久化規則
        Redis基礎學習Redis學習
      • 當持久化寫入出現錯誤是否停止運作
        Redis基礎學習Redis學習
      • 是否壓縮rdb檔案,需要消耗cpu資源
        Redis基礎學習Redis學習
      • 報錯rdb檔案的時候,是否進行錯誤檢查
        Redis基礎學習Redis學習
      • rdb檔案儲存的目錄
        Redis基礎學習Redis學習
    • REPLICATION(複制)
    • SECURITY(安全)
      • 設定密碼
        Redis基礎學習Redis學習
        # 使用下行語句設定登陸密碼
        config set requirepass "password"
        # 使用下行語句登陸
        auth password
                   
    • CLIENTS(用戶端)
      • 連接配接用戶端的最大數量(預設10000個)
        Redis基礎學習Redis學習
    • MEMORY MANAGEMENT(記憶體管理)
      • 配置最大的記憶體容量
        Redis基礎學習Redis學習
      • 記憶體滿了所執行的政策
        Redis基礎學習Redis學習
        # 六大政策
        volatile-lru:從已設定過期時間的記憶體資料集中挑選最近最少使用的資料 淘汰;
        volatile-ttl: 從已設定過期時間的記憶體資料集中挑選即将過期的資料 淘汰;
        volatile-random:從已設定過期時間的記憶體資料集中任意挑選資料 淘汰;
        allkeys-lru:從記憶體資料集中挑選最近最少使用的資料 淘汰;
        allkeys-random:從資料集中任意挑選資料 淘汰;
        no-enviction(驅逐):禁止驅逐資料。(預設淘汰政策。當redis記憶體資料達到maxmemory,在該政策下,直接傳回OOM錯誤)
                   
    • APPEND ONLY MODE(aof配置)
      • 是否開啟aof(預設不開啟)
        Redis基礎學習Redis學習
      • 同步方式
        Redis基礎學習Redis學習

八、RDB

  • 簡介

    • RDB是什麼?
      • Redis是記憶體資料庫,資料存放在記憶體中,若不将記憶體中的資料庫狀态儲存到磁盤,那麼一旦伺服器程序退出,伺服器中的資料庫狀态也會消失,是以Redis提供了持久化操作;
      • RDB(Redis DataBase),Redis資料持久化的一種方式,在指定的時間間隔内将記憶體中的資料集快照寫入磁盤(Snapshot快照),它恢複時将快照檔案直接讀到記憶體裡。
      • Redis基礎學習Redis學習
        運作原理圖
    • 産生rdb檔案的場景
      • 操作滿足save的規則,會自動産生rdb檔案;
      • 執行FLUSHALL/FLUSHDB,會産生rdb檔案;
      • 退出Redis,也會産生rdb檔案。
    • 如何恢複rdb檔案?
      • 隻需要将dump.rdb檔案放在Redis啟動目錄(redis.config存放的目錄)即可,啟動時自動檢查dump.rdp檔案
    • 優點
      • 适合大規模的資料恢複;
      • 對資料的完整性要求不高;
    • 缺點
      • 需要一定時間間隔操作程序,若在此期間意外當機,這間隔内的資料就丢失了;
      • fork程序的時候,會占用一定的記憶體空間。

九、AOF

  • 簡介

    • 什麼時AOF?
      • AOF(Append Only File),Redis資料持久化的方式之一;
      • 将所有的指令都記錄下來,恢複的時候把這些指令全部執行一遍;
      • Redis基礎學習Redis學習
        運作原理圖
      • AOF儲存的是appendonly.aof檔案;
      • Redis預設不開啟,需手動修改配置檔案啟動;
      • 若appendonly.aof檔案有錯誤,Redis無法啟動,需修複之後才可以啟動;
        # redis提供的修複工具(會将出錯的地方删除)
        redis-check-aof --fix appendonly.aof
                   
    • 重寫規則
      • 若AOF檔案大于64M,則父程序會fork一個新程序将檔案重寫;
    • 優點
      • 每一次修改都同步,檔案的完整性較好;
      • 每秒同步一次,可能會丢失一秒的資料;
      • 從不同不,效率最高;
    • 缺點
      • 相對于資料檔案來說,AOF遠遠大于RDB,而且修複的速度也比RDB慢很多;
      • AOF的效率也比RDB慢,是以Redis預設RDB;

十、訂閱釋出

  • 介紹

    • 什麼是Redis的訂閱釋出?
      • Redis的釋出訂閱(pub/sub)是一種消息通信模式:
        • 發送者(pub):發送消息;
        • 訂閱者(sub):接受消息;
      • Redis用戶端可以訂閱任意數量的頻道;
      • Redis基礎學習Redis學習
      • 頻道channel1以及訂閱這個頻道的三個用戶端的關系:
        Redis基礎學習Redis學習
      • 當有新消息通過PUBLISH指令發送給channel1時:
        Redis基礎學習Redis學習
  • 使用

    • 指令 描述
      PSUBSCRIBE pattern1 pattern2 … 訂閱一個或多個符合給定模式的頻道
      PUBSUB channel message 檢視訂閱與釋出系統狀态
      PUBLISH channel message 将資訊發送到指定的頻道
      PUNSUBSCRIBE pattern1 pattern2 … 推定所有給定模式的頻道
      SUBSCRIBE channel1 channel2 … 訂閱給定的一個或多個頻道的資訊
      UNSUBSCRIBE channel1 channel2 … 推定給定的頻道
    • 測試
      # A用戶端-訂閱頻道(若頻道不存在,則預設建立)
      127.0.0.1:6379> SUBSCRIBE game
      Reading messages... (press Ctrl-C to quit)
      1) "subscribe"
      2) "game"
      3) (integer) 1
      1) "message"
      2) "game"
      
      # B用戶端-端推送消息
      127.0.0.1:6379> PUBLISH game "SKT win"
      (integer) 1
      
      # A用戶端-顯示B用戶端推送的消息
      127.0.0.1:6379> SUBSCRIBE game
      Reading messages... (press Ctrl-C to quit)
      1) "subscribe"
      2) "game"
      3) (integer) 1
      # 等待讀取推送的消息
      1) "message"
      # 等待讀取消息的頻道
      2) "game"
      # 顯示B用戶端推送的消息
      3) "SKT win"
                 
  • 原理

    • 公衆号推送消息原理
      Redis基礎學習Redis學習

十一、主從複制

  • 介紹

    • 什麼是主從複制?
      • 主從複制,是指将一台Redis伺服器的資料,複制到其他的Redis伺服器,前者稱為主節點(master/leader),後者成為從節點(slave/follower);
      • 資料的複制是單向的,隻能由主節點到從節點,Master以寫為主,Slave以讀為主

      • 預設情況下,每台Redis伺服器都是主節點

      • 一個主節點可以有多個從節點(或沒有從節點),但一個從節點隻能有一個主節點

        ;
      • Redis基礎學習Redis學習
        主從複制結構圖
    • 主從複制的作用
      • 資料備援:主從複制實作了資料的熱備份,是持久化之外的一種資料備援方式;
      • 故障恢複:當主節點出現問題時,可以由從節點提供服務,實作快速的故障恢複(服務備援);
      • 負載均衡:在主從複制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(在寫少讀多的場景下,可以極大的提高Redis伺服器的并發);
      • 高可用基石:主從複制時哨兵和叢集能夠實施的基礎,是以說主從複制是Redis高可用的基礎。
    • 為什麼要叢集?
      • 一般來說,要将Redis運用于工程項目中,隻使用一台Redis服務會:
        • 結構上:單個Redis伺服器會發生單點故障,并且一台伺服器需要處理所有的請求負載,壓力較大;
        • 容量上:單個Redis伺服器記憶體容量有限;
      • 而使用叢集可以很好的解決上述問題。
  • 環境搭建

    • 檢視目前Redis資料庫資訊
      # Redis預設為Master
      127.0.0.1:6379> info replication
      # Replication
      # 角色
      role:master
      # 表示沒有從機
      connected_slaves:0
      master_replid:1e5f4113713dadda56cf3381ac136f488c7e38c2
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:0
      second_repl_offset:-1
      repl_backlog_active:0
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:0
      repl_backlog_histlen:0
                 
    • 建立不同的redis.conf配置檔案
      # redisxx.conf 表示端口為63xx
      [[email protected] myconfig]# ls
      backup.db  dump.rdb  redis79.conf  redis80.conf  redis81.conf 
                 
    • 修改關鍵資訊
      port 63xx
      pidfile /var/run/redis_63xx.pid
      logfile "63xx.log"
      dbfilename dump63xx.rdb
                 
      Redis基礎學習Redis學習
      [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-hwsVv8dW-1600165722812)(https://gitee.com/lazy-r/blog-img/raw/master/images/image-20200914221554410.png)]
      Redis基礎學習Redis學習
      Redis基礎學習Redis學習
    • 啟動三個redis
      # 分别執行不同的Redis配置檔案
      [[email protected] myconfig]# redis-server redisxx.conf 
      [[email protected] myconfig]# redis-cli -p 63xx
                 
    • 檢視Redis啟動情況
      [[email protected] myconfig]# ps -ef|grep redis
      root      3062     1  0 Sep04 ?        00:17:46 redis-server *:6379
      root     30327     1  0 22:47 ?        00:00:01 redis-server *:6380
      root     30332     1  0 22:47 ?        00:00:02 redis-server *:6381
      root     30358 30184  0 22:49 pts/1    00:00:00 redis-cli -p 6380
      root     30383 30203  0 22:51 pts/2    00:00:00 redis-cli -p 6381
      root     30701 29520  0 23:22 pts/0    00:00:00 redis-cli -p 6379
      root     30708 30222  0 23:23 pts/3    00:00:00 grep --color=auto redis
                 
    • 叢集配置(指令配置)
      # 指定Redis服務所屬的主節點
      SLAVEOF host port
      
      # 執行個體測試
      # 6381端口的Redis服務
      127.0.0.1:6381> SLAVEOF 127.0.0.1 6379
      OK
      127.0.0.1:6381> info replication
      # Replication
      # 角色轉為slave
      role:slave
      # 所屬主節點的資訊
      master_host:127.0.0.1
      master_port:6379
      master_link_status:up
      master_last_io_seconds_ago:3
      master_sync_in_progress:0
      slave_repl_offset:28
      slave_priority:100
      slave_read_only:1
      connected_slaves:0
      master_replid:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:28
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:1
      repl_backlog_histlen:28
      
      # 6380端口的Redis服務
      127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
      OK
      127.0.0.1:6380> info replication
      # Replication
      # 角色slave
      role:slave
      # 所屬主節點的資訊
      master_host:127.0.0.1
      master_port:6379
      master_link_status:up
      master_last_io_seconds_ago:2
      master_sync_in_progress:0
      slave_repl_offset:476
      slave_priority:100
      slave_read_only:1
      connected_slaves:0
      master_replid:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:476
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:435
      repl_backlog_histlen:42
      
      # 6379端口的Redis服務
      127.0.0.1:6379> info replication
      # Replication
      # 角色master
      role:master
      # 從節點個數
      connected_slaves:2
      # 從節點詳細資訊
      slave0:ip=127.0.0.1,port=6381,state=online,offset=574,lag=0
      slave1:ip=127.0.0.1,port=6380,state=online,offset=574,lag=1
      master_replid:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:574
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:1
      repl_backlog_histlen:574
                 
    • 叢集配置(配置檔案配置)
      replicaof <masterip> <masterport>
                 
      [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-3IRNBgFk-1600165722816)(F:\work\myBlogs\study\Redis學習\image-20200914234108707.png)]
    • 測試
      # Master(6379端口)節點
      # 寫資料
      127.0.0.1:6379> set name wjr
      OK
      # 讀資料
      127.0.0.1:6379> get name
      "wjr"
      
      # Slave(6380端口)節點
      # 讀資料
      127.0.0.1:6380> get name
      "wjr"
      # 寫資料(失敗)
      127.0.0.1:6380> set age 22
      (error) READONLY You can't write against a read only replica.
                 
    • 指令配置的情況下:若主節點(6379端口)當機,手動設定新的主節點(

      謀朝篡位,選擇新的主節點後,原先主節點恢複之後和這個叢集沒有任何關系了

      # 系統随機從剩餘從節點選中一個當主節點
      127.0.0.1:6380> SLAVEOF no one
      OK
      # 檢視6380端口詳細資訊
      127.0.0.1:6380> info replication
      # Replication
      # 角色master,系統随機選擇了6380端口為主節點
      role:master
      # 從節點個數
      connected_slaves:1
      # 從節點詳細資訊
      slave0:ip=127.0.0.1,port=6381,state=online,offset=574,lag=0
      master_replid:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:476
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:435
      repl_backlog_histlen:42
                 
  • 總結

    • 主從節點的特性
      • 主節點可以讀也可以寫資料,但從節點隻可以讀資料

      • 沒有配置哨兵模式的情況下:主節點斷開時,從節點隻可以讀資料無法寫資料,待主節點恢複時,從機依舊可以擷取主節點寫入的資訊

      • 使用指令行配置主從節點的情況下:若從節點斷開了,再恢複時又變回初始狀态的獨立主節點,若此時再使用指令行連接配接回主節點,則會恢複主節點寫入的資料

    • 原理
      • Slave節點啟動成功連接配接到Master節點會發送一個sync指令;
    • Master節點接收到指令,啟動背景的存盤程序,同時收集所有接收到的用于修改資料集指令,在背景執行完畢後,Master節點将傳送整個資料庫檔案到Slave節點,完成一次完全同步;
      • 全量複制:Slave節點再接收到資料庫檔案後,将其存盤并加載到記憶體中;
    • 增量複制:Master節點繼續将新的所有收集到的修改指令依次傳給Slave,完成同步;
      • 隻要從節點重新連接配接Master節點,一次全量複制将被自動執行

十二、哨兵模式

  • 介紹

    • 為什麼要用哨兵模式?
      • 在哨兵模式出現之前,主節點當機之後,必須人工幹預才可以恢複正常運作,費時費力,于是哨兵模式為了解決這個問題應運而生;
      • Redis2.8開始正式提供了Sentinel(哨兵)架構來解決這個問題。
    • 什麼是哨兵模式?
      • 手動設定主節點(謀朝篡位)的自動版,能夠背景自動監控主機是否故障,若故障了根據投票數自動将從節點轉換為主節點;
      • 哨兵模式一種特殊的模式,Redis提供了哨兵的指令,哨兵是一個獨立運作的程序;
      • 原理是哨兵通過發送指令,等待Redis伺服器響應進而監控運作的多個Redis執行個體:
        Redis基礎學習Redis學習
        哨兵架構圖
    • 哨兵的作用
      • 通過發送指令。讓Redis伺服器傳回監控器運作狀态,包括主節點和從節點;
      • 當哨兵監測到master當機,會自動将Slave切換成Master,然後通過

        釋出訂閱模式通知其他從節點

        ,修改配置檔案進而切換主節點;
    • 多哨兵模式
      • 一個哨兵對Redis伺服器進行監控可能會出現問題,是以可以使用多個哨兵進行監控,各個哨兵之間還會進行監控
      • Redis基礎學習Redis學習
        多哨兵模式架構圖
    • 多哨兵模式原理
      • 若主節點當機,哨兵1檢測到這個結果,系統并不會立刻重新選舉新的主節點,

        僅當達到一定數量的哨兵檢測到主節點不可用時,哨兵之間會進行一次投票,投票結果由一個哨兵發起,進行failover(故障轉移)操作,切換成功後,就會通過釋出訂閱模式,讓各個哨兵把自己的主節點監控切換到新的主節點

        Redis基礎學習Redis學習
  • 使用

    • 初始條件
      # 開啟6379、6380、6381三個端口的Redis伺服器
      [[email protected] ~]# ps -ef|grep redis
      root      3062     1  0 Sep04 ?        00:18:45 redis-server *:6379
      root      8391  7780  0 15:56 pts/0    00:00:00 redis-cli -p 6379
      root      8415  8394  0 15:56 pts/1    00:00:00 redis-cli -p 6380
      root      8442  8418  0 15:57 pts/2    00:00:00 redis-cli -p 6381
      root      8463  8445  0 15:57 pts/3    00:00:00 grep --color=auto redis
      root     30327     1  0 Sep14 ?        00:01:00 redis-server *:6380
      root     30332     1  0 Sep14 ?        00:01:00 redis-server *:6381
      
      # 檢視主從節點的資訊
      127.0.0.1:6379> info replication
      # Replication
      # 6379端口Redis為主節點
      role:master
      # 6380端口、6381端口Redis為從節點
      connected_slaves:2
      slave0:ip=127.0.0.1,port=6381,state=online,offset=83047,lag=1
      slave1:ip=127.0.0.1,port=6380,state=online,offset=83047,lag=1
      master_replid:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:83047
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:1
      repl_backlog_histlen:83047
                 
    • 建立哨兵配置檔案
      [[email protected] myconfig]# pwd
      /usr/local/bin/myconfig
      [[email protected] myconfig]# ls
      6379.log  6380.log  6381.log  backup.db  dump6380.rdb  dump6381.rdb  dump.rdb  redis79.conf  redis80.conf  redis81.conf
      [[email protected] myconfig]# vim sentinel.conf
                 
    • sentinel.conf内容
      # 設定初始監控的主節點
      # sentinel monitor 被監控節點的名稱 host port n
      # n表示當有n個哨兵認為主節點不可用才開始投票
      sentinel monitor masetrRedis 127.0.0.1 6379 1
                 
    • 啟動哨兵sentinel
      # 通過sentinel.conf配置檔案啟動哨兵
      [[email protected] myconfig]# redis-sentinel sentinel.conf 
      8554:X 15 Sep 2020 16:04:08.918 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
      8554:X 15 Sep 2020 16:04:08.918 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=8554, just started
      8554:X 15 Sep 2020 16:04:08.918 # Configuration loaded
                      _._                                                  
                 _.-``__ ''-._                                             
            _.-``    `.  `_.  ''-._           Redis 5.0.9 (00000000/0) 64 bit
        .-`` .-```.  ```\/    _.,_ ''-._                                   
       (    '      ,       .-`  | `,    )     Running in sentinel mode
       |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
       |    `-._   `._    /     _.-'    |     PID: 8554
        `-._    `-._  `-./  _.-'    _.-'                                   
       |`-._`-._    `-.__.-'    _.-'_.-'|                                  
       |    `-._`-._        _.-'_.-'    |           http://redis.io        
        `-._    `-._`-.__.-'_.-'    _.-'                                   
       |`-._`-._    `-.__.-'    _.-'_.-'|                                  
       |    `-._`-._        _.-'_.-'    |                                  
        `-._    `-._`-.__.-'_.-'    _.-'                                   
            `-._    `-.__.-'    _.-'                                       
                `-._        _.-'                                           
                    `-.__.-'                                               
      
      8554:X 15 Sep 2020 16:04:08.920 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
      8554:X 15 Sep 2020 16:04:08.922 # Sentinel ID is cfd6f6b93080126d61100e032aa4c494e79e06b2
      # 監控主節點資訊
      8554:X 15 Sep 2020 16:04:08.922 # +monitor master masetrRedis 127.0.0.1 6379 quorum 1
      # 監控從節點資訊
      8554:X 15 Sep 2020 16:04:08.923 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:04:08.925 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ masetrRedis 127.0.0.1 6379
                 
    • 測試
      # 關閉主節點
      127.0.0.1:6379> SHUTDOWN
      not connected> exit
      
      # 哨兵模式
      # 省略初始資訊,顯示主節點當機之後追加的資訊
      # 檢測到6379主節點當機
      8554:X 15 Sep 2020 16:07:28.439 # +sdown master masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.439 # +odown master masetrRedis 127.0.0.1 6379 #quorum 1/1
      8554:X 15 Sep 2020 16:07:28.439 # +new-epoch 1
      8554:X 15 Sep 2020 16:07:28.439 # +try-failover master masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.441 # +vote-for-leader cfd6f6b93080126d61100e032aa4c494e79e06b2 1
      8554:X 15 Sep 2020 16:07:28.441 # +elected-leader master masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.441 # +failover-state-select-slave master masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.532 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.532 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.587 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.779 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.779 # +failover-state-reconf-slaves master masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:28.865 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:29.863 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:29.863 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ masetrRedis 127.0.0.1 6379
      8554:X 15 Sep 2020 16:07:29.928 # +failover-end master masetrRedis 127.0.0.1 6379
      # 随機選舉6381端口Redis為新的主節點
      8554:X 15 Sep 2020 16:07:29.928 # +switch-master masetrRedis 127.0.0.1 6379 127.0.0.1 6381
      8554:X 15 Sep 2020 16:07:29.928 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ masetrRedis 127.0.0.1 6381
      8554:X 15 Sep 2020 16:07:29.928 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ masetrRedis 127.0.0.1 6381
      8554:X 15 Sep 2020 16:07:59.954 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ masetrRedis 127.0.0.1 6381
      
      # 檢視6381端口Redis詳細資訊
      127.0.0.1:6381> info replication
      # Replication
      # 角色切換為主機
      role:master
      connected_slaves:1
      slave0:ip=127.0.0.1,port=6380,state=online,offset=98520,lag=1
      master_replid:ad5919b61535ff7e8ace1b6e5693d168d872d09a
      master_replid2:7f2476a7a5727f2aa89c23611d49fe0ba11560bc
      master_repl_offset:98534
      second_repl_offset:97682
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:1
      repl_backlog_histlen:98534
      
      # 恢複6379端口Redis
      [[email protected] myconfig]# redis-server redis79.conf 
      [[email protected] myconfig]# redis-cli -p 6379
      # 檢視6379端口Redis詳細資訊
      127.0.0.1:6379> info replication
      # Replication
      # 角色不再是主節點,而是自動變為從節點
      role:slave
      master_host:127.0.0.1
      master_port:6381
      master_link_status:up
      master_last_io_seconds_ago:1
      master_sync_in_progress:0
      slave_repl_offset:122289
      slave_priority:100
      slave_read_only:1
      connected_slaves:0
      master_replid:ad5919b61535ff7e8ace1b6e5693d168d872d09a
      master_replid2:0000000000000000000000000000000000000000
      master_repl_offset:122289
      second_repl_offset:-1
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:122131
      repl_backlog_histlen:159
                 
  • 配置檔案詳細内容

    • sentinel.conf
      基礎配置
      protected-mode no       #關閉保護模式                                   
      port 26479                    #端口                                             daemonize yes             #使用背景模式啟動                                       pidfile "/var/run/redis-sentinel_26479.pid"                       #程序id檔案   logfile "/usr/local/redis/sentinel/sentinel_26479.log"           #日志檔案       dir "/usr/local/redis/sentinel"               #工作目錄
      
      核心配置
      1、sentinel monitor <master-name> <ip> <port> <quorum>
      master-name:redis主節點昵稱。
      ip:redis主機ip。
      port:redis主機端口。
      quorum:哨兵判斷主節點是否發生故障的票數。如果設定為2,表示2個哨兵節點認為主節點發生了故障,一般設定為:哨兵節點數/2+1。
      
      2、sentinel down-after-milliseconds <master-name> <times>
      哨兵會定期的向redis節點發送ping指令來判斷redis是否可達,若超過指定的times毫秒内還未得到pong回複,則判讀該redis不可達。
      
      3、sentinel parallel-syncs <master-name> <nums>
      當redis主節點挂了後,哨兵會選出新的master,此時,剩餘的slave會向新的master發起同步資料,這個設定表示允許并行同步的slave個數。
      
      4、sentinel failover-timeout <master-name>  <times>
      進行故障轉移時,如果超過設定的times毫秒,表示故障轉移失敗。
      
      5、sentinel auth-pass <master-name> <password>
      如果redis主節點設定了密碼,則需要進行這個配置。
      
      6、sentinel notification-script <master-name> <script-path>
      若主節點出現故障,則啟動腳本檔案發送郵件通知,注意:腳本檔案必須是存在且可執行的,否則可能會導緻無法啟動的情況
       
      
      *****備注配置redis主從複制、讀寫分離*******
      
      配置思路:master配置檔案不需要動,修改slave的配置檔案。
      
      1、添加一行:replicaof <masterip> <masterport>
      2、如果master配置有密碼,則需要配置這一行
        masterauth <master-password>
      3、replica-read-only yes    #表示slave中的資料是隻讀的
                 
    • SpringBoot在application.yaml中整合哨兵模式
      spring:
      
        redis:
          database: 0
          password: 12345678
          sentinel:
            master: mymaster
            nodes: 192.168.0.1:26379,192.168.0.1:26479,192.168.0.1:26579
                 

十三、緩存穿透、擊穿、雪崩

  • 介紹

    • 什麼是緩存穿透?
      • 使用者想查詢一個資料,發現Redis記憶體資料庫沒有,也就是緩存沒有命中,于是向持久層資料庫查詢,發現也沒有,于是本次查詢失敗;
      • 當查詢使用者非常多的時候,便會大量的向持久層資料庫查詢資料,這會給持久層資料庫造成很大的壓力;
      • 緩存穿透原理圖
        Redis基礎學習Redis學習
    • 什麼是緩存擊穿?
      • 緩存擊穿是指高并發集中通路對一個點進行通路,

        當這個key在失效的瞬間,持續的大并發就會穿破緩存,直接通路持久層資料庫

        ,就像在緩存資料庫上擊穿了一個洞;
    • 什麼是緩存雪崩?
      • 緩存雪崩指在某一個時間段,緩存集中過期失效或Redis當機;
      • 緩存雪崩原理圖
        Redis基礎學習Redis學習
  • 緩存穿透解決方案

    • 布隆過濾器
      • 布隆過濾器是一種資料結構,對所有可能的查詢的參數以Hash形式存儲,在控制層先進行校驗,不符合則丢棄,進而避免了對持久層資料庫的查詢壓力;
      • 布隆過濾器運作原理圖
        Redis基礎學習Redis學習
    • 緩存空對象
      • 當持久層不命中後,即使傳回空對象也緩存起來,同時會設定一個過期時間,之後再通路這個資料将會直接從緩存中擷取,緩解了持久層的查詢壓力;
      • 緩存空對象運作原理圖
        Redis基礎學習Redis學習
  • 緩存擊穿解決方案

    • 設定熱點資料永不過期
    • 加分布式鎖
      • 使用分布式鎖,

        保證對于每個key同時隻有一個線程取查詢後端服務,其他線程沒有獲得分布式鎖的權限,是以隻需要等待即可

        ,這種方式将包并發的壓力轉移到了分布式鎖,是以對分布式鎖的考驗很大。
  • 緩存雪崩解決方案

    • Redis高可用
      • 多加幾個Redis服務節點,搭建更大的叢集;
      • 關閉一些非關鍵功能;
    • 限流降級
      • 在緩存失效後,通過加鎖或者隊列來控制資料庫寫緩存的線程數量,如對某個key隻允許一個線程查詢資料和寫緩存,其他線程等待;
    • 資料預熱
      • 在正式部署之前,把所有可能通路的資料先預通路一遍,保證可能大量通路的資料提前加載到緩存中;
      • 在即将發生大并發前手動觸發加載緩存不同的key,設定不同的過期時間,讓緩存失效的時間盡量均勻;