主頁 > 資料庫 > Redis學習

Redis學習

2022-07-19 08:31:32 資料庫

Redis

image-20211104130443874

因為沒有指定組態檔

需配置

redis-server redis.windows.conf

之后自動啟動

測驗性能

redis-benchmark -p 6379 -c 100 -n 10000

image-20211104140217226

image-20211104140647780

基礎概念:

image-20211104141011197

image-20211104141230255

清空當前資料庫:flushdb

清空全部資料庫:flushall

redis是單執行緒的

redis的瓶頸是機器的記憶體和網路的帶寬,用單執行緒既然可以實作,就用單執行緒了

為什么單執行緒還這么快呢

redis是將所有的資料全部放在記憶體中,所以說用單執行緒操作效率最高,多執行緒(cpu背景關系會切換:耗時的操作),對于記憶體系統來說,如果沒有背景關系切換效率就是最高的!多次讀寫都是在一個cpu上,在記憶體情況下,這個就是最佳的選擇,

底層資料結構(參考

簡單動態字串

img

  一般來說,SDS 除了保存資料庫中的字串值以外,SDS 還可以作為緩沖區(buffer):包括 AOF 模塊中的AOF緩沖區以及客戶端狀態中的輸入緩沖區,

鏈表

 Redis鏈表特性:

  ①、雙端:鏈表具有前置節點和后置節點的參考,獲取這兩個節點時間復雜度都為O(1),

  ②、無環:表頭節點的 prev 指標和表尾節點的 next 指標都指向 NULL,對鏈表的訪問都是以 NULL 結束,  

  ③、帶鏈表長度計數器:通過 len 屬性獲取鏈表長度的時間復雜度為 O(1),

  ④、多型:鏈表節點使用 void* 指標來保存節點值,可以保存各種不同型別的值

字典

Redis 的字典使用哈希表作為底層實作、

key 用來保存鍵,val 屬性用來保存值,值可以是一個指標,也可以是uint64_t整數,也可以是int64_t整數,

  注意這里還有一個指向下一個哈希表節點的指標,我們知道哈希表最大的問題是存在哈希沖突,如何解決哈希沖突,有開放地址法和鏈地址法,這里采用的便是鏈地址法,通過next這個指標可以將多個哈希值相同的鍵值對連接在一起,用來解決哈希沖突,

跳表

跳躍表(skiplist)是一種有序資料結構,它通過在每個節點中維持多個指向其它節點的指標,從而達到快速訪問節點的目的,具有如下性質:

  1、由很多層結構組成;

  2、每一層都是一個有序的鏈表,排列順序為由高層到底層,都至少包含兩個鏈表節點,分別是前面的head節點和后面的nil節點;

  3、最底層的鏈表包含了所有的元素;

  4、如果一個元素出現在某一層的鏈表中,那么在該層之下的鏈表也全都會出現(上一層的元素是當前層的元素的子集);

  5、鏈表中的每個節點都包含兩個指標,一個指向同一層的下一個鏈表節點,另一個指向下一層的同一個鏈表節點;

? ①、搜索:從最高層的鏈表節點開始,如果比當前節點要大和比當前層的下一個節點要小,那么則往下找,也就是和當前層的下一層的節點的下一個節點進行比較,以此類推,一直找到最底層的最后一個節點,如果找到則回傳,反之則回傳空,

  ②、插入:首先確定插入的層數,有一種方法是假設拋一枚硬幣,如果是正面就累加,直到遇見反面為止,最后記錄正面的次數作為插入的層數,當確定插入的層數k后,則需要將新元素插入到從底層到k層,

  ③、洗掉:在各個層中找到包含指定值的節點,然后將節點從鏈表中洗掉即可,如果洗掉以后只剩下頭尾兩個節點,則洗掉這一層,

五大資料型別的應用場景

對于string 資料型別,因為string 型別是二進制安全的,可以用來存放圖片,視頻等內容,另外由于Redis的高性能讀寫功能,而string型別的value也可以是數字,可以用作計數器(INCR,DECR),比如分布式環境中統計系統的在線人數,秒殺等,

對于 hash 資料型別,value 存放的是鍵值對,比如可以做單點登錄存放用戶資訊,

對于 list 資料型別,可以實作簡單的訊息佇列,另外可以利用lrange命令,做基于redis的分頁功能

對于 set 資料型別,由于底層是字典實作的,查找元素特別快,另外set 資料型別不允許重復,利用這兩個特性我們可以進行全域去重,比如在用戶注冊模塊,判斷用戶名是否注冊;另外就是利用交集、并集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能,

對于 zset 資料型別,有序的集合,可以做范圍查找,排行榜應用,取 TOP N 操作等

五大資料型別

redis-key

#移除name key
move name 1

image-20211104143325041

#設定過期時間
expire name 10 

image-20211104143636111

查看剩余過期時間:ttl name;

#查看鍵的型別
type name

image-20211104143922548

String

image-20211104144412464

如果append后的鍵不存在就創建一個,相當于set

image-20211104145142401

獲取一部分值

image-20211104145422840

獲取全部的值

image-20211104145501629

替換值

image-20211104145749240

setex 設定過期時間

setnx 如果沒有這個鍵就設定值成功,如果已存在這個鍵就設定不成功(在分布式鎖中常應用 )

image-20211104150144398

批量設定鍵和值,批量獲取值

image-20211104150700175

msetnx 具有原子性

設定物件,以json字串的形式

image-20211104151319002

getset

image-20211104151448797

List

在redis中,list可以被我們玩成堆疊,佇列,阻塞佇列

lpush 放進串列資料

lrange 取出指定位置的資料,可以看出下標是倒著來的,

image-20211104152112654

說明rpush把值放在了佇列的最后面

image-20211104152548954

從串列中移除值,可以分為移除左邊的和右邊的

image-20211104153013118

通過下標獲取值

image-20211104153153183

獲取串列長度

llen

移除指定的值,可指定數量

image-20211104153655790

通過下標截取指定的長度

image-20211104154058106

移除串列的最后一個元素,將他移動到新串列中

image-20211104154308321

更新指定位置的值

image-20211104154722495

image-20211104155347613

set

image-20211104155948255

image-20211104160159057

image-20211104160308656

image-20211104160500757

image-20211104161114018

hash

Map集合,key-map,那時候這個值是一個map集合,本質和String型別沒有太大區別,還是一個簡單的key-vlaue

image-20211104162116587

獲取hash表的內容長度

image-20211104162829439

獲取所有的field和所有的值

image-20211104163226493

hash更適合于物件的存盤

Zset(有序集合)

排列

image-20211104170955039

顯示工資小于2000的工資排列

image-20211104171308530

移除指定元素

image-20211104172219379

獲取集合中的個數

zcard salary

獲取指定區間的成員數量

image-20211104173454977

總結:

image-20211104175033465

三種特殊資料型別

Geospatial(地理位置)

geoadd 添加地理位置

geoadd key longitude latitude member [longitude latitude member ...]

geopos獲得地理位置詳細資訊

geopos key member [member ...]

geodist獲得兩個地點之間的距離,可在后面追加獲得結果的單位 km m

geodist key member1 member2 [unit]

georadius獲得以某一點經緯度為圓心,一定距離為半徑之內的元素

georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC

georadiusbymember獲得某一成員為圓心,一定距離為半徑之內的元素

geo底層的實作原理是zset,可以使用zset命令來操作geo

hyperloglog

統計基數

可以用作網站的UV(一個人訪問網站多次,但是還是算作一個人)

傳統的方式是用set,如果存盤量太大的話就比較麻煩

測驗

image-20211105221008371

bitmaps

位存盤

位圖,是資料結構,都是操作二進制為來進行操作,只有0和1兩個狀態

統計一周的打卡情況

image-20211105221855488

查看某一天的打卡情況

image-20211105222028892

查看打卡了幾天

127.0.0.1:6379> bitcount si
(integer) 2

事務

本質:一組命令的集合,所有命令都會被序列化,執行程序中,按照順序執行

redis單挑命令保存原子性,但是事務不保證原子性,沒有隔離級別的概念

所有命令在事務中,并不被直接執行,只有發起執行命令的時候才被執行

  1. 開啟事務
  2. 命令入隊
  3. 執行事務

正常執行事務

127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec#執行事務
1) OK
2) OK
3) "v2"
4) OK
127.0.0.1:6379>

