主頁 > 資料庫 > Redis學習筆記(理論+面試)

Redis學習筆記(理論+面試)

2020-10-12 12:08:05 資料庫

Redis

1 簡介

  • 是開源免費、遵守BSD協議、高性能的NOSQLkey-value 資料庫,
  • 是簡單的、高效的、分布式的、基于記憶體單執行緒快取工具,
  • 簡單是Redis的突出特色,簡單可以保證核心功能的穩定和優異,
  • 支持網路、可以持久化、支持資料備份、集群、訊息佇列等高可用功能,
  • 在企業開發中,Redis常被作為分布式快取
    • 熱點資料:常被查詢、不常被修改、洗掉的資料
    • 臨時資料:不必持久化、有失效時間的資料(驗證碼等)

2 特點

2.1 關系型資料庫 VS 非關系型資料庫

(1)關系型

  • 優點
    • 容易理解,二維表比較符合邏輯世界的展示
    • 單一關系模型,可以進行結構化存盤,有完整的約束
    • 正是因為是結構化存盤的,所以可以很方便的使用結構化語言SQL,實作復雜的操作(表關聯JOIN等)
  • 缺點
    • SQL需要決議,效率低
    • 要保證資料一致性,就需要加鎖,并發性能低
    • 結構化存盤雖然方便,但是不靈活,擴展困難,

(2)非關系型

  • 優點
    • 并發性能高,可以處理大量的資料
    • 效率高、速度快
  • 缺點
    • 不能支持復雜的操作(比如JOIN),每次只能執行簡單的命令
    • 沒有完整的約束,事務處理能力差(比如Redis的事務就是偽事務)

2.2 Redis優點

  • 性能高速度快,簡單高效,可以處理萬級的QPS,使用集群后可達百萬級,遠超MySQL(幾千算好的),
  • 資料型別豐富(5個基本資料型別,還有其他的擴展型別,下面介紹)
  • 因為是單執行緒的,所以操作都是原子性的,天生執行緒安全,
  • 雖然是基于記憶體的,但是提供持久化功能,(兩種持久化方式,下面介紹)

2.3 Redis缺點

  • 基于記憶體,所以對記憶體的要求高

3 安裝

還是去搜詳細教程吧,這部分之后有時間再整理,

  • 使用docker安裝
docker pull redis
docker run -d --name redis -p 6379:6379 redis
docker exec -it redis redis-cli
  • 直接壓縮包安裝
1、確保Linux已經安裝gcc
    若沒安裝,則需要在root登錄下、可連接外網狀態下執行下面命令
    yum -y install gcc automake autoconf libtool make
     
2、下載Redis
    wget http://download.redis.io/releases/redis-5.0.5.tar.gz
    
3、解壓
    tar -zxvf redis-5.0.5.tar.gz -C /opt (解壓到此目錄)
    
4、進入到解壓的目錄后編譯
    cd redis-5.0.5
    make MALLOC=libc
    
5、同樣在解壓后的目錄內進行安裝(安裝后會有一個bin目錄,目錄內就有redis-server檔案)
    make PREFIX=/usr/local/redis install
    
6、啟動redis服務(默認不是后臺行程,所以當前視窗就會被占用,不能進行其他操作)
    cd /usr/local/redis/bin
    ./redis-server
   
7、啟動redis客戶端(可以在xshell重開一個對話,啟動客戶端)
    cd /usr/local/redis/bin
    ./redis-cli
        啟動客戶端后檢測redis服務是否開啟:
        redis 127.0.0.1:6379> PING(回傳PONG則表示ping通即服務已開啟)

4 配置

1、進入解壓的Redis目錄
    cd /opt/redis-5.0.5

2、將redis.conf復制到安裝檔案的目錄下(與bin同級)
    cp redis.conf /usr/local/redis

3、注意:要想讓組態檔生效,需要在啟動redis時帶上組態檔!!!
    cd /usr/local/redis/bin
    ./bin/redis-server ./redis.conf

?

部分配置項

