1. 程式人生 > 資料庫 >Redis的基本環境配置以及基本使用入門

Redis的基本環境配置以及基本使用入門

文章目錄

Redis是什麼

Redis(Remote Dictionary Server ),即遠端字典服務,是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。

Redis能做什麼

1、記憶體儲存、持久化,記憶體中是斷電即失、所以說持久化很重要( rdb、 aof )
2、效率高,可以用於快取記憶體
3、釋出訂閱系統
4、地圖資訊分析
5、計時器、計數器(瀏覽量!)

Redis使用之前的準備工作

將Redis安裝到本地的Linux或者遠端的伺服器都可以,我這裡是選擇將Redis安裝到了阿里雲伺服器,可以通過寶塔一鍵傻瓜式安裝,具體教程可以觀看。也可以通過自己下載對應的Redis的Linux版本的安裝包,通過Xshell和Xftp自行安裝。如果是通過寶塔安裝完成Redis之後,Redis會存放到以下目錄:

在這裡插入圖片描述
因為Redis是用C++編寫的,我們使用Xshell連線到遠端伺服器之後,通過cd命令進入到這個目錄,安裝一些基本的使用環境,通過:
yum install gcc-c++
yum install tcl(redis6.0版本以上需要使用這個)
安裝完成之後,我們通過make(寶塔傻瓜式安裝好像不用make,因為他已經幫我們準備好了所有的環境,具體使用可以看這篇文章上面一點的一個超連結,但是如果是自己通過下載安裝包拷貝的形式的話,需要make一下)將一些環境給配置一下。配置完成後,我們可以通過
make install檢視安裝情況,出現如下程式碼則顯示安裝成功。
在這裡插入圖片描述

安裝完成之後,我們為了避免直接修改此檔案,應該將該目錄下的redis.conf檔案複製貼上一份,貼上到我們的/usr/local/bin/xxx的目錄下,可通過Xftp直接複製貼上,然後在bin目錄下新建一個資料夾用於存放我們的redis配置檔案。如圖所示:

在這裡插入圖片描述
隨後我們通過shell命令列vim redis.conf或者直接用Xftp右鍵修改,將
daemonize 修改為yes,設定為預設啟動,因為redis不是預設啟動的(使用寶塔傻瓜式安裝好像這裡預設就是yes不用修改)在這裡插入圖片描述
到這裡基本準備環境就準備好了,我們可以啟動redis了,在/usr/local/bin目錄下,我們通過前面一步自己配置的conf檔案啟動我們的redis,通過shell輸入:
redis-server 自己的目錄/redis.conf
redis6.0版本之後啟動成功是不會有提示的,所以到這一步的小夥伴們不要擔心是不是自己哪一個步驟除了問題導致啟動失敗。然後我們連結我們的redis伺服器,通過:
redis-cli -h 埠號 -p 6379
其中由於-h是預設的使用的本機,所以因此可以不用寫上去,-p是我們的redis伺服器,6379是我們的預設埠號。
回車之後,我們通過Ping命令測試是否連線成功,如果返回的是pong,則表示連線成功,如圖所示:
在這裡插入圖片描述
通過keys *可以檢視所有的key值。
在這裡插入圖片描述

如果我們想要檢視我們的程序是否開啟,可以通過
ps -ef | grep 程序
檢視,如:
在這裡插入圖片描述
如果我們要關閉我們的redis服務,可以通過
shutdown 然後 exit即可,如:
在這裡插入圖片描述
再次檢視程序,會發現該程序其實已經是被終結了。 至此,我們的基本準備環境已經完成了。

Redis-benchmark壓力測試工具

相關引數:
在這裡插入圖片描述

Redis基礎知識

1、redis的資料庫有16個,預設使用的是第0個。
在這裡插入圖片描述
我們可以通過select切換資料庫,通過DBSIZE檢視當前庫大小如圖所示:
在這裡插入圖片描述
如果我們要清空當前資料庫的key資訊,可以通過
flushdb清除當前庫或者通過flushall清除所有的資料庫內容