放棄事務

discard

編譯型例外(代碼有問題),事務中所有命令都不會被執行

127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.#所有事務不會被運行
127.0.0.1:6379>

運行時例外(1/0),其他命令正常執行,錯誤命令拋出例外

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1#字串不會加1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range#屬于運行時例外
2) "v1" #正常執行
127.0.0.1:6379>

監控

樂觀鎖

獲取version,比較version

監視:

watch key [key …]

執行之前,另外一個執行緒如果修改了我們的值,事務就會執行失敗,就要放棄監視,然后重新監視

放棄監視

unwatch key

 

Jedis

配置依賴

<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
      
    </dependencies>

創建連接進行測驗

Jedis jedis=new Jedis("127.0.0.1", 6379);
System.out.println(jedis.ping());

springboot整合

底層為lettuce:采用netty,實體可以在多個執行緒中共享,不存在執行緒不安全的情況,NIO模式

jeids采用直連,多執行緒不安全,如想避免不安全,就使用jedis pool連接池,BIO模式

操作各種基本型別

image-20211106154640957

獲得鏈接,操作資料庫

image-20211106154840090

序列化

放入物件需序列化

@Configuration
public class RedisConfig {

    //撰寫自己的redisTemplate
    @Bean
    @SuppressWarnings("all")

    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {

        RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //String的序列化
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();

        //key采用String的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        //Hash的序列化方式也采用String的方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        //value序列化方式采用jackson
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

———————–固定配置模板

Redis.conf詳解

image-20211106221030918

對大小寫不敏感

包含

image-20211106221148896

可包含多個組態檔

網路

bind 127.0.0.1
protected-mode yes #保護模式
port 6379 #默認埠

系結的IP

通用

# NOT SUPPORTED ON WINDOWS daemonize no 
#window端不支持此配置,配置此項須在linux端
daemonize yes #以守護行程的方式運行,默認是no,我們需要自己開啟為yes

# NOT SUPPORTED ON WINDOWS pidfile /var/run/redis.pid
#如果指定為后臺方式運行,則需指定pid檔案
pidfile /var/run/redis.pid

#日志級別
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice


logfile "" #日志檔案位置
databases 16 #默認資料庫數量

快照

持久化:在規定時間內,執行了多少次操作則會持久化到檔案.rdb .aof

reids是記憶體資料庫,如果沒有持久化,那么資料斷電即失,

save 900 1 #如果900s內,有一個key進行了修改,我們將進行持久化操作,以下皆同
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes#持久化出錯,redis是否還繼續作業
rdbcompression yes#是否壓縮rdb檔案
rdbchecksum yes #保存rdb檔案的時候,進行錯誤的檢查校驗
dir ./ #rdb檔案的保存目錄

安全

127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config set requirepass 1234 #設定密碼
OK
127.0.0.1:6379> config get requirepass
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 1234 #登錄
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "1234"
127.0.0.1:6379>

image-20211107174514097

客戶端連接相關

# maxclients 10000a 最大客戶端數量
# maxmemory <bytes> 最大記憶體限制
# maxmemory-policy noeviction 記憶體到達極限值的處理策略

maxmemory-policy 六種方式

1、volatile-lru:只對設定了過期時間的key進行LRU(默認值)

2、allkeys-lru : 洗掉lru演算法的key

3、volatile-random:隨機洗掉即將過期key

4、allkeys-random:隨機洗掉

5、volatile-ttl : 洗掉即將過期的

6、noeviction : 永不過期,回傳錯誤

Redis持久化

RDB:Redis Databases

什么是RDB


在指定時間間隔后,將記憶體中的資料集快照寫入資料庫 (復制媒介);在恢復時候,直接讀取快照檔案,進行資料的恢復 ;

在這里插入圖片描述

默認情況下, Redis 將資料庫快照保存在名字為 dump.rdb的二進制檔案中,檔案名可以在組態檔中進行自定義,

三種觸發方式

1656990982238

還有一種就是自動觸發

作業原理


在進行 RDB 的時候,**redis** 的主執行緒是不會做 io 操作的,主執行緒會 fork 一個子執行緒來完成該操作;

  1. Redis 呼叫forks,同時擁有父行程和子行程,
  2. 子行程將資料集寫入到一個臨時 RDB 檔案中,
  3. 當子行程完成對新 RDB 檔案的寫入時,Redis 用新 RDB 檔案替換原來的 RDB 檔案,并洗掉舊的 RDB 檔案,

這種作業方式使得 Redis 可以從寫時復制(copy-on-write)機制中獲益(因為是使用子行程進行寫操作,而父行程依然可以接收來自客戶端的請求,)

在這里插入圖片描述

觸發機制


  1. save的規則滿足的情況下,會自動觸發rdb原則
  2. 執行flushall命令,也會觸發我們的rdb原則
  3. 退出redis,也會自動產生rdb檔案

優缺點

優點:

  1. 適合大規模的資料恢復
  2. 對資料的完整性要求不高

缺點:

耗時,耗性能

  1. 需要一定的時間間隔進行操作,如果redis意外宕機了,這個最后一次修改的資料就沒有了,由此引入AOF,
  2. fork行程的時候,會占用一定的內容空間,

AOF

Append Only File

將我們所有的命令都記錄下來,history,恢復的時候就把這個檔案全部再執行一遍

以日志的形式來記錄每個寫的操作,將Redis執行過的所有指令記錄下來(讀操作不記錄),只許追加檔案但不可以改寫檔案,redis啟動之扯訓讀取該檔案重新構建資料,換言之,redis重啟的話就根據日志檔案的內容將寫指令從前到后執行一次以完成資料的恢復作業,

三種策略

always:每條命令都刷盤

everysec:每一秒刷一次

no:作業系統決定

什么是AOF

快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那么服務器將丟失最近寫入、以及未保存到快照中的那些資料, 從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化,

如果要使用AOF,需要修改組態檔:

在這里插入圖片描述

appendonly no yes則表示啟用AOF

默認是不開啟的,我們需要手動配置,然后重啟redis,就可以生效了!

如果這個aof檔案有錯位,這時候redis是啟動不起來的,我需要修改這個aof檔案

redis給我們提供了一個工具redis-check-aof --fix

優點和缺點

123456appendonly yes  # 默認是不開啟aof模式的,默認是使用rdb方式持久化的,在大部分的情況下,rdb完全夠用
appendfilename "appendonly.aof"

# appendfsync always # 每次修改都會sync 消耗性能
appendfsync everysec # 每秒執行一次 sync 可能會丟失這一秒的資料
# appendfsync no # 不執行 sync ,這時候作業系統自己同步資料,速度最快

優點

  1. 每一次修改都會同步,檔案的完整性會更加好
  2. 每秒同步一次,可能會丟失一秒的資料
  3. 從不同步,效率最高

缺點

  1. 相對于資料檔案來說,aof遠遠大于rdb,修復速度比rdb慢!
  2. Aof運行效率也要比rdb慢,所以我們redis默認的配置就是rdb持久化

AOF重寫

fork出子行程,一個進行重寫,一個把重寫程序中產生的aof記錄寫到buffer中,最后添加到AOF新檔案中,

RDB和AOP選擇

RDB優勢與劣勢

優勢

  • 適合大規模的資料恢復
  • 對資料完整性和一致性要求不高

劣勢

  • 在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改,

  • Fork的時候,記憶體中的資料被克隆了一份,大致2倍的膨脹性能需要考慮

AOF優勢/劣勢

優勢

  • 每次修改同步:appendfsync always同步持久化,每次發生資料變更會被立即記錄到磁盤,性能較差但資料完整性比較好
  • 每秒同步:appendfsync everysec異步操作,每秒記錄,如果一秒內宕機,僅一秒內的資料丟失

劣勢

  • 相同資料集的資料而言aof檔案要遠大于rdb檔案,恢復速度慢于rdb
  • Aof運行效率要慢于rdb,每秒同步策略效率較好,不同步效率和rdb相同

RDB消耗性能大,如果宕機可能丟失最后一次所做的修改,但是檔案小,恢復快

為什么RDB恢復資料集較快

AOF,存放的指令日志,做資料恢復的時候,其實是要回放和執行所有的指令日志,來恢復出來記憶體中的所有資料的;
RDB,就是一份資料檔案,恢復的時候,直接加載到記憶體中即可

1657074702612

如何選擇使用哪種持久化方式?

一般來說, 如果想達到足以媲美 PostgreSQL 的資料安全性, 你應該同時使用兩種持久化功能,

如果你非常關心你的資料, 但仍然可以承受數分鐘以內的資料丟失, 那么你可以只使用 RDB 持久化,

有很多用戶都只使用 AOF 持久化, 但并不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便于進行資料庫備份, 并且 RDB 恢復資料集的速度也要比 AOF 恢復的速度要快,

常見問題

fork

記憶體越大,fork時間越長,所以設定引數maxmemory引數

降低fork頻率,避免不必要的全量復制

1657075584068

AOF追加阻塞

1657075818193

距離上次同步超過兩秒,就阻塞主執行緒,直到同步完成

參考硬碟優化的相關策略

1657076033013

Redis發布訂閱

訂閱

subscribe hongdou
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "hongdou"
3) (integer) 1

發布

127.0.0.1:6379> publish hongdou hahaha
(integer) 1

結果:

1) "message"
2) "hongdou"
3) "hahaha"