配置項說明
bind指定可以訪問Redis的主機IP,默認只能本機訪問Redis,如果要遠程訪問Redis,則需要將 bind 其注釋掉,或者系結地址==# bind 127.0.0.1==
daemonize指定是否為守護行程(后臺運行), 默認為no,即不是后臺運行,一運行就占用視窗,無法啟動其他程式,一般修改為 yes
port指定埠號,默認為 6379
requirepass設定密碼,默認沒有密碼
pidfile指定piffile檔案位置,當Redis以守護行程運行時,會產生pid檔案默認把pid寫入到==/var/run/redis-6379.pid==檔案中,
timeout客戶端閑置多少(秒)后關閉連接, 默認為0,表示關閉此功能
loglevel指定日志記錄級別,共四級:debug、verbose、notice、warning ,默認為notice
database設定資料庫數量,默認是16個,編號 0-15
save 指定多少時間、有多少次更新操作,就將資料持久化到dump.rdb檔案,這是RDB持久化方式的配置,redis默認配置有三個,滿足其中一個就會進行持久化: save 900 1 (900秒有1個更改) save 300 10 (300秒有10個更改) save 60 10000 (60秒有10000更改)
rdbcompression指定持久化是否壓縮資料,默認是yes,
dbfilename指定持久化后生成的檔案,默認是dump.rdb
dir指定上面檔案存放的路徑,默認是 ./ (當前目錄,與bin同級)
slaveof 當本機設定為slave服務時,設定相應master服務的IP地址和埠號 ,redis啟動時,自動從master進行資料同步
masterauth 當master服務設定了密碼保護時,slave服務連接master的密碼
maxclients 設定同一時間最大客戶端連接數, 默認不限制,
maxmemory 指定最大記憶體限制,(建議不要超過1G,在256-512M) 默認不限制, 單位是M

5 啟動和關閉

5.1 啟動

(一)服務端啟動

[root@localhost ~]# cd /usr/local/redis
[root@localhost redis]# ./bin/redis-server ./redis.conf

(二)客戶端啟動

? ①本地訪問客戶端

[root@localhost redis]# ./bin/redis-cli -a [密碼(123456)]
默認: -h 127.0.0.1 -p 6379

? ②遠程訪問客戶端

[root@localhost redis]# ./bin/redis-cli -h [服務端IP] -p [埠號] -a [密碼]

5.2 關閉

  • 正常關閉(通過客戶端,關閉服務端)
127.0.0.1:6379> shutdown [NOSAVE|SAVE]
  • 非正常關閉(直接殺掉redis服務端行程)
查看當前與redis有關的行程:				 ps –ef | grep –i redis  

得到redis-server的PID后,殺死相應的行程:	kill -9 PID

6 基本資料型別和常用命令

key的命名建議

? 使用統一的命名模式,用冒號隔開,通過統一模式,來體現資料之間的關系

? 如:user:123:name 不用我解釋,也能看懂大概是什么

注意:

? 1、key區分大小寫,命令不區分大小寫

? 2、基本資料型別針對的是value,key的保存都是通過字串形式保存的

6.1 公用命令

? 對所有型別資料都可以操作,或者說是資料庫層面的命令,

  • SELECT numb:切換資料庫(默認是0)

  • DEL key:洗掉key(回傳受影響的key數量)

  • DUMP key:序列化給定key(回傳被序列化的值)

  • EXISTS key:檢查key是否存在(存在回傳1,不存在回傳0)

  • EXPIRE key seconds:為key設定過期時間(秒)

    • 沒有設定則默認為永久存在,除非delete掉
    • 驗證碼等有時效性的資料中常用
    • PEXPIRE key milliseconds:功能相同,毫秒為單位
  • TTL key:回傳key剩余時間(秒)

    • -1 表示永久有效
    • -2表示已無效 / 不存在
    • PTTL key:功能相同,毫秒為單位
  • PERSIST key:移除key的過期時間,key將持久保存

  • KEYS pattern:查詢所有符號給定模式的key

    • pattern表示通配符:* 代表任意數量任意字符,? 代表任意一個字符
      • KEYS * : 查詢所有的key
      • KEYS *a: 查詢以a為結尾的key
      • KEYS ?a*:查詢以任意一個字符拼接上a作為開頭的key
      • KEYS ??: 查詢出兩個字符的key
  • RANDOMKEY:隨機回傳一個key

  • RANAME key newkey:修改key的名稱

  • MOVE key numb:移動key至numb序號所指定資料庫中(第一個庫為0)

  • FLUSHDB:清除當前資料庫的所有key

  • FLUSHALL:清除整個Redis所有資料庫的所有key

  • DBSIZE:查看當前資料庫的key的數量

  • TYPE key:回傳key所儲存的值的型別

6.2 基本資料型別

? Redis有5中基本資料型別:StringHashListSetZSet

6.2.1 String

? String型別是二進制安全的,redis的String可以包含任何資料,如字串、影像音頻視頻的序列化物件(二進制),但是一個value最多能存盤512MB

二進制安全是指,在傳輸資料的時候,能保證二進制資料的不會被篡改、破譯;如果被攻擊,能夠及時檢測出來

注意:String可以覆寫其他型別的資料,但是其他型別不能覆寫String型別的資料

? 如果一個key已經存在且是String型別,那么就不可以有其他型別使用賦值陳述句覆寫原來的key

? 如果一個key是其他型別的,可以用String型別的賦值陳述句將其覆寫成String型別的資料

使用場景

  • 通常用于保存單個資料(字串或者數值)
  • 也可用于保密要求高的圖片檔案,內容作為字串(二進制序列化)來存盤