2、redis是單執行緒的,是基於記憶體操作的。瓶頸是機器記憶體和網路頻寬。(redis6.0以上是可以開啟多執行緒的)

Redis的五大資料型別

它支援多種型別的資料結構,如字串(strings)雜湊(hashes)列表(lists)集合(sets)有序集合(sorted sets) 與範圍查詢, bitmapshyperloglogs地理空間(geospatial) 索引半徑查詢。Redis 內建了 複製(replication),LUA指令碼(Lua scripting),LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁碟持久化(persistence),並通過 Redis哨兵(Sentinel)和自動 分割槽(Cluster)提供高可用性(high availability)。

Redis-key

在這裡插入圖片描述

String型別

append key value
往key對應的字串裡面追加字串。如果當前key不存在則相當於set key value
strlen key
可以檢視當前key的字串長度。
incr key
相當於i++的操作,可以用於網頁瀏覽量的使用
decr key
相當於i–
incrby key value(增長量)
一次增加多少增長量
decrby key value(減少量)
一次減少多少的減少量
getrange key start(起始位置) end(結束位置)
獲取字串範圍裡面的值,例如我有個字串key名為name,value值為"hello,world",getrange name 0 3,就是擷取當前字串0號索引到3號索引的字元,輸出的結果是hell。
getrange key start -1表示的是獲取全部字串,同get key作用
setrange key start(起始索引位置) value(要替換的字串)
替換指定位置的字串
在這裡插入圖片描述
setex key outtime(過期時間) value(字串)
設定一個存活時間為outtime的key鍵值對。
setnx key value
不存在設定(常用於分散式鎖),如果不存在則建立,存在的話就建立失敗。
在這裡插入圖片描述
mset key1 value1 key2 value2 ……
批量設定
mget key1 key2 key 3……
批量獲取
在這裡插入圖片描述
開發中常用的String存物件 寫法如下圖所示:
在這裡插入圖片描述
getset key
先get然後再set
在這裡插入圖片描述
其中value除了可以是字串,也還可以是數字。

List型別

在redis裡面,我們可以把list變成棧、佇列、阻塞佇列。命令前面加L表示是List型別,R是特殊的List型別
Lpush list從左邊插入佇列
Rpush list從右邊插入佇列
在這裡插入圖片描述
具體的執行流程:
在這裡插入圖片描述
Lpop list
從左邊移除第一個元素
Rpop list
從右邊移除第一個元素
在這裡插入圖片描述
Lindex根據下標取出對應的元素
在這裡插入圖片描述
Llen
返回List長度
在這裡插入圖片描述
Lrem
移除指定的個數的value,精確匹配
在這裡插入圖片描述
trim list start end修剪,通過下表擷取指定長度,保留想要的元素
在這裡插入圖片描述
rpoplpush
移除list最後一個元素,加入新的list集合中
在這裡插入圖片描述
lset
根據指定下標的值更新為另一個值,相當於update操作
在這裡插入圖片描述
linsert
插入操作,將某一個具體的value插入到某個元素前面或者後面
在這裡插入圖片描述
小結:

⚫ list其實是一個連結串列,可以通過linsert在某個具體元素的前面或後面插入,也可以通過lpush,rpush在首或者尾插入元素。
⚫ 可靈活變換,Lpush,Rpop就成了訊息佇列。Lpush,Lpop就成了

Set型別

sadd
往set集合裡面新增值
smembers
檢視set集合所有的值
sismember
判斷該元素是否在set集合裡
在這裡插入圖片描述
scard set
獲取集合中元素的個數
在這裡插入圖片描述

srem
移除集合具體元素
在這裡插入圖片描述
srandmember
隨機獲取set集合中的一個元素。可以用於隨機獲取