原理

每個 Redis 服務器行程都維持著一個表示服務器狀態的 redis.h/redisServer 結構, 結構的 pubsub_channels 屬性是一個字典, 這個字典就用于保存訂閱頻道的資訊,其中,字典的鍵為正在被訂閱的頻道, 而字典的值則是一個鏈表, 鏈表中保存了所有訂閱這個頻道的客戶端,

在這里插入圖片描述

客戶端訂閱,就被鏈接到對應頻道的鏈表的尾部,退訂則就是將客戶端節點從鏈表中移除,

缺點

  1. 如果一個客戶端訂閱了頻道,但自己讀取訊息的速度卻不夠快的話,那么不斷積壓的訊息會使redis輸出緩沖區的體積變得越來越大,這可能使得redis本身的速度變慢,甚至直接崩潰,
  2. 這和資料傳輸可靠性有關,如果在訂閱方斷線,那么他將會丟失所有在短線期間發布者發布的訊息,

應用

  1. 訊息訂閱:公眾號訂閱,微博關注等等(起始更多是使用訊息佇列來進行實作)
  2. 多人在線聊天室,

稍微復雜的場景,我們就會使用訊息中間件MQ處理,

Redis主從復制

概念

主從復制,是指將一臺Redis服務器的資料,復制到其他的Redis服務器,前者稱為主節點(Master/Leader),后者稱為從節點(Slave/Follower), 資料的復制是單向的!只能由主節點復制到從節點(主節點以寫為主、從節點以讀為主),