命令

  • SET key value [EX seconds|PX milliseconds] [ NX |XX ]:設定key-value
    • EX表示過期時間設為幾秒,PX則是毫秒級
    • NX → key不存在時才設定成功
    • XX → key存在時才能設定成功(覆寫)
    • 如果都不申明:不過期、key存不存在都可以設定
  • SETNX key value:設定key-value
    • 如果key已經存在,則不會執行任何操作(也就是只有不存在才設定
  • GET key:獲得key對應的value
  • GETRANGE key start end:獲取key中字串的子字串,
    • 下標從start開始,end結束(左閉右閉)(第一個字符的下標位0
  • SETRANGE key offset value:**置換(不是拼接)**指定的字串
    • 從 key 對應的 value 中 第offset位 開始置換
  • APPEND key value:字串拼接
    • 追加至末尾,如果不存在,為其賦值
  • MGET key1 [key2 …]:獲取多個key
    • 每個key之間用空格隔開
  • GETSET key value:設定key的值,并回傳key的舊值
    • 當key不存在,回傳nil
    • 當key存在時,回傳舊值
  • STRLEN key:回傳key所存盤的字串的長度
  • INCR key: key對應的value(整數)的數字 +1
    • 如果不存在key,則key中的值話先被初始化為 0 再加 1
  • INCRBY key 增量:key 對應的value(整數)增加增量的大小
    • 增量只能是整數
  • INCRBYFLOAT key 增量:key 對應的value增加增量的大小
    • value可以是整數,也可以是小數,增量同理
  • DECR key: key中的值自 -1
  • DECRBY key 減量:key 對應的value減少指定量的大小
  • DECRBYFLOAT key 減量:同理

6.2.2 Hash

? 是一個String型別的 field-value 的映射表,hash特別適用于存盤物件(類似于Java中的bean,field為屬性,value為屬性值),每個Hash可以存盤 (2^32 - 1) 鍵值對,可以看成存放key-value對的HashMap容器,相比于JSON,hash占用很少的磁盤空間,

?

使用場景

? 常用來存盤一個物件的資料,Hash是最接近關系資料庫的資料型別,可以將資料庫的一條記錄或程式中的一個物件轉換成HashMap存放在Redis中,

為什么不用String存盤一個物件?/ 為什么Hash更適合存盤多屬性的物件?

如果使用String來存盤,主要有下面兩種方式:

1、將物件的主鍵作為key,其他的所有屬性封裝成JSON串,保存成value,

? 這種方式有下面幾個缺點:JSON串修改單個屬性需要將整個值取出來;增加了序列化/反序列化的開銷

? 2、物件的所有屬性都保存成一個個key-value,在key中進行物件的唯一性標識不同物件的不同屬性

? (物件型別:實體物件主鍵:屬性名) 這種方式的缺點很明顯:浪費記憶體

常用命令

  • HSET key field value:為設定的key設定 field 及其 value

  • HSETNX key field value:只有field不存在,才設定此欄位

  • HMSET key field value [field2 value2]:批量設定(空格隔開即可)

  • HGET key field:獲取Hash型別的key中對應的field的value

  • HMGET key field [field2]:批量獲取

  • HGETALL key:回傳hash表中key的所有field和value

  • HKEYS key:獲取hash表中key的所有field

  • HLEN key:獲取hash表中key對應的field的數量

  • HDEL key field [field2]:洗掉一個或多個hash表中key的field

    • 注意:洗掉時,如果key中所有的field都被洗掉,redis會自動清除這個key (redis不能存在沒有value的key,對于hash型別,其value就是field)
  • HESISTS key field:查看field是否存在

  • HINCRBY key field 增量:指定field(整數)增加增量

  • HINCRBYFLOAT key field 增量:指定field(整數或小數)增加增量

    • 上面計數器的功能和效果,同String型別

6.2.3 List

? 類似于Java中LlinkedList,是簡單的字串串列,按照插入的順序排序,串列中的每個字串稱為元素(element),一個串列最多可以存盤2^32 -1個元素,

使用場景

  • 保存 資料量大、型別一致的基本資料型別的集合
    • 粉絲串列、留言評價、熱點新聞等
  • Redis的 lpush + brpop 命令組合即可實作阻塞佇列(不過一般不用redis作為訊息佇列)

常用命令

  • LPUSH key value1 [value2 …]:按順序從左側插入值

  • RPUSH key value1 [value2 …]:按順序從右側插入值

  • LPUSHX key value:從左側插入值,如果list不存在,則不操作

  • RPUSHX key value:從右側插入值,如果list不存在,則不操作

  • LLEN key:獲取串列長度(元素的個數)

  • LINDEX key index:獲取指定索引的元素

  • LRANGE key start stop:獲取串列指定范圍的元素

    • LRANGE key 0 -1:表示獲取list的全部元素
    • LRANGE key 1 1:表示獲取下標為1的一個元素
    • -1 表示最后一個元素 -2 表示倒數第二個元素 以此類推
  • LPOP key:從左側移除一個元素

  • RPOP key:從右側移除一個元素

    • 同樣的,list內一定要有元素,如果所有元素都移除,則redis也會自動洗掉這個key
  • BLPOP key [key2 …] timeout:從左側移除并獲取key串列一個元素

    • 可以多個串列一起
    • 如果串列不存在,會阻塞到等待超時(秒)或發現可彈出元素為止
  • BRPOP key [key2 …] timeout:功能同上,只不過是從右側

  • LTRIM key start stop :對串列進行修剪,保留指定區間的元素

  • LSET key index value : 修改指定索引的值

  • LINSERT key before|after element value:在串列key的element元素前或則后插入元素value

6.2.4 Set

? 是String型別的無序、不可重復的集合,(唯一性、無序性是與List型別的區別)

使用場景

? 常用于兩個集合之間資料進行交、差、并運算

  • 方便實作如共同關注、共同喜好等功能
  • 利用唯一性,可以統計訪問網站的所有獨立 IP等

常見命令

  • SADD key value1 [value2]:向key添加元素
  • SCARD key:回傳集合元素數
  • SMEMBERS key:回傳集合中所有元素
  • SISMEMBER key element:判斷element元素是否在集合 key 中
  • SRANDMEMBER key [count]:回傳集合中一個或多個(count)亂數
  • SREM key element1 [element2]:移除集合中一個或多個元素
  • SPOP key:移除并回傳集合中隨機一個元素
  • SMOVE source destination element:將element元素從source集合移動到destination集合
  • SINTER key [key …] : 回傳多個集合求交集
  • SUNION key [key …] :回傳多個集合求并集(不會出現重復資料)
  • SDIFF key [key …]: 回傳多個集合的差集
  • SINTERSTORE destination key [key …]: 回傳給定所有key集合的交集并存盤在destination中
  • SUNIONSTORE destination key [key …]: 回傳給定所有key集合的并集并存盤在destination中
  • SDIFFSTORE destination key [key …]: 回傳給定所有key集合的差集并存盤在destination中

6.2.5 ZSet

? 不能重復、可以排序的String型別元素的集合,每個元素都會關聯一個double型別分數(score),Redis通過分數進行從小到大的排序,(元素唯一,但是分數可以重復)

使用場景

? 排行榜

常用命令

  • ZADD key score1 memeber1 [score2 member2 ]:設定分數和元素

  • ZCARD key :獲取集合中的元素數量

  • ZCOUNT key min max: 計算指定區間分數的元素數量

  • ZRANK key member:回傳指定元素的索引(下標值)

  • ZSCORE key element:獲得指定元素的分數

  • ZINCRBY key 增量 element:為指定元素的分數增加增量

  • ZRANGE key start stop:回傳索引區間內的元素(分數從低到高排序)

  • ZREVRANGE key start stop :回傳索引區間內的元素(分數從高到低排序)

  • ZRANGEBYSCORE key min max:回傳分數區間內的元素

  • ZREM key member [member …]: 移除有序集合中的指定元素

  • ZREMRANGEBYRANK key start stop: 移除索引區間的所有元素

  • ZREMRANGEBYSCORE key min max: 移除分數區間的所有元素

7 持久化

? Redis有兩種持久化的機制:RDBAOF,默認是RDB
? 若兩種方式同時開啟,則重啟時以AOF的檔案恢復原始的Redis資料庫,(建議兩種都開啟)

7.1 RDB

? 這是Redis默認的持久化機制,是 定時快照 的方式,保存的是一種狀態,這種方式就是將記憶體中的資料以快照的方式寫入到二進制檔案中,默認檔案名為dump.rdb,(幾十G的資料 → 幾KB的快照檔案)

? 優點

  • 保存速度、還原速度極快,適合大規模的資料恢復

  • 適用于災難備份

    缺點

  • 小記憶體的機器不符合使用(快照的時候,redis消耗增加了一倍的記憶體)

  • 有可能丟失最后一份修改

    配置

    配置是在組態檔中的save部分進行相關的配置(何時進行快照)

#redis默認配置有三個,滿足其中一個即可 
save 900 1 #900秒有1個更改
save 300 10 #300秒有10個更改
save 60 10000 #60秒有10000更改

# 如果資料很重要,又不能等到時間到讓redis自動持久化,則可以使用命令來保存
save:只管保存,其他不管,全部阻塞
bgsave:后臺異步保存,快照的同時還可以相應客戶端請求

# (可以通過lastsave查看最后一次成功執行快照的時間)	

7.2 AOF

? 由于RDB方式是在一定時間間隔做的,如果在間隔期間,修改了資料而redis斷電等意外導致服務端shutdown,就會丟失最后一次修改,如果要求不能丟失任何修改的話,就可以采用AOF的方式,

? 使用AOF,Redis會將每一個收到的寫命令都通過write函式 追加到檔案 中,默認是appendonly.aof,當redis重啟時會通過重新執行檔案中命令,重建整個資料庫內容,(保存的不是狀態,而是命令)

? 優點

  • 可以保證修改資料不丟失

    缺點

  • 持久化檔案會越來越大,且檔案中可能存在許多多余的命令

  • 比如不斷對統一資料的修改命令都會加入到檔案中,所有命令都會執行,才能得到最后真正有用的一個資料,

  • aof檔案遠大于rdb檔案,恢復速度較慢

? 配置

# 首先要開啟AOF:
appendonly yes

# 可以指定檔案:
appendfilename "appendonly.aof"

# 有三種AOF方式:
appendfsync always   # 收到寫命令就立即寫入磁盤
appendfsync everysec # 每秒寫入磁盤一次(默認)
appendfsync no		 # 完全依賴OS,redis不主動進行AOF

重寫機制(REWRITE)

? 由于AOF采取檔案追加的方式,檔案會越來越大,為避免檔案過大的情況,新增了重寫機制:當檔案大小超過一定閾值的時候,Redis會啟動AOF檔案的內容壓縮,只保留可以恢復資料的最小指令集

? 重寫原理和快照相似,是 fork一個新行程將整個記憶體中的資料用命令的方式重寫了一個新的AOF檔案,并洗掉舊的AOF檔案,注意沒有讀取舊的AOF檔案

? 觸發情景:Redis會記錄上次重寫時AOF的大小,默認配置是當AOF檔案大小是上次rewrite后大小的一倍且檔案大于64M時觸發,

auto-aof-rewrite-percenttage 100  # 重寫資料所占的百分比
auto-aof-rewrite-min-size 64mb	  # 重寫檔案最小大小
no-appendfsync-on-rewrite no      # 重寫時是否可以運用Appendfsync,默認為no,保證資料安全

8 事務

? Redis事務可以一次執行多個命令,且有下面兩個保證:

  • Redis會將一個事務中的所有命令序列化,然后按順序執行(串行執行)
  • 執行中不會被其他命令插入,即不允許加塞行為

相關命令

  • MULTI:標記一個事務塊的開始
  • EXEC:執行上面事務塊內的命令
  • DISCARD:取消事務,放棄事務塊中的命令
  • WATCH key1 [ key2 ]:監視key,如果在事務執行前,這些key被其他命令改動,則打斷此事務,
    • 有點像樂觀鎖機制,watch相當于確定版本號,只要前后兩次所監視的key不同,則打斷
    • 一旦執行了EXEC或DISCARD或UNWATCH,之前所加的watch監控鎖都會取消掉
  • UNWATCH:取消對所有key的監視

正常事務命令塊例子

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> GET account:a
QUEUED
127.0.0.1:6379> GET account:b
QUEUED
127.0.0.1:6379> DECRBY account:a 50
QUEUED
127.0.0.1:6379> INCRBY account:b 50
QUEUED
127.0.0.1:6379> EXEC
1) "80"
2) "10"
3) (integer) 30
4) (integer) 60

