Redis部署與使用

leikj發表於2024-07-12

一、關係型資料庫與非關係型資料庫

1.關係型資料庫

關係型資料庫是一個結構化的資料庫,建立在關係模型(二維表格模型)基礎上,一般面向於記錄。

SQL語句(標準資料查詢語言)就是一種基於關係型資料庫的語言,用於執行對關係型資料庫中資料的檢索和操作。

主流的關係型資料庫包括Oracle、MySQL、SQLServer、DB2、PostgreSQL等。以上資料庫在使用的時候必須先建庫建表設計表結構,然後儲存資料的時候按表結構去存,如果資料與表結構不匹配就會儲存失敗。

2.非關係型資料庫

NoSQL(NoSQL=NotonlysQL),意思是“不僅僅是SQL",是非關係型資料庫的總稱。
除了主流的關係型資料庫外的資料庫,都認為是非關係型。
不需要預先建庫建表定義資料儲存表結構,每條記錄可以有不同的資料型別和欄位個數(比如微信群聊裡的文字、圖片、影片、音樂等)。
主流的NOSQL 資料庫有Redis、MongoBD、 Hbase(分散式非關係型資料庫,大資料使用)、Memcached、ElasticSearch(簡稱ES,索引型資料庫)、TSDB(時續型資料庫) 等

兩者區別

1.資料儲存方式不同

  • 關係型:依賴於關係模型E-R圖,同時以表格式的方式儲存資料

  • 非關係型:除了以表格形式儲存之外,通常會以大塊的形式組合在一起進行儲存資料

關係型和非關係型資料庫的主要差異是資料儲存的方式。關係型資料天然就是表格式的,因此儲存在資料表的行和列中。資料表可以彼此關聯協作儲存,也很容易提取資料。
與其相反,非關係型資料不適合儲存在資料表的行和列中,而是大塊組合在一起。非關係型資料通常儲存在資料集中,就像文件、鍵值對或者圖結構。你的資料及其特性是選擇資料儲存和提取方式的首要影響因素。

2.擴充套件方式不同

  • 關係:縱向(天然表格式)
  • 非關係型:橫向(天然分散式)

SQL和NoSQL資料庫最大的差別可能是在擴充套件方式上,要支援日益增長的需求當然要擴充套件。
要支援更多併發量,SQL資料庫是縱向擴充套件,也就是說提高處理能力,使用速度更快速的計算機,這樣處理相同的資料集就更快了。因為資料儲存在關係表中,操作的效能瓶頸可能涉及很多個表,這都需要透過提高計算機效能來克服。雖然SQL資料庫有很大擴充套件空間,但最終肯定會達到縱向擴充套件的上限。
而NoSQL資料庫是橫向擴充套件的。因為非關係型資料儲存天然就是分散式的,NoSQL資料庫的擴充套件可以透過給資源池新增更多普通的資料庫伺服器 (節點) 來分擔負載。

3.對事務性的支援不同

  • 關係型:特別適合高事務性要求和需要控制執行計劃的任務
  • 非關係型:此處會稍顯弱勢,其價值點在於高擴充套件性和大資料量處理方面

如果資料操作需要高事務性或者複雜資料查詢需要控制執行計劃,那麼傳統的SQL資料庫從效能和穩定性方面考慮是最佳選擇。SQL資料庫支援對事務原子性細粒度控制,並且易於回滾事務。
雖然NoSQL資料庫也可以使用事務操作,但穩定性方面沒法和關係型資料庫比較,所以它們真正閃亮的價值是在操作的擴充套件性和大資料量處理方面。

4.非關係型資料庫產生背景

可用於應對 Web2.0 純動態網站型別的三高問題(高併發、高效能、高可用)。

  • High performance——對資料庫高併發讀寫需求
  • Huge Storage——對海量資料高效儲存與訪問需求
  • High Scalability && High Availability——對資料庫高可擴充套件性與高可用性需求

關係型資料庫和非關係型資料庫都有各自的特點與應用場景,兩者的緊密結合將會給Web2.0的資料庫發展帶來新的思路。讓關係型資料庫關注在關係上和對資料的一致性保障,非關係型資料庫關注在儲存和高效率上。例如,在讀寫分離的MySQL資料庫環境中,可以把經常訪問的資料儲存在非關係型資料庫中,提升訪問速度。

二、Redis介紹

1.Redis概念