spop
隨機刪除集合的元素

smove set1 set2(目標集合) key
移動一個指定的元素到另外一個集合
在這裡插入圖片描述

sdiff set1 set2
以set1為基準比較set1和set2,找出set1差集。

sinter set1 set2
交集,找出set1,set2並集的部分

sunion set1 set2
並集
在這裡插入圖片描述

Hash型別

Map集合,村的是key—value的形式,相當於key value(key,value>。
hset key key,value
在這裡插入圖片描述
hdel key key
刪除某一個key的某一個具體欄位
在這裡插入圖片描述
hlen
獲取雜湊表字段數量

hexists
判斷hash中指定欄位是否存在
在這裡插入圖片描述
hkeys key
只獲取所有欄位
hvals key
只獲取所有值
在這裡插入圖片描述
incr

decr

在這裡插入圖片描述

Zset有序集合

zadd key source value
新增操作,其中source是分數,可以理解為權值,主要用於排序在這裡插入圖片描述
zrangebyscore key min max
排序
在這裡插入圖片描述

zrem key value
移除元素
在這裡插入圖片描述
zcard key
檢視集合元素個數
在這裡插入圖片描述

zcount
檢視區間內成員個數
在這裡插入圖片描述

小結:
具體應用,zset可以用於排行榜實時熱搜的實現。
具體的使用和set無異,差別是多了一個權重,一個scores分數而已。

三大特殊型別

Geospatial地理位置

Geoadd
新增地理位置
在這裡插入圖片描述
getpos
獲取指定城市的經度緯度,獲得當前定位。
在這裡插入圖片描述
geodist
返回兩個座標之間的距離。距離單位有m米,km千米,mi英里,ft英尺
在這裡插入圖片描述
georadius
以給定的經緯度為中心,查詢某一半徑中的具體元素
在這裡插入圖片描述
在這裡插入圖片描述
GEORADIUSBYMEMBER
找出指定元素周圍的元素
在這裡插入圖片描述

小結:
Geo的底層使用原理其實是zset,因此我們要刪除某些元素,我們可以通過zrem移除:
在這裡插入圖片描述

Hyperloglog基數統計

常用於頁面瀏覽量統計
在這裡插入圖片描述

Bitmaps

非0即1,操作二進位制位來進行儲存。
在這裡插入圖片描述

Redis的基本事務操作

Redis單條命令是保證原子性的,但事務不保證原子性,沒有隔離級別的概念。Redis事務的本質其實就是一組指令的集合,一個事務中的所有命令都會被序列化,按順序執行。

開啟事務:
命令入隊:
執行事務:(注意,執行完事務之後,當前事務就已經結束了,如果還要開啟事務,還要重新輸入multi命令)
在這裡插入圖片描述
放棄事務:
在這裡插入圖片描述
異常事務:
編譯時異常,所有的程式碼都不會被執行。
在這裡插入圖片描述
執行時異常:
錯誤的指令不會執行,不會影響其他指令的正常執行。
在這裡插入圖片描述

Redis實現樂觀鎖

通過watch監視器監視,這裡的watch其實就相當於上鎖。具體用法:watch key
正常執行的情況:
在這裡插入圖片描述
異常操作
在這裡插入圖片描述

如何解決?
如果發現事務執行失敗,就先通過unwatch解鎖,然後再通過watch加鎖。檢查版本看看是否發生了修改,再進行execute。

Jedis

連線遠端伺服器

是Java來操作redis的中介軟體,通過Jedis可以對redis進行操作。具體操作步驟如下:
第一步、引入相關測試Jar包

<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--匯入fastJson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
    </dependencies>

第二步、編寫測試用例
這裡由於我使用的是遠端伺服器進行測試,因此這裡的ip寫各自的ip即可,如果是安裝在本地的伺服器,可以直接使用127.0.0.1進行測試。

public class testPing {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("your ip",6379);
        System.out.println(jedis.ping());
    }
}