默認情況下,每臺Redis服務器都是主節點,一個主節點可以有0個或者多個從節點,但每個從節點只能由一個主節點,

作用

  1. 資料冗余:主從復制實作了資料的熱備份,是持久化之外的一種資料冗余的方式,
  2. 故障恢復:當主節點故障時,從節點可以暫時替代主節點提供服務,是一種服務冗余的方式
  3. 負載均衡:在主從復制的基礎上,配合讀寫分離,由主節點進行寫操作,從節點進行讀操作,分擔服務器的負載;尤其是在多讀少寫的場景下,通過多個從節點分擔負載,提高并發量,
  4. 高可用基石:主從復制還是哨兵和集群能夠實施的基礎,

為什么使用集群

  1. 單臺服務器難以負載大量的請求
  2. 單臺服務器故障率高,系統崩壞概率大
  3. 單臺服務器記憶體容量有限,

環境配置

我們在講解組態檔的時候,注意到有一個replication模塊 (見Redis.conf中第8條)

查看當前庫的資訊:info replication

123456789101112127.0.0.1:6379> info replication
# Replication
role:master # 角色
connected_slaves:0 # 從機數量
master_replid:3b54deef5b7b7b7f7dd8acefa23be48879b4fcff
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

既然需要啟動多個服務,就需要多個組態檔,每個組態檔對應修改以下資訊:

  • 埠號

  • pid檔案名

  • 日志檔案名

  • rdb檔案名