事務的錯誤處理

  • 如果是邏輯上的錯誤(比如:對一個字串“hello”執行加一命令),那么此事務塊中,只有這個報錯的命令不執行,其他的命令,無論在其前或后,只要是邏輯正確的,都會執行,

  • 如果是語法上的錯誤(即命令語法不正確,也稱報告錯誤),那么此事務塊到最后執行exec時,會自動取消此事務,

    • 在事務塊中,提交了一個錯誤的命令,會立即列印出報告錯誤,但是如果無視,依舊可以繼續在事務塊中添加其他命令,但是到最后執行exec也會取消此事務,所以一旦出現報告錯誤,則可以使用discard中斷事務,

所以說:Redis的事務,并不是真正的事務,是偽事務

9 主從復制 & 哨兵模式 & 集群

單臺Redis服務機有下面幾個缺點:

  • 容易發生單點故障,不具備容錯性
  • 一臺服務器負責所有的請求負載,壓力較大
  • 且單臺服務器容量有限,一臺Redis服務器記憶體最好不要超過20G

如果使用多臺機器來保存Redis資料,不就可以解決上面問題,保證系統的高可用性了嗎?而這種方式,就需要進行機器之間的資料同步問題,這就是接下來要討論的,

9.1 主從復制

? 一個Redis服務可以有多個該服務的復制,這個Redis服務稱為Master,其他復制稱為Slave,因為大部分的應用都是“讀多寫少”,故:

  • Master負責處理寫請求可寫可讀
  • Slave負責處理讀請求只讀不可寫