如果使用的遠端伺服器,執行到這裡,可能又會報錯,會顯示
Failed connecting to host IP 6379
提示報錯我們的訪問被拒絕了,其實很簡單改。

首先我們得在阿里雲伺服器安全組,開放redis6379的埠,如圖所示:
在這裡插入圖片描述
第二步,我們得修改相對應的redis啟動配置檔案,具體要修改的地方有兩個,第一個是將bind 127.0.0.1進行註釋,允許所有IP進行訪問,或者將其修改為0.0.0.0。第二個是將保護模式關閉,將protected-mode no設定為no。
第三步,將防火牆開啟,允許6379訪問,由於我使用的是寶塔安裝,因此我管理對應的防火牆埠非常方便,只需要手動新增放行即可,如圖所示:
在這裡插入圖片描述
如果不是使用寶塔安裝的朋友,可以參考這篇文章:

最後,我們在客戶端進行連線,如果響應為PONG,則連線成功啦。
在這裡插入圖片描述
但是為了安全,我們最好還是為我們的redis設定一個密碼,具體的設定流程可以參考這篇文章:

具體的操作API同上文講的五大基本型別無異,無非是通過jedis操作罷了,下面展示測試結果:
在這裡插入圖片描述
在這裡插入圖片描述

事務操作

public class testTX {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("Your IP",your port);
        jedis.flushDB();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username","redis");
        jsonObject.put("password","123");

        //開啟事務
        Transaction multi = jedis.multi();
        String result = jsonObject.toJSONString();
        jedis.watch(result);//加鎖以確定result沒被修改
        try {
            multi.set("key1",result);
            multi.set("key2",result);
            multi.exec();//執行事務
        } catch (Exception e) {
            multi.discard();//放棄事務
            e.printStackTrace();
        }finally {
            System.out.println(jedis.get("key1"));
            System.out.println(jedis.get("key2"));
            jedis.close();//關閉客戶端
        }


    }

}

Redis整合SpringBoot

首先說明,在springboot2.x以後,我們所匯入的springboot-redis整合包,他採用的不再是jedis操作redis,而使用的是lettuce操作redis。這樣做的目的是因為jedis採用的是直連,多個執行緒操作是不安全的,如果要避免不安全,得使用jedis pool執行緒池。而採用lettuce的話,它是用netty實現的,例項可以在多執行緒中共享,不存線上程不安全的情況。

整合過程

整合步驟,通過springboot腳手架,建立一個基本專案。
在這裡插入圖片描述
建立完專案後,因為使用的是springboot整合的redis,springboot幫我們整合了redis的配置檔案,但是如果我們想自己配置,但是又不知道有什麼可以配置,可以自己去尋找相關的配置檔案。如下所示
在這裡插入圖片描述
在這裡插入圖片描述
通過ctrl+滑鼠左鍵,點選進入該配置檔案
在這裡插入圖片描述
我們就找到我們的redis配置檔案啦

原始碼分析:

@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")//我們可以自定義一個叫redisTemplate的類來替換這個類,使這個類失效,因為這個類很多都沒有設定,預設序列化格式是jdk序列化
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		//兩個泛型都是obj,obj形式,後面得強轉為str,obj形式
		//預設redisTemplate沒有過多設定,redis物件都需要序列化
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

整合測試

@SpringBootTest
class RedisSpringbootApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        //opsFor  操作不同資料型別
        redisTemplate.opsForValue().set("key1","test");
        System.out.println(redisTemplate.opsForValue().get("key1"));

        //操作資料庫,獲取redis連線物件
//        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//        connection.flushDb();
//        connection.flushAll();
    }
}

在這裡插入圖片描述

自定義RedisTemplate