注意:window配置方法:

開啟多個埠服務器
1.組態檔
將redis.windows-service.conf復制一份,改名為相應檔案,并更改組態檔中的埠為指定埠,以6380為例

port 6380

2.安裝服務
redis-server –service-install –service-name redis_6380 redis.windows-service-6380.conf
3.啟動服務
redis-server –service-start –service-name redis_6380
4.停止服務
redis-server –service-stop –service-name redis_6380
5.卸載服務
redis-server –service-uninstall –service-name redis_6380

指定埠啟動客戶端:
redis.cli -p 埠號

image-20211108113934528

啟動單機多服務集群:

在這里插入圖片描述

一主二從配置

默認情況下,每臺Redis服務器都是主節點;一般情況下只用配置從機就好了!

認老大!一主(79)二從(80,81)

使用SLAVEOF host port就可以為從機配置主機了,

image-20211108114239188

image-20211108114323436

主機截圖:

image-20211108114407873

使用命令搭建是暫時的,真實開發中應該在從機的組態檔中進行配置,這樣的話是永久的,

image-20211108114911108

規則

從機只能讀,不能寫,主機可讀可寫但是多用于寫,

當主機斷電宕機后,默認情況下從機的角色不會發生變化 ,集群中只是失去了寫操作,當主機恢復以后,又會連接上從機恢復原狀,