主機(Master)資料更新后,根據配置和策略,自動同步到備機(Slave)中

  • Slave啟動成功連接到Master后,會發送一個sync命令,進行全量復制(Master所有的資料進行同步)
  • 之后的Master寫資料,slave進行的是增量復制(新增的部分進行同步)

? 要點:

  • 一個Slave只能有一個Master
  • 一個Redis可以既是Master,也是Slave
  • 主從復制的時候不會阻塞Master,是異步的

? 配置實作

? 配從不配主,有下面三種方式可以變成從機

  • 在服務端登錄時,帶上 -slaveof-p 兩個屬性
注意是服務端登錄帶上上面兩個屬性,客戶端登錄只需帶上6380埠
(因為這里假設6379為主機的埠,從機的埠為6380)

//服務端登錄
./bin/redis-server ./redis6380-conf -p 6380 -slaveof MasterIP Master埠

//客戶端登錄
./bin/redis-cli -p 6380 -a 123456
  • 在客戶端已經登錄的情況下,使用slaveof命令,可以變成從機
127.0.0.1:6380> slaveof MasterIP Master埠

上面兩種在與Master斷開連接(即從機shutdown等)時,需要重新進行salve連接,如果想要永久連接,則需要下面這種方式,將相關屬性配置在組態檔中

  • 復制一份conf檔案作為從機的組態檔,從機配置開啟下面配置