前面說到我們的RedisTemplate預設配置其實有很多都是沒有配置的,包括我們的序列化設定,如果使用的是預設的序列化配置,我們通過redis的keys *操作,會看到已經被轉義了的value值,如上一步測試操作裡,我set的value明明是test,但是我在redis伺服器get的值如圖所示:
在這裡插入圖片描述
所以,我們要配置一個自己的配置類。

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate1(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //設定連線方式為預設的lettuce
        template.setConnectionFactory(redisConnectionFactory);
        //所有的object物件都要經過該json序列化
        Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

        //對序列化物件進行轉義,確保不出現諸如\xac\xed\x00\x05t\x00\這種格式的情況
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        objectJackson2JsonRedisSerializer.setObjectMapper(om);

        //String字串型別的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        /**
         * 此處是設定各資料型別key的序列化格式
         * */
        //key採用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key採用String序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //value序列化採用的是jackson
        template.setValueSerializer(objectJackson2JsonRedisSerializer);
        //hash的value採用的是jackson
        template.setHashValueSerializer(objectJackson2JsonRedisSerializer);

        template.afterPropertiesSet();

        return template;
    }

}

測試:
POJO類:

@Component
@Data
@NoArgsConstructor
@AllArgsConstructor
/**
 * 序列化物件,不然的話在通過redisTemplate傳物件的時候傳不了
 * */
public class user implements Serializable {

    private String name;
    private String password;

}

測試類:

@SpringBootTest
class RedisSpringbootApplicationTests {

    @Autowired
    @Qualifier("redisTemplate1")
    private RedisTemplate redisTemplate;
    
    @Test
    void test(){
        user user = new user("learn", "good");
        redisTemplate.opsForValue().set("user",user);
        System.out.println(redisTemplate.opsForValue().get("user"));

    }
}

Redis配置檔案詳解

持久化的RDB操作

因為redis是基於記憶體操作的,斷電即失,因此我們需要將相關的資料持久化操作。 Redis會單獨建立( fork )-個子程序來進行持久化
,會先將資料寫入到一個臨時檔案中,待持久化過程都結束了,再用這個臨時檔案替換上次持久化好的檔案。整個過程中,主程序是不進行任何I0操作的。這就確保了極高的效能。如果需要進行大規模資料的恢復,且對於資料恢復的完整性不是非常敏感,那RDB方式要比A0F方式更加的高效。RDB的缺點是最後一次持久化後的資料可能丟失。
我們預設的就是RDB , -般情況下不需要修改這個配置!rdb儲存的檔案是dump.rdb都是在我們的配置檔案中快照中進行配置的!
在這裡插入圖片描述
我們可以去定製自己的儲存規則,在redis.conf檔案裡面修改即可,如下圖所示。
在這裡插入圖片描述
預設情況下,有三種情況會觸發我們的RDB操作,第一個是save規則,第二個是flushAll操作,第三個是exit退出redis。
那麼,我們如何恢復rdb檔案呢?其實只需要放到redis.conf的啟動目錄下就可以了,即bin目錄下即可。

持久化的AOF操作

一個檔案將我們所有的操作記錄下來,恢復的時候就將該檔案重新執行一遍。預設是不開啟的,需要手動開啟。
在這裡插入圖片描述
修改策略
在這裡插入圖片描述

Redis釋出訂閱

訂閱端

127.0.0.1:6379> subscribe jieshouduan //訂閱一個訊息的接收端
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "jieshouduan"
3) (integer) 1
//等待讀取推送的資訊
1) "message"//訊息
2) "jieshouduan"//哪一個頻道的訊息
3) "nihao"//具體訊息
1) "message"
2) "jieshouduan"
3) "hello,redis"

傳送端

127.0.0.1:6379> publish jieshouduan "nihao"//傳送端需要指定具體的接收端名稱,後面接的具體訊息
(integer) 1
127.0.0.1:6379> publish jieshouduan "hello,redis"
(integer) 1

在這裡插入圖片描述

Redis主從複製