當從機斷電宕機后,若不是使用組態檔配置的從機,再次啟動后作為主機是無法獲取之前主機的資料的,若此時重新配置稱為從機,又可以獲取到主機的所有資料,這里就要提到一個同步原理

復制原理

從機成功連接到主機后會發送一個同步命令

主機啟動bgsave,開始生成RDB檔案,同時把期間的寫命令快取在記憶體中,RDB檔案生成后發送給slave,slave會先寫入磁盤,再從磁盤加載到記憶體,接著master將快取中的寫命令發送到slave,slave再進行同步

1657117554315

全量復制:主機生成RDB——-》同時快取寫命令———–》發送給從機,從機清空舊資料加載rdb到記憶體中———》同時基于舊資料版本提供服務

增量復制:每次更新資料同步到從機

過期key處理:主機刪掉,模擬一條del指令發給slave

層層鏈路

主機從機成鏈路式連接

如果主機斷開了連接,我們可以使用SLAVEOF no one讓自己變成主機!其他的節點就可以手動連接到最新的主節點

哨兵模式的全部配置

完整的哨兵模式組態檔 sentinel.conf

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970# Example sentinel.conf
 
# 哨兵sentinel實體運行的埠 默認26379
port 26379
 
# 哨兵sentinel的作業目錄
dir /tmp
 