# 在redis-6380.conf中配置
slaveof 127.0.0.1 6379
port 6380
# 還有其他類似 log檔案名、pid檔案名、dump檔案名 都進行修改

# 注意:這里修改是為了在一臺機器上模擬成多臺機器運行,實際上都是在不同機器上的redis中實作主從的,所以一般只需要配置slaveof即可,

# 服務端啟動
./bin/redis-server ./redis6380-conf

? 若要將從機變為獨立的主機Master,則執行命令slaveof on one即可,

9.2 哨兵模式(Sentinel)

? 主從復制弊端就是不具備高可用性,一旦Master掛了,Redis就不能提供寫操作處理,所以就出現了哨兵模式(若Master掛了自動從slave機中選出新的Master機)

? 哨兵模式是Redis高可用的一種解決方案,當Master主機遇到例外中斷服務后,Redis能夠在后臺自動檢測到主機是否故障,如果故障了就根據投票數自動將一個Slave從機轉換成新Master機,并發送訊息通知管理員,無需人工操作,實作高可用性,

? 每秒每個哨兵會向整個集群:Master主庫、Slave從庫、其他Sentinel(哨兵)行程,發送一次ping命令做一次心跳檢測,這個就是哨兵用來判斷節點是否正常的重要依據,涉及兩概念:

  • 主觀下線:一個哨兵節點判定主機掛掉了
  • 客觀下線:多個哨兵交換主觀判定結果,只有半數以上的哨兵都認為主機掛了,才會判定主機下線

? 基本上哪個哨兵節點最先判斷出這個主機客觀下線,就會在各個哨兵節點中發起投票機制Raft演算法(選舉演算法),最終被投為新Master機的哨兵節點完成主從自動化切換,

? 注意

? 如果原來掛了的Master在哨兵決定了新Master后,又恢復正常回來了,則這個舊Master機則會作為Slave機,掛在新的Master后

? 和主從復制中手動修改新Master機不同,主從復制中手動修改,舊Master回來后,和其他的主從關系機無關系,是一個新的獨立的Master主機,

9.3 集群(Redis Cluster)

? 哨兵模式基本可以滿足一般生產的需求,具備高可用性,但是當資料量過大到一臺服務器存放不下的情況時,主從模式或sentinel模式就不能滿足需求了,這個時候需要對存盤的資料進行分片,將資料存盤到多個Redis實體中,

? 集群可以說是哨兵和主從模式的結合體,集群模式就是為了解決單機Redis容量有限的問題,將Redis的資料根據一定的規則分配到多臺機器

cluster集群特點

  • 所有redis節點網路互聯,資料共享

  • 都是 一主N從,其中從庫不提供服務,僅作為備用

  • 集群至少要三個主庫才能正常運行,即一個集群最少需要有6個Redis節點(三組,每組一主一從)

  • 不支持同時處理多個key,redis把key均勻分布在各個節點上,分開保存

  • 客戶端可以連接任何一個主節點進行讀寫,支持在線增加、洗掉節點

  • 集群是去中心化的,每個Master節點都是平等的,都可以獲取和設定資料,而slave節點不提供服務,只是對應Master的一個備份,

  • 在其中一個Master服務器上登錄的客戶端,寫入的資料會根據一定的演算法,將其存入到計算得到的 槽(slot) 中,由于槽平均分配給不同的Master,所以有可能在AMaster設定的資料,會保存在其他的BMaster服務器中,同時BSlave服務器也會同步備份,(這也是去中心化的部分體現)