主從複製,是指將一臺Redis伺服器的資料 ,複製到其他的Redis伺服器。前者稱為主節點(master/leader) ,後者稱為從節點(slave/follower);資料的複製是單向的,只能由主節點到從節點。Master以寫為主, Slave 以讀為主。預設情況下,每臺Redis伺服器都是主節點;且一個主節點可以有多個從節點(或沒有從節點),但一個從節點只能有一個主節點。
redis的主要作用:
在這裡插入圖片描述

環境配置

檢視當前庫資訊:

127.0.0.1:6379> info replication
# Replication
role:master//主機
connected_slaves:0//從機
master_replid:1b577a2810ea61d1f05cbabdaadc18e804c920c9
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

要實現主從複製,主要有以下幾個步驟:
第一步:複製conf檔案
在這裡插入圖片描述
第二步,依次修改每個config的檔案內容,主要修改的有如下幾個:
1、埠
2、pid名字
3、log檔名字
4、dump.rdb名字

第三步,通過redids-server啟動服務,檢視程序,如果啟動了三個程序,則配置成功

在這裡插入圖片描述

一主二從

預設情況,每臺Redis都是主節點,一般情況下只用配置從機就可以了。一主(6379),二從(6380,6381),從機通過SLAVEOF host port即可。通過info replication可以檢視是否配置成功。需要注意的是,如果要配置的主機是有密碼認證的,需要在從機的配置檔案中修改masterauth 主機密碼。

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=28,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=28,lag=0
master_replid:12c74a12389a3f02b53582ae27dc655293848366
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
127.0.0.1:6379> 

但是這種通過命令配置的主從機,只是暫時的,真實的情況我們要配置的資訊其實應該是永久的。需要在配置檔案的REPLICATION裡面配置
在這裡插入圖片描述
其中,主機的資訊,從機中可以儲存。主機只管寫,從機只管讀。主機斷開連線,從機依舊執行,但是從機依然只能讀操作。主機回來了,依然可寫,從機依然能讀到寫的資訊。如果是通過命令SLAVEOF配置的主從機,是暫時的,從機斷開重連就又是主機。
在這裡插入圖片描述
通過手動命令,當主機宕機了,從機可以通過命令SLAVEOF NO ONE自己升級為主機,其他節點可以手動重連到這個主機。但是這個時候如果主機重連,升級的主機並不會自動變為從機,還是得手動配置。

哨兵模式

其實就是手動版的升級自動版切換。哨兵模式能夠後臺自動監控主機是否故障,如果故障了則通過投票數自動將從庫變為主庫。哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的程序,作為程序,它會獨立執行。其原理是哨兵通過傳送命令,等待Redis伺服器響應.從而監控執行的多個Redis例項。
在這裡插入圖片描述
當然,一個哨兵也可能會出現’‘死亡’'的情況,因此,一般的情況下,我們的哨兵也是會有多個
在這裡插入圖片描述
假設主伺服器宕機,哨兵1先檢測到這個結果,系統並不會馬上進行failover過程,僅僅是哨兵1主觀的認為主伺服器不可用,這個現象稱為主觀下線。當後面的哨兵也檢測到主伺服器不可用,並且數量達到一定值時,那麼哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行failover[故障轉移]操作。切換成功後,就會通過釋出訂閱模式,讓各個哨兵把自己監控的從伺服器實現切換主機,這個過程稱為客觀下線。

程式碼實現:
第一步、配置哨兵配置檔案sentinel.conf,名字不能寫錯。如果主機配置了密碼的,此處還要配置多一個密碼資訊。

//sentinel monitor 被監控的名稱 IP 埠 1代表主機掛了,哨兵投票選舉主機
sentinel monitor myredis 127.0.0.1 6379 1
sentinel auth-pass master(這裡的名字是上面這一行你自定義的名字,例如我的名字是myredis) yourpassword

第二步、啟動哨兵

[root@username bin]# redis-sentinel yourconfig/sentinel.conf