# 哨兵sentinel監控的redis主節點的 ip port 
# master-name  可以自己命名的主節點名字 只能由字母A-z、數字0-9 、這三個字符".-_"組成,
# quorum 當這些quorum個數sentinel哨兵認為master主節點失聯 那么這時 客觀上認為主節點失聯了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
 
# 當在Redis實體中開啟了requirepass foobared 授權密碼 這樣所有連接Redis實體的客戶端都要提供密碼
# 設定哨兵sentinel 連接主從的密碼 注意必須為主從設定一樣的驗證密碼
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之后 主節點沒有應答哨兵sentinel 此時 哨兵主觀上認為主節點下線 默認30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
 
# 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,
這個數字越小,完成failover所需的時間就越長,
但是如果這個數字越大,就意味著越 多的slave因為replication而不可用,
可以通過將這個值設為 1 來保證每次只有一個slave 處于不能處理命令請求的狀態,
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
 
 
 
# 故障轉移的超時時間 failover-timeout 可以用在以下這些方面: 
#1. 同一個sentinel對同一個master兩次failover之間的間隔時間,
#2. 當一個slave從一個錯誤的master那里同步資料開始計算時間,直到slave被糾正為向正確的master那里同步資料時,
#3.當想要取消一個正在進行的failover所需要的時間,  
#4.當進行failover時,配置所有slaves指向新的master所需的最大時間,不過,即使過了這個超時,slaves依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規則來了
# 默認三分鐘
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置當某一事件發生時所需要執行的腳本,可以通過腳本來通知管理員,例如當系統運行不正常時發郵件通知相關人員,
#對于腳本的運行結果有以下規則:
#若腳本執行后回傳1,那么該腳本稍后將會被再次執行,重復次數目前默認為10
#若腳本執行后回傳2,或者比2更高的一個回傳值,腳本將不會重復執行,
#如果腳本在執行程序中由于收到系統中斷信號被終止了,則同回傳值為1時的行為相同,
#一個腳本的最大執行時間為60s,如果超過這個時間,腳本將會被一個SIGKILL信號終止,之后重新執行,
 
#通知型腳本:當sentinel有任何警告級別的事件發生時(比如說redis實體的主觀失效和客觀失效等等),將會去呼叫這個腳本,
#這時這個腳本應該通過郵件,SMS等方式去通知系統管理員關于系統不正常運行的資訊,呼叫該腳本時,將傳給腳本兩個引數,
#一個是事件的型別,
#一個是事件的描述,
#如果sentinel.conf組態檔中配置了這個腳本路徑,那么必須保證這個腳本存在于這個路徑,并且是可執行的,否則sentinel無法正常啟動成功,
#通知腳本
# sentinel notification-script <master-name> <script-path>
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 客戶端重新配置主節點引數腳本
# 當一個master由于failover而發生改變時,這個腳本將會被呼叫,通知相關的客戶端關于master地址已經發生改變的資訊,
# 以下引數將會在呼叫腳本時傳給腳本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>總是“failover”,
# <role>是“leader”或者“observer”中的一個, 
# 引數 from-ip, from-port, to-ip, to-port是用來和舊的master和新的master(即舊的slave)通信的
# 這個腳本應該是通用的,能被多次呼叫,不是針對性的,
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

快取穿透與雪崩

快取穿透(查不到)

概念

在默認情況下,用戶請求資料時,會先在快取(Redis)中查找,若沒找到即快取未命中,再在資料庫中進行查找,數量少可能問題不大,可是一旦大量的請求資料(例如秒殺場景)快取都沒有命中的話,就會全部轉移到資料庫上,造成資料庫極大的壓力,就有可能導致資料庫崩潰,網路安全中也有人惡意使用這種手段進行攻擊被稱為洪水攻擊,