真集群:每個Redis服務端都在不同的機器上(IP不同,port可能同)

假集群:在同一個機器上,通過不同的埠,模擬多個Redis服務端(IP同,port不同)

開啟集群(這部分留坑,之后深入使用后再填坑)

  • 需要將redis組態檔中的cluster-enable配置打開,配置為yes
  • 在redis沒有設定密碼并且bind IP注釋掉的情況下,redis會處于安全保護模式,禁止公網訪問redis cache,為了正常訪問需要取消保護模式:protected-mode no

10 快取常見問題 & 解決

10.1 快取穿透

? 當查詢一個資料庫不存在的資料,這個資料默認也不會寫入到快取Redis中,所以在高并發下,大量的用戶查詢此不存在的資料,會導致每次查詢都是直接訪問資料庫,穿透快取中間件,導致資料庫壓力極大,這就是快取穿透,

解決

  • 當查詢一個不存在的資料時,在Redis快取中間件中寫于相對應key的空字串,表示空結果,這樣子之后繼續查詢此資料時,就會在快取中找到對應的key回傳空字串,避免再次穿透到資料庫,
  • 進行引數過濾(對于大區間可以進行過濾,但是對于區間內的部分小無效的間隙,無法細致地過濾)
    • 比如引數在1-100中有效,其中的3、8號無效,區間過濾只能過濾掉<1 、>100部分無效引數,
  • 布隆過濾器(判斷所查資料是否存在資料庫中)

10.2 快取擊穿

? 在高并發下,對一個特定的值進行查詢,但是這個時候快取正好過期了,導致大量請求直接落到資料庫上

解決

  • 重要的快取資料不設定過期,若資料需要更新,就再同步更新快取,
  • 或者限流,減低直接查詢資料庫的請求數量,查詢到后會快取在redis中,之后的請求就不會直接查詢資料庫了,因為在redis的時候就命中了,
  • 甚至直接使用鎖(簡單利用redis的setnx以及Java的sleep即可),鎖住一小段時間,保證只有一個請求達到資料庫拿到資料后快取到redis中,sleep時間過后,大量的請求再去redis中拿,就不會打到資料庫上了,(如果請求量很多,個人感覺比限流好)

區分:

? 快取穿透:查詢的資料是資料庫不存在的資料

? 快取擊穿:查詢的資料是資料庫存在的資料,只是在快取中剛好過期了

10.3 快取雪崩

? 大量快取在同一時間內失效,導致大量的查詢直接訪問資料庫,即發生大量的快取擊穿,造成快取雪崩,

解決

  • 讓快取的失效時間分布均勻(加上個隨機值,不要同一時間失效),然后就是處理快取擊穿的操作了,

10.4 快取預熱

? 在專案產品上線前,快取暫時為空,如果直接上線,同樣會導致大量的查詢直接訪問資料庫,所以在上線之前,可以先進行主要的查詢,將熱點資料加入到快取中在上線,這就是快取預熱,

11 其他面試題

部分參考敖丙大佬的:https://blog.csdn.net/qq_35190492/article/details/103041932

1、快取型別

  • 本地快取:保存在本地,只有本地可以訪問,服務重啟就沒了,

  • 分布式快取:保存在快取中間件,各服務都可以訪問,可以持久化,

2、redis的淘汰策略

  • noeviction: 不洗掉策略, 達到最大記憶體限制時, 直接回傳錯誤資訊,
  • allkeys-lru: 所有key通用, 優先洗掉最近最少使用的 key,
  • volatile-lru: 只限于設定了 expire 的部分, 優先洗掉最近最少使用的 key,
  • allkeys-random: 所有key通用;,隨機洗掉一部分 key,
  • volatile-random: 只限于設定了 expire 的部分,隨機洗掉一部分 key,
  • volatile-ttl: 只限于設定了 expire 的部分,優先洗掉剩余時間短的key,

3、Redis為什么是單執行緒的?單執行緒還那么快?

? Redis 核心就是 如果我的資料全都在記憶體里,我單執行緒的去操作 就是效率最高的,為什么呢,因為多執行緒的本質就是 CPU 模擬出來多個執行緒的情況,這種模擬出來的情況就有一個代價,就是背景關系的切換,對于一個記憶體的系統來說,它沒有背景關系的切換就是效率最高的,**redis 用 單個CPU 系結一塊記憶體的資料,然后次讀寫的時候針對這塊記憶體的資料進行多,都是在一個CPU上完成的,所以它是單執行緒處理這個事,**在記憶體的情況下,這個方案就是最佳方案 —— 阿里 沈詢