Redis(遠端字典伺服器) 是一個開源的、使用 C 語言編寫的 NoSQL 資料庫。
Redis 基於記憶體執行並支援持久化,採用key-value(鍵值對)的儲存形式,是目前分散式架構中不可或缺的一環。
Redis伺服器程式是單程序模型,也就是在一臺伺服器上可以同時啟動多個Redis程序,Redis的實際處理速度則是完全依靠於主程序的執行效率。

  • 若在伺服器上只執行一個Redis程序,當多個客戶端同時訪問時,伺服器的處理能力是會有一定程度的下降;

  • 若在同一臺伺服器上開啟多個Redis程序,Redis在提高併發處理能力的同時會給伺服器的CPU造成很大壓力。

即:在實際生產環境中,需要根據實際的需求來決定開啟多少個Redis程序。若對高併發要求更高一些,可能會考慮在同一臺伺服器上開啟多個程序。若CPU資源比較緊張,採用單程序即可。

2.Redis優缺點

1.優點

  • 具有極高的資料讀寫速度:資料讀取的速度最高可達到 110000 次/s,資料寫入速度最高可達到 81000 次/s。(因為Redis是基於記憶體執行的)

  • 支援豐富的資料型別:支援 key-value、Strings、Lists、Hashes、Sets 及 Sorted Sets 等資料型別操作。

  • 支援資料的持久化:當服務意外當機,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。

  • 原子性:Redis 所有操作都是原子性的。(支援事務,所有操作都作為事務)

  • 支援資料備份:即 master-salve 模式的資料備份。(支援主從複製)

2.缺點

  • 快取和資料庫雙寫一致性問題

  • 快取雪崩問題

  • 快取擊穿問題

  • 快取的併發競爭問題

3.Redis適用場景

Redis作為基於記憶體執行的資料庫,是一個高效能的快取,一般應用在Session快取、佇列、排行榜、計數器、最近最熱文章、最近最熱評論、釋出訂閱等。

Redis 適用於資料實時性要求高、資料儲存有過期和淘汰特徵的、不需要持久化或者只需要保證弱一致性、邏輯簡單的場景。

我們通常會將部分資料放入快取中,來提高訪問速度,然後資料庫承擔儲存的工作。

4.Redis為什麼這麼快?

  • redis是基於記憶體執行的,資料讀寫都是在記憶體中完成的

  • 資料讀寫採用單執行緒模式,避免了多執行緒切換帶來的CPU效能消耗,同時也不要考慮各種鎖的問題

  • 採用IO多路複用模型,可以使執行緒處理更多的網路連線請求,提高併發能力

注意:在 Redis 6.0 中新增加的多執行緒也只是針對處理網路請求過程採用了多線性,而資料的讀寫命令,仍然是單執行緒處理的。

三、Redis安裝部署

1.編譯安裝Redis

原始碼包:download.redis.io/releases/

1.安裝依賴包

點選檢視程式碼
[root@node6 ~]#  yum -y install gcc jemalloc-devel systemd-devel

2.下載redis安裝包並解壓

點選檢視程式碼
[root@node6 ~]#  cd /data
[root@node6 data]#  wget http://download.redis.io/releases/redis-5.0.7.tar.gz
[root@node6 data]#  tar xf redis-5.0.7.tar.gz

3.編譯安裝

點選檢視程式碼
[root@node6 data]#  cd redis-5.0.7/
[root@node6 redis-5.0.7]#  make USE_SYSTEMD=yes PREFIX=/apps/redis install

4.配置變數

點選檢視程式碼
[root@node6 redis-5.0.7]#  echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh
[root@node6 redis-5.0.7]#  . /etc/profile.d/redis.sh

5.準備配置檔案及目錄

點選檢視程式碼
[root@node6 redis-5.0.7]#  mkdir /apps/redis/{etc,log,data,run} //建立配置檔案、日誌、資料等目錄
[root@node6 redis-5.0.7]#  cp redis.conf /apps/redis/etc/ //原始碼包中自帶的配置檔案

[root@node6 redis-5.0.7]#  cd /apps/redis/
[root@node6 redis]#  ls
bin  data  etc  log  run
[root@node6 redis]#  tree
.
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof
│   ├── redis-check-rdb
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── data
├── etc
│   └── redis.conf
├── log
└── run

6.啟動redis

  • 前臺啟動

redis-sever是redis伺服器程式

點選檢視程式碼
[root@node6 redis]#  redis-server /apps/redis/etc/redis.conf   //指定配置檔案啟動