解決方案

布隆過濾器

對所有可能查詢的引數以Hash的形式存盤,以便快速確定是否存在這個值,在控制層先進行攔截校驗,校驗不通過直接打回,減輕了存盤系統的壓力,

在這里插入圖片描述

快取空物件

一次請求若在快取和資料庫中都沒找到,就在快取中方一個空物件用于處理后續這個請求,

在這里插入圖片描述

這樣做有一個缺陷:存盤空物件也需要空間,大量的空物件會耗費一定的空間,存盤效率并不高,解決這個缺陷的方式就是設定較短過期時間

即使對空值設定了過期時間,還是會存在快取層和存盤層的資料會有一段時間視窗的不一致,這對于需要保持一致性的業務會有影響,

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

概念

相較于快取穿透,快取擊穿的目的性更強,一個存在的key,在快取過期的一刻,同時有大量的請求,這些請求都會擊穿到DB,造成瞬時DB請求量大、壓力驟增,這就是快取被擊穿,只是針對其中某個key的快取不可用而導致擊穿,但是其他的key依然可以使用快取回應,

比如熱搜排行上,一個熱點新聞被同時大量訪問就可能導致快取擊穿,

解決方案

  1. 設定熱點資料永不過期

    這樣就不會出現熱點資料過期的情況,但是當Redis記憶體空間滿的時候也會清理部分資料,而且此種方案會占用空間,一旦熱點資料多了起來,就會占用部分空間,

  2. 加互斥鎖(分布式鎖)

    在訪問key之前,采用SETNX(set if not exists)來設定另一個短期key來鎖住當前key的訪問,訪問結束再洗掉該短期key,保證同時刻只有一個執行緒訪問,這樣對鎖的要求就十分高,

快取雪崩

概念

大量的key設定了相同的過期時間,導致在快取在同一時刻全部失效,造成瞬時DB請求量大、壓力驟增,引起雪崩,

在這里插入圖片描述

解決方案

  • redis高可用

    這個思想的含義是,既然redis有可能掛掉,那我多增設幾臺redis,這樣一臺掛掉之后其他的還可以繼續作業,其實就是搭建的集群

  • 限流降級

    這個解決方案的思想是,在快取失效后,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量,比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待,

  • 資料預熱

    資料加熱的含義就是在正式部署之前,我先把可能的資料先預先訪問一遍,這樣部分可能大量訪問的資料就會加載到快取中,在即將發生大并發訪問前手動觸發加載快取不同的key,設定不同的過期時間,讓快取失效的時間點盡量均勻,

  • 1647835150674

快取一致性

先更新資料庫,在更新快取,先更新快取,再更新資料庫都會有問題

一般使用先更新資料庫再洗掉快取可以解決,因為快取的寫入要快于資料庫的寫入,但是會影響快取的命中率,

那么快取洗掉失敗怎么辦?

  1. 先洗掉快取,再更新資料庫

  2. 此時就引入了延時雙刪:

    洗掉快取
    更新資料庫
    睡眠 需要大于第二個執行緒讀取資料并寫入快取的時間
    洗掉快取

    睡眠時間難以估算,所以還是先更新資料庫再洗掉快取比較好

那么為什么不是更新快取而是洗掉快取呢,就是一個 lazy 計算的思想,不要每次都重新做復雜的計算,不管它會不會用到,而是讓它到需要被使用的時候再重新計算

Redis 過期策略

定期洗掉+惰性洗掉

如果還有大量的過期資料既沒有被用到過,又沒有被定期洗掉掃描到那怎么辦,就引入淘汰策略

淘汰策略

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

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/499683.html

標籤:其他

上一篇:mysql語法使用詳細代碼版

下一篇:位元組跳動資料質量動態探查及相關前端實作

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more