出現如下介面則配置成功:

11049:X 09 Dec 2020 16:18:58.155 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
11049:X 09 Dec 2020 16:18:58.155 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=11049, just started
11049:X 09 Dec 2020 16:18:58.155 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 11049
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

11049:X 09 Dec 2020 16:18:58.156 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
11049:X 09 Dec 2020 16:18:58.156 # Sentinel ID is xxxxxxxxxxxxxxxxxxx(我省略了)
11049:X 09 Dec 2020 16:18:58.156 # +monitor master myredis 127.0.0.1 6379 quorum 1
11049:X 09 Dec 2020 16:18:58.156 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379//我的從節點
11049:X 09 Dec 2020 16:18:58.160 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379//我的從節點

如果這個時候主機宕機了,會自動重新選擇一個主機,但是並不是說宕機了就會馬上被看到,他需要一定的時間。此時如果主機重連的話,就會變成從機。

在這裡插入圖片描述

快取穿透和雪崩

快取穿透(查不到)

什麼是快取穿透?

快取穿透的概念很簡單,使用者想要查詢一、一個數據,發現redis記憶體資料庫沒有,也就是快取沒有命中,於是向持久層資料庫查詢。發現也沒有,於是本次查詢失敗。當用戶很多的時候,快取都沒有命中(秒殺! ) , 於是都去請求了持久層資料庫。這會給持久層資料庫造成很大的壓力,這時候就相當於出現了快取穿透。

解決?

1、布隆過濾器
對所有可能查詢的引數以hash的形式儲存,在控制層校驗,不符合就丟棄在這裡插入圖片描述
2、快取空物件
當儲存層不命中的時候,即使返回的空物件也會被儲存起來,同時設定一個過期時間,之後哦再訪問這個資料就會從快取中獲取。
在這裡插入圖片描述

快取擊穿(量太大,快取過期,一個key)

1、什麼是快取擊穿
這裡需要注意和快取擊穿的區別,快取擊穿,是指一個key非常熱點,在不停的扛著大併發,大併發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的大併發就穿破快取,直接請求資料庫,就像在一個屏障上鑿開了一個洞。當某個key在過期的瞬間,有大量的請求併發訪問,這類資料一般是熱點資料,由於快取過期,會同時訪問資料庫來查詢最新資料,並且回寫快取,會導使資料庫瞬間壓力過大。
2、解決方案
設定熱點資料永不過期
從快取層面來看,沒有設定過期時間,所以不會出現熱點key過期後產生的問題。
加互斥鎖
分散式鎖:使用分散式鎖,保證對於每個key同時只有一個執行緒去查詢後端服務 ,其他執行緒沒有獲得分散式鎖的許可權,因此只需要等待即可。這種方式將高併發的壓力轉移到了分散式鎖,因此對分散式鎖的考驗很大。這個時候只需要等待回寫快取key即可。

快取雪崩(大量key)

1、 什麼是快取雪崩?
快取雪崩,是指在某個時間段,快取集中過期失效。Redis宕機!產生雪崩的原因之一,比如在寫本文的時候,馬上就要到雙十二零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了快取,假設快取一個小時。 那麼到了凌晨一點鐘的時候 ,這批商品的快取就都過期了。而對這批商品的訪問查詢,都落到了資料庫上,對於資料庫而言,就會產生週期性的壓力波峰。於是所有的請求都會達到儲存層,儲存層的呼叫量會暴增,造成儲存層也會掛掉的情況。
2、解決方案
redis叢集
搭建redis叢集,提高可用性。
限流降級
在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。
資料預熱
資料加熱的含義就是在正式部署之前,我先把可能的資料先預先訪問一遍,這樣部分可能大量訪問的資料就會載入到快取中。在即將發生大併發訪問前手動觸發載入快取不同的key ,設定不同的過期時間,讓快取失效的時間點儘量均勻。