4、Redis為什么很快

  • 是基于記憶體的單執行緒
  • IO多路復用
  • 底層的設計結構

5、RDB的原理是什么?

? 首先redis通過fork子行程來進行RDB檔案的寫入操作,然后進行copy on write,子行程創建后,父子行程共享資料段,父行程繼續提供讀寫服務子行程負責寫RDB,隨者子行程的RDB寫入,父子行程共享的資料段會不斷減少,即寫臟的頁面資料會逐漸和子行程分離開來,(和拉鏈一樣,還沒拉開的就共享,拉開了的就分離了,如果父行程在已分離的區域有寫了資料,是不會寫入到本次RDB檔案中的)

6、除了5種基本資料型別,還有沒有其他的?

? pipeline、pub/sub、HyperLogLog等

Redis的同步機制了解么?

? slave 剛啟動時,會發送一個psync命令給master ,如果是這個slave第一次連接到master,他會觸發一個**全量復制:master就會啟動一個執行緒,生成RDB快照,還會把新的寫請求都快取在記憶體中,RDB檔案生成后,master會將這個RDB發送給slave的,slave拿到之后做的第一件事情就是寫進本地的磁盤,然后加載進記憶體,而在RDB快照之后新增的資料,則是通過AOF進行增量復制**保證同步的,

7、多個系統同時操作(并發)Redis帶來的資料問題?

? Redis是單執行緒的,并沒有鎖機制,各個客戶端之間的事務并不隔離,所以需要同步的話,要么就利用外部的分布式鎖來保證,要么就采取非鎖的方式來保證,

  • 加上分布式鎖,可以利用zookeeper實作分布式鎖,
  • 非鎖方式,那就是CAS,成本低、非阻塞、并發性能高,這個也是Redis提供的一個機制:watch,在redis事務中可以監聽某些key,如果key在這個事務未提交期間被其他客戶端修改過了,則本事務不會提交,會執行回滾,

8、如何保證快取與資料庫的雙寫一致性?

? 如果是嚴格要求資料一致性的,那么就是只能將讀請求和寫請求串行化了,資料絕對一致性,但是并發性嚴重拉跨,

? 如果不是嚴格要求資料一致性的,那么最經典的快取+資料庫讀寫的模式,就是 Cache Aside Pattern,

  • 讀的時候,先讀快取,快取沒有的話,就讀資料庫,然后取出資料后放入快取,同時回傳回應,

  • 更新的時候,先更新資料庫,然后再洗掉快取/更新快取

    • 洗掉快取還是更新快取,主要看是不是熱點資料,如果不是熱點資料,那么直接洗掉掉,等到之后有人訪問再存入快取即可,不然直接更新快取的話,這個資料又是經常修改但是不被經常用到,也就白白更新了,
    • 注意這樣同樣也會出現資料不一致的情況,就比如更新資料庫后洗掉快取失敗,那么資料庫是新資料,快取是舊資料,不一致了,一般可以采用延時雙刪,也就是多次洗掉確保洗掉成功,

9、為什么要用redis做快取

? 首先,為什么要快取?

  • 如果沒有快取,請求會頻繁地達到資料庫上,對資料庫的壓力較大,使用了快取,相當于在資料庫前加了一層屏障,不僅可以降低資料庫的壓力,還可以較快地回傳擊中快取的資料,

? 其次,為什么要用redis做快取?

  • redis是分布式快取,可以獨立部署,可以持久化,
  • redis是基于記憶體、單執行緒、多路復用的快取,速度快,效率高,

10、redis實作分布式鎖

? 先拿setnx來爭搶鎖,搶到之后,再用expire給鎖加一個過期時間防止鎖忘記了釋放,最后如果是手動釋放鎖的話,使用delete

? 而為了避免出現setnx之后執行expire之前行程意外crash或者要重啟維護了,導致鎖釋放不遼,可以直接在setnx命名后面帶上過期時間(即將setnx和expire結合成一條命令

11、如果redis正在給線上的業務提供服務,那使用keys指令模糊查找會有什么問題?

? Redis的單執行緒的,keys指令會導致執行緒阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復,

? 這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key串列,但是會有一定的重復概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用keys指令長,不過在scan程序中,鍵可能會被修改, 所以增量式迭代命令只能對被回傳的元素提供有限的保證 ,

12、使用過Redis做異步佇列么,你是怎么用的?

一般使用list結構作為佇列,rpush生產訊息,lpop消費訊息(或者相反也可以),當lpop沒有訊息的時候,要適當sleep一會再重試,

如果不用sleep,可以使用的是blpop,在沒有訊息的時候,它會阻塞住直到訊息到來,

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

標籤:其他

上一篇:從歷史資料看阿里云和華為云?

下一篇:Centos7離線安裝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