[root@node6 redis]#  redis-server --port 埠號 //指定埠號開啟,預設埠為6379

  • systemd啟動
點選檢視程式碼
//準備使用者 修改許可權
[root@node6 apps]#  useradd redis -M -s /sbin/nologin  
[root@node6 apps]#  chown -R redis.redis /apps/redis/

//準備service檔案
[root@node6 redis]#  vim /usr/lib/systemd/system/redis.service

[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支援systemd可以啟用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

[root@node6 redis]#  systemctl daemon-reload
[root@node6 redis]#  systemctl start  redis
[root@node6 redis]#  systemctl status  redis

2.處理redis的warning資訊

TCP backlog

backlog引數控制的是三次握手的時候server端收到client ack確認號之後的佇列值,即全連線佇列

點選檢視程式碼
#vim /etc/sysctl.conf
net.core.somaxconn = 1024
#sysctl -p

vm.overcommit_memory

核心引數說明:

  • 0 表示核心將檢查是否有足夠的可用記憶體供應用程序使用;如果有足夠的可用記憶體,記憶體申請允許;否則,記憶體申請失敗,並把錯誤返回給應用程序。

  • 1 表示核心允許分配所有的實體記憶體,而不管當前的記憶體狀態如何

  • 2 表示核心允許分配超過所有實體記憶體和交換空間總和的記憶體

點選檢視程式碼
#vim /etc/sysctl.conf
vm.overcommit_memory = 1
#sysctl -p

transparent hugepage

警告:您在核心中啟用了透明大頁面(THP,不同於一般記憶體頁的4k為2M)支援。 這將在Redis中造成延遲和記憶體使用問題。 要解決此問題,請以root 使用者身份執行命令“echo never>/sys/kernel/mm/transparent_hugepage/enabled”,並將其新增到您的/etc/rc.local中,以便在重啟後保留設定。禁用THP後,必須重新啟動Redis。

點選檢視程式碼
//臨時修改
echo never > /sys/kernel/mm/transparent_hugepage/enabled

//永久修改
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local

四、Redis多例項

測試環境中經常使用多例項,需指定不同例項的相應的埠,配置檔案,日誌檔案等相關配置。

示例:

  • 準備配置檔案
點選檢視程式碼
[root@node6 etc]#  cp  -a /apps/redis/etc/redis.conf  /apps/redis/etc/redis6380.conf
[root@node6 etc]#  vim redis6380.conf
70 bind 0.0.0.0                             //允許遠端連線
93 port 6380                                //修改埠號
159 pidfile /apps/redis/run/redis_6380.pid  //修改pid檔案
172 logfile /apps/redis/log/redis6380.log   //修改日誌檔案
254 dbfilename dump6380.rdb                 //修改備份檔案的名字
264 dir /apps/redis/data/                   //快照檔案儲存路徑

[root@node6 etc]#  cp -a redis6380.conf redis6381.conf
[root@node6 etc]#  cp -a redis6380.conf redis6382.conf
[root@node6 etc]#  vim redis6381.conf
:% s/6380/6381/g   //全文替換
[root@node6 etc]#  vim redis6382.conf
:% s/6380/6382/g   //全文替換

  • 準備service檔案
點選檢視程式碼
[root@node6 etc]#  cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6380.service
[root@node6 etc]#  cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6381.service
[root@node6 etc]#  cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6382.service

[root@node6 etc]#  vim /lib/systemd/system/redis6380.service
  ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6380.conf --supervised systemd
[root@node6 etc]#  vim /lib/systemd/system/redis6381.service
  ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6381.conf --supervised systemd
[root@node6 etc]#  vim /lib/systemd/system/redis6382.service
  ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6382.conf --supervised systemd

[root@node6 etc]#  systemctl daemon-reload
[root@node6 etc]#  systemctl start redis6380
[root@node6 etc]#  systemctl start redis6381
[root@node6 etc]#  systemctl start redis6382

[root@node6 etc]#  ss -natp |grep '63'
LISTEN     0      511          *:6379                     *:*                   users:(("redis-server",pid=59386,fd=6))
LISTEN     0      511          *:6380                     *:*                   users:(("redis-server",pid=59976,fd=6))
LISTEN     0      511          *:6381                     *:*                   users:(("redis-server",pid=59986,fd=6))
LISTEN     0      511          *:6382                     *:*                   users:(("redis-server",pid=59996,fd=6))

  • 測試info指令
點選檢視程式碼
[root@node6 etc]#  redis-cli -p 6380
127.0.0.1:6380> info

[root@node6 etc]#  redis-cli -p 6381
127.0.0.1:6381> info

[root@node6 etc]#  redis-cli -p 6382
127.0.0.1:6382> info

五、Redis的配置最佳化

1.redis主要配置項

點選檢視程式碼
bind 0.0.0.0 
//監聽地址,可以用空格隔開後多個監聽IP

protected-mode yes 
//redis3.2之後加入的新特性,在沒有設定bind IP和密碼的時候,redis只允許訪問127.0.0.1:6379,可以遠端連線,但當訪問將提示警告資訊並拒絕遠端訪問

port 6379 
//監聽埠,預設6379/tcp

tcp-backlog 511 
//三次握手的時候server端收到client ack確認號之後的佇列值,即全連線佇列長度timeout 0 #客戶端和Redis服務端的連線超時時間,預設是0,表示永不超時

tcp-keepalive 300 
//tcp 會話保持時間300s

daemonize no 
//預設no,即直接執行redis-server程式時,不作為守護程序執行,而是以前臺方式執行,如果想在後臺執行需改成yes,當redis作為守護程序執行的時候,它會寫一個 pid 到/var/run/redis.pid 檔案

supervised no 
//和OS相關引數,可設定透過upstart和systemd管理Redis守護程序,centos7後都使用systemd

pidfile /var/run/redis_6379.pid 
//pid檔案路徑,可以修改為/apps/redis/run/redis_6379.pid

loglevel notice 
//日誌級別

logfile "/path/redis.log" 
//日誌路徑,示例:logfile "/apps/redis/log/redis_6379.log"databases 16 #設定資料庫數量,預設:0-15,共16個庫

always-show-logo yes 
//在啟動redis 時是否顯示或在日誌中記錄記錄redis的logo

//自動儲存策略,三者滿足其一就會儲存
save 900 1     //在900秒內有1個key內容發生更改,就執行快照機制
save 300 10    //在300秒內有10個key內容發生更改,就執行快照機制
save 60 10000  //60秒內如果有10000個key以上的變化,就自動快照備份

stop-writes-on-bgsave-error yes 
//預設為yes時,可能會因空間滿等原因快照無法儲存出錯時,會禁止redis寫入操作,生產建議為no。此項只針對配置檔案中的自動save有效

rdbcompression yes 
//持久化到RDB檔案時,是否壓縮,"yes"為壓縮,"no"則反之

rdbchecksum yes 
//是否對備份檔案開啟RC64校驗,預設是開啟

dbfilename dump.rdb 
//快照檔名

dir ./ 
//快照檔案儲存路徑,示例:dir "/apps/redis/data"

//主從複製相關
replicaof <masterip> <masterport>  //指定複製的master主機地址和埠,5.0版之前的指令為slaveof 
masterauth <master-password>       //指定複製的master主機的密碼

replica-serve-stale-data yes 
//當從庫同主庫失去連線或者複製正在進行,從機庫有兩種執行方式:
//設定為yes(預設設定),從庫會繼續響應客戶端的讀請求,此為建議值
//設定為no,除去特定命令外的任何請求都會返回一個錯誤"SYNC with master in progress"。

replica-read-only yes 
//是否設定從庫只讀,建議值為yes,否則主庫同步從庫時可能會覆蓋資料,造成資料丟失

repl-diskless-sync no 
//是否使用socket方式複製資料(無盤同步),新slave第一次連線master時需要做資料的全量同步,redis server就要從記憶體dump出新的RDB檔案,然後從master傳到slave,有兩種方式把RDB檔案傳輸給客戶端:
//基於硬碟(disk-backed):為no時,master建立一個新程序dump生成RDB磁碟檔案,RDB完成之後由父程序(即主程序)將RDB檔案傳送給slaves,此為預設值
//基於socket(diskless):master建立一個新程序直接dump RDB至slave的網路socket,不經過主程序和硬碟
//推薦使用基於硬碟(為no),是因為RDB檔案建立後,可以同時傳輸給更多的slave,但是基於socket(為yes), 新slave連線到master之後得逐個同步資料。只有當磁碟I/O較慢且網路較快時,可用diskless(yes),否則一般建議使用磁碟(no)

repl-diskless-sync-delay 5 
//diskless時複製的伺服器等待的延遲時間,設定0為關閉,在延遲時間內到達的客戶端,會一起透過diskless方式同步資料,但是一旦複製開始,master節點不會再接收新slave的複製請求,直到下一次同步開始才再接收新請求。即無法為延遲時間後到達的新副本提供服務,新副本將排隊等待下一次RDB傳輸,因此伺服器會等待一段時間才能讓更多副本到達。推薦值:30-60

repl-ping-replica-period 10 
//slave根據master指定的時間進行週期性的PING master,用於監測master狀態,預設10s

repl-timeout 60 
//複製連線的超時時間,需要大於repl-ping-slave-period,否則會經常報超時

repl-disable-tcp-nodelay no 
//是否在slave套接字傳送SYNC之後禁用 TCP_NODELAY,如果選擇"yes",Redis將合併多個報文為一個大的報文,從而使用更少數量的包向slaves傳送資料,但是將使資料傳輸到slave上有延遲,Linux核心的預設配置會達到40毫秒,如果 "no" ,資料傳輸到slave的延遲將會減少,但要使用更多的頻寬

repl-backlog-size 512mb 
//複製緩衝區記憶體大小,當slave斷開連線一段時間後,該緩衝區會累積複製副本資料,因此當slave 重新連線時,通常不需要完全重新同步,只需傳遞在副本中的斷開連線後沒有同步的部分資料即可。只有在至少有一個slave連線之後才分配此記憶體空間,建議建立主從時此值要調大一些或在低峰期配置,否則會導致同步到slave失敗

repl-backlog-ttl 3600 
//多長時間內master沒有slave連線,就清空backlog緩衝區

replica-priority 100 
//當master不可用,哨兵Sentinel會根據slave的優先順序選舉一個master,此值最低的slave會優先當選master,而配置成0,永遠不會被選舉,一般多個slave都設為一樣的值,讓其自動選擇
//min-replicas-to-write 3 #至少有3個可連線的slave,mater才接受寫操作
//min-replicas-max-lag 10 #和上面至少3個slave的ping延遲不能超過10秒,否則master也將停止寫操作

requirepass foobared 
//設定redis連線密碼,之後需要AUTH pass,如果有特殊符號,用" "引起來,生產建議設定

rename-command 
//重新命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
//示例: rename-command del 123456
   
maxclients 10000 
//Redis最大連線客戶端
 
maxmemory <bytes> 
//redis使用的最大記憶體,單位為bytes位元組,0為不限制,建議設為實體記憶體一半,8G記憶體的計算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是緩衝區是不計算在maxmemory內,生產中如果不設定此項,可能會導致OOM

appendonly no 
//是否開啟AOF日誌記錄,預設redis使用的是rdb方式持久化,這種方式在許多應用中已經足夠用了,但是redis如果中途當機,會導致可能有幾分鐘的資料丟失(取決於dump資料的間隔時間),根據save來策略進行持久化,Append Only File是另一種持久化方式,可以提供更好的持久化特性,Redis會把每次寫入的資料在接收後都寫入 appendonly.aof 檔案,每次啟動時Redis都會先把這個檔案的資料讀入記憶體裡,先忽略RDB檔案。預設不啟用此功能

appendfilename "appendonly.aof" 
//文字檔案AOF的檔名,存放在dir指令指定的目錄中

appendfsync everysec 
//aof持久化策略的配置
//no表示由作業系統保證資料同步到磁碟,Linux的預設fsync策略是30秒,最多會丟失30s的資料
//always表示每次寫入都執行fsync,以保證資料同步到磁碟,安全性高,效能較差
//everysec表示每秒執行一次fsync,可能會導致丟失這1s資料,此為預設值,也生產建議值

2.config動態修改配置

config命令用於檢視當前redis配置、以及不重啟redis服務實現動態更改redis配置等。

注意:不是所有配置都可以動態修改,且此方式無法持久保持。

點選檢視程式碼
CONFIG SET parameter value
config   set  引數值
時間複雜度:O(1)
CONFIG SET 命令可以動態地調整 Redis 伺服器的配置(configuration)而無須重啟。

示例:設定連線密碼

點選檢視程式碼
127.0.0.1:6379> CONFIG SET requirepass 123456
OK

示例:設定最大記憶體

點選檢視程式碼
127.0.0.1:6379> CONFIG SET maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592"

3.慢查詢

點選檢視程式碼
slowlog-log-slower-than 1    //指定為超過1us即為慢的指令 
slowlog-max-len 1024         //指定儲存1024條慢記錄


127.0.0.1:6379> CONFIG GET slow-log-slower-then  //慢查詢列表
(empty list or set)

127.0.0.1:6379> SLOWLOG LEN    //檢視慢日誌的記錄條數

127.0.0.1:6379> SLOWLOG RESET  //清空慢日誌

127.0.0.1:6379> slowlog get    //檢視全部
127.0.0.1:6379> slowlog get 2  //檢視慢查詢具體情況,看前2條

4.持久化

Redis 雖然是一個記憶體級別的快取程式,也就是redis是使用記憶體進行資料的快取的,但是其可以將記憶體的資料按照一定的策略儲存到硬碟上,從而實現資料持久儲存的目的目前redis支援兩種不同方式的資料持久化儲存機制,分別是RDB和AOF。

持久化功能:Redis是記憶體資料庫,所有資料都是儲存在記憶體中,為了避免伺服器斷電等原因導致Redis程序異常退出後資料永久丟失,需要定期將Redis中的資料以某種形式(資料或者命令)從記憶體儲存到硬碟;當下次Redis重啟時,利用持久化檔案實現資料恢復。除此之外為了進行災難備份,可以持久將檔案複製到一個遠端位置(比如備份伺服器)。

Redis 提供兩種方式進行持久化:

  • RDB 持久化 (Redis DataBase):原理是將Redis在記憶體中的資料庫記錄定時儲存到磁碟上,類似於快照。

  • AOF 持久化(append only file):原理是將Redis的操作日誌以追加的方式寫入檔案,類似於mysql的binlog。優先順序高

由於AOF的永續性實時性更好,即發生特殊情況導致資料丟失時,丟失的資料更少,因此是目前主流的持久化方式,不過RDB持久化仍然有其用武之地。

RDB模式

RDB(Redis DataBase):基於時間的快照,其預設只保留當前最新的一次快照,特點是執行速度比較快,缺點是可能會丟失從上次快照到當前時間點之間未做快照的資料。

RDB持久化是指在指定的時間間隔內將記憶體中當前程序中的資料生成快照儲存到硬碟(因此也稱作快照持久化),用二進位制壓縮儲存,儲存的檔案字尾是rdb;當Redis重新啟動時,可以讀取快照檔案恢復資料。

實現RDB方式

  • save:同步,會阻塞其它命令,不推薦使用

  • bgsave:非同步後臺執行,不影響其它命令的執行

  • 自動:制定規則,自動執行

觸發條件

RDB持久化的觸發分為手動觸發和自動觸發兩種。

  • 手動觸發

save命令和bgsave命令都可以生成RDB檔案。

  • 自動觸發

在自動觸發RDB持久化時,Redis 也會選擇bgsave而不是save來進行持久化。

自動觸發最常見的情況是在配置檔案中透過 save m n 指定當m秒內發生n次變化時,會觸發bgsave

點選檢視程式碼
//自動觸發,兩個條件 m 和 n 都要滿足
save 900 1         //900s內修改了1個key即觸發儲存RDB
save 300 10        //300s內修改了10個key即觸發儲存RDB
save 60 10000      //60s內修改了10000個key即觸發儲存RDB

dir /apps/redis/run   //指定RDB檔案和AOF檔案所在目錄
dbfilename dump.rdb   //指定RDB檔名
stop-writes-on-bgsave-error yes  //預設為yes時,可能會因空間滿等原因快照無法儲存出錯時,會禁止redis寫入操作,生產建議為no
rdbcompression yes   //是否開啟RDB檔案壓縮
rdbchecksum yes      //是否對備份檔案開啟RC64校驗,預設是開啟

bgsave實現快照的具體過程

1.Redis父程序首先判斷:當前是否在執行save,或bgsave/bgrewriteaof的子程序,如果在執行則bgsave命令直接返回。bgsave/bgrewriteaof 的子程序不能同時執行,主要是基於效能方面的考慮:兩個併發的子程序同時執行大量的磁碟寫操作,可能引起嚴重的效能問題。

2.父程序執行fork操作建立子程序,這個過程中父程序是阻塞的,Redis不能執行來自客戶端的任何命令

3.父程序fork後,bgsave 命令返回 "Background saving started" 資訊並不再阻塞父程序,並可以響應其他命令

4.子程序建立RDB檔案,根據父程序記憶體快照生成臨時快照檔案,完成後對原有檔案進行替換

5.子程序傳送訊號給父程序表示完成,父程序更新統計資訊

AOF 模式

AOF:AppendOnylFile,按照操作順序依次將操作追加到指定的日誌檔案末尾。

同時啟用RDB和AOF,進行恢復時,預設AOF檔案優先順序高於RDB檔案,即會使用AOF檔案進行恢復。

注意: AOF 模式預設是關閉的,第一次開啟AOF後,並重啟服務生效後,會因為AOF的優先順序高於RDB,而先恢復AOF檔案,AOF預設沒有資料檔案存在,從而導致所有資料丟失

AOF相關配置

點選檢視程式碼
appendonly yes                   //開啟AOF
appendfilename "appendonly.aof"  //指定AOF檔名稱
aof-load-truncated yes           //是否忽略最後一條可能存在問題的指令

//儲存規則
appendfsync everysec //aof持久化策略的配置
//no表示由作業系統保證資料同步到磁碟,Linux的預設fsync策略是30秒,最多會丟失30s的資料
//always表示每次寫入都執行fsync,以保證資料同步到磁碟,安全性高,效能較差
//everysec表示每秒執行一次fsync,可能會導致丟失這1s資料,此為預設值,也生產建議值

//重寫規則 rewrite相關
no-appendfsync-on-rewrite yes    //在aof rewrite期間,是否對aof新記錄的append暫緩使用檔案同步策略,主要考慮磁碟IO開支和請求阻塞時間
auto-aof-rewrite-percentage 100  //當Aof log增長超過指定百分比例時,重寫AOF檔案,設定為0表示不自動重寫Aof日誌,重寫是為了使aof體積保持最小,但是還可以確保儲存最完整的資料
auto-aof-rewrite-min-size 64mb   //觸發aof rewrite的最小檔案大小
aof-load-truncated yes           //是否載入由於某些原因導致的末尾異常的AOF檔案(主程序被kill/斷電等),建議yes

AOF重寫機制

隨著時間流逝,Redis伺服器執行的寫命令越來越多,AOF檔案也會越來越大;過大的AOF檔案不僅會影響伺服器的正常執行,也會導致資料恢復需要的時間過長。

檔案重寫是指定期重寫AOF檔案,減小AOF檔案的體積。需要注意的是,AOF重寫是把Redis程序內的資料轉化為寫命令,同步到新的AOF檔案;不會對舊的AOF檔案進行任何讀取、寫入操作!

關於檔案重寫需要注意的另一點是:對於AOF持久化來說,檔案重寫雖然是強烈推薦的,但並不是必須的;即使沒有檔案重寫,資料也可以被持久化並在Redis啟動的時候匯入;因此在一些現實中,會關閉自動的檔案重寫,然後透過定時任務在每天的某一時刻定時執行。

檔案重寫的流程:

  • 執行重寫操作的時候,父程序會開啟一個子程序

  • 這個子程序會分析AOF檔案,刪除一些重複過期的資料,將這些寫入 重寫的快取區,然後形成一個新的aof臨時檔案

  • 同時也有新的資料寫入,會將新寫入的資料放入aof快取區

  • 最後將臨時檔案和新寫入的資料合併到舊的aof檔案中

關於檔案重寫的流程,有兩點需要特別注意:(1)重寫由父程序fork子程序進行;(2)重寫期間Redis執行的寫命令,需要追加到新的AOF檔案中,為此Redis引入了aof_rewrite_buf快取。

RDB和AOF對比

RDB和AOF的選擇

  • 如果主要充當快取功能,或者可以承受數分鐘資料的丟失,通常生產環境一般只需啟用RDB即可,此也是預設值

  • 如果資料需要持久儲存,一點不能丟失,可以選擇同時開啟RDB和AOF

  • 一般不建議只開啟AOF

RDB和AOF的優缺點

  • RDB持久化

  • 優點:RDB檔案緊湊,體積小,網路傳輸快,適合全量複製;恢復速度比AOF快很多。當然,與AOF相比,RDB最重要的優點之一是對效能的影響相對較小。

  • 缺點:RDB檔案的致命缺點在於其資料快照的持久化方式決定了必然做不到實時持久化,而在資料越來越重要的今天,資料的大量丟失很多時候是無法接受的,因此AOF持久化成為主流。此外,RDB檔案需要滿足特定格式,相容性差(如老版本的Redis不相容新版本的RDB檔案)。

  • 對於RDB持久化,一方面是bgsave在進行fork操作時Redis主程序會阻塞,另一方面,子程序向硬碟寫資料也會帶來IO壓力。

  • AOF持久化

  • 與RDB持久化相對應,AOF的優點在於支援秒級持久化、相容性好,缺點是檔案大、恢復速度慢、對效能影響大。

  • 對於AOF持久化,向硬碟寫資料的頻率大大提高(everysec策略下為秒級),IO壓力更大,甚至可能造成AOF追加阻塞問題。

  • AOF檔案的重寫與RDB的bgsave類似,會有fork時的阻塞和子程序的IO壓力問題。相對來說,由於AOF向硬碟中寫資料的頻率更高,因此對 Redis主程序效能的影響會更大。

六、Redis相關命令

命令 作用
info 顯示當前節點redis執行狀態資訊
select 切換資料庫,相當於在MySQL的 USE DBNAME 指令(0-15 共16個庫)
keys 檢視當前庫下的所有key,慎用!!!
mset 一次性設定多個key****
bgsave 手動在後臺執行RDB持久化操作****
dbsize 返回當前庫下的所有key 數量****
flushdb 強制清空當前庫中的所有key,此命令慎用
flushall 強制清空當前redis伺服器所有資料庫中的所有key,即刪除所有資料,此命令慎用!
shutdown 停止所有客戶端

七、Redis資料型別

  • 字元型(string): 普通字串

  • 雜湊(hash): 鍵值對的 鍵值對

  • 列表 (linked lists): 類似於 陣列

  • 集合(set): 無序

  • 有序集合(sorted set): 排行榜

字串string

字串是所有程式語言中最常見的和最常用的資料型別,而且也是redis最基本的資料型別之一,而且redis 中所有的 key 的型別都是字串。常用於儲存 Session 資訊場景,此資料型別比較常用。

點選檢視程式碼
TYPE key名稱  //判斷資料型別

2.列表list

列表是一個雙向可讀寫的管道,其頭部是左側,尾部是右側,一個列表最多可以包含2^32-1(4294967295)個元素,下標 0 表示列表的第一個元素,以 1 表示列表的第二個元素,以此類推。也可以使用負數下標,以 -1 表示列表的最後一個元素, -2 表示列表的倒數第二個元素,元素值可以重複,常用於存入日誌等場景,此資料型別比較常用。

特點:

  • 有序
  • 可重複
  • 左右都可以操作
命令 解釋 例子
lpush 從左邊新增資料 例子:lpush name zhou wu zheng wang
rpush 從右邊新增資料 例子: rpush car benz bmw
llen 獲取列表長度 例子: llen 列表名稱
lindex 獲取單個元數 例子: lindex name 0 ; lindex name -1
lrange 獲取多個元素 例子: lrange name 0 3 第1個到第三個元素
lset 修改列表元素 例子: lset name 2 feng 將name的第二個元素改為feng
lpop 刪除列表元素 例子: lpop name 刪除左邊第一個
rpop 刪除列表元素 例子: rpop name 刪除右邊第一個
ltrim 對列表修剪 例子: ltrim name 1 2 只留下編號為 1 2 的檔案
del刪除列表 例子:del name

3.集合set

Set 是 String 型別的無序集合,集合中的成員是唯一的,這就意味著集合中不能出現重複的資料,可以在兩個不同的集合中對資料進行對比並取值,常用於取值判斷,統計,交集等場景,例如: 實現共同的朋友,微信好友,qq好友

集合特點:

  • 無序
  • 無重複
  • 集合間操作

4.有序集合sorted set

Redis 有序集合和集合一樣也是string型別元素的集合,且不允許重複的成員,不同的是每個元素都會關聯一個double(雙精度浮點型)型別的分數,redis正是透過該分數來為集合中的成員進行從小到大的排序,有序集合的成員是唯一的,但分數(score)卻可以重複,集合是透過雜湊表實現的,所以新增,刪除,查詢的複雜度都是O(1), 集合中最大的成員數為 2^32 - 1 (4294967295, 每個集合可儲存40多億個成員),經常用於排行榜的場景。

有序集合特點:

  • 有序
  • 無重複元素
  • 每個元素是由score和value組成
  • score 可以重複
  • value 不可以重複

5.雜湊hash

hash 即字典, 是一個string型別的欄位(field)和值(value)的對映表,Redis 中每個 hash 可以儲存 2^32 -1 鍵值對,類似於字典,存放了多個k/v 對,hash特別適合用於儲存物件場景。

八、訊息佇列

訊息佇列的兩種模式:

  • 生產者/消費者模式
  • 釋出者/訂閱者模式

相關文章