網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

更多內(nèi)容請(qǐng)參考官網(wǎng):https://redis.io/
Redis持久化
Redis有兩種持久化方案:RDB持久化和AOF持久化。
RDB持久化
RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡(jiǎn)單來(lái)說(shuō)就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤(pán)中。當(dāng)Redis實(shí)例故障重啟后,從磁盤(pán)讀取快照文件,恢復(fù)數(shù)據(jù)??煺瘴募Q為RDB文件,默認(rèn)是保存在當(dāng)前運(yùn)行目錄。
RDB持久化在四種情況下會(huì)執(zhí)行:執(zhí)行save命令、執(zhí)行bgsave命令、Redis停機(jī)時(shí)、觸發(fā)RDB條件時(shí)。
save命令會(huì)導(dǎo)致主進(jìn)程執(zhí)行RDB,這個(gè)過(guò)程中其它所有命令都會(huì)被阻塞,只有在數(shù)據(jù)遷移時(shí)可能用到。
bgsave命令執(zhí)行后會(huì)開(kāi)啟獨(dú)立進(jìn)程完成RDB,主進(jìn)程可以持續(xù)處理用戶請(qǐng)求,不受影響。
Redis停機(jī)時(shí)會(huì)執(zhí)行一次save命令,實(shí)現(xiàn)RDB持久化。
Redis內(nèi)部有觸發(fā)RDB的機(jī)制,可以在redis.conf文件中找到,格式如下:
# 900秒內(nèi),如果至少有1個(gè)key被修改,則執(zhí)行bgsave , 如果是save "" 則表示禁用RDB
save 900 1
save 300 10
save 60 10000
RDB的其它配置也可以在redis.conf文件中設(shè)置:
# 是否壓縮 ,建議不開(kāi)啟,壓縮也會(huì)消耗cpu,磁盤(pán)比較便宜
rdbcompression yes
# RDB文件名稱
dbfilename dump.rdb
# 文件保存的路徑目錄
dir ./
RDB原理
bgsave開(kāi)始時(shí)會(huì)fork主進(jìn)程得到子進(jìn)程,然后得到的子進(jìn)程共享主進(jìn)程的內(nèi)存數(shù)據(jù)。完成fork后讀取內(nèi)存數(shù)據(jù)并寫(xiě)入 RDB 文件,用新RDB文件替換舊的RDB文件。fork采用的是copy-on-write技術(shù):當(dāng)主進(jìn)程執(zhí)行讀操作時(shí),訪問(wèn)共享內(nèi)存;當(dāng)主進(jìn)程執(zhí)行寫(xiě)操作時(shí),則會(huì)拷貝一份數(shù)據(jù),執(zhí)行寫(xiě)操作。
RDB的缺點(diǎn):
RDB執(zhí)行間隔時(shí)間長(zhǎng),兩次RDB之間寫(xiě)入數(shù)據(jù)有丟失的風(fēng)險(xiǎn)。
fork子進(jìn)程、壓縮、寫(xiě)出RDB文件都比較耗時(shí)。
AOF持久化
AOF全稱為Append Only File(追加文件)。Redis處理的每一個(gè)寫(xiě)命令都會(huì)記錄在AOF文件,可以看做是命令日志文件。AOF默認(rèn)是關(guān)閉的,需要修改redis.conf配置文件來(lái)開(kāi)啟AOF:
# 是否開(kāi)啟AOF功能,默認(rèn)是no
appendonly yes
# AOF文件的名稱
appendfilename "appendonly.aof"
AOF的命令記錄的頻率也可以通過(guò)redis.conf文件來(lái)配:
# 表示每執(zhí)行一次寫(xiě)命令,立即記錄到AOF文件
appendfsync always
# 寫(xiě)命令執(zhí)行完先放入AOF緩沖區(qū),然后表示每隔1秒將緩沖區(qū)數(shù)據(jù)寫(xiě)到AOF文件,是默認(rèn)方案
appendfsync everysec
# 寫(xiě)命令執(zhí)行完先放入AOF緩沖區(qū),由操作系統(tǒng)決定何時(shí)將緩沖區(qū)內(nèi)容寫(xiě)回磁盤(pán)
appendfsync no
因?yàn)槭怯涗浢?,AOF文件會(huì)比RDB文件大的多。而且AOF會(huì)記錄對(duì)同一個(gè)key的多次寫(xiě)操作,但只有最后一次寫(xiě)操作才有意義。通過(guò)執(zhí)行bgrewriteaof命令,可以讓AOF文件執(zhí)行重寫(xiě)功能,用最少的命令達(dá)到相同效果。
Redis也會(huì)在觸發(fā)閾值時(shí)自動(dòng)去重寫(xiě)AOF文件,閾值也可以在redis.conf中配置:
# AOF文件比上次文件 增長(zhǎng)超過(guò)多少百分比則觸發(fā)重寫(xiě)
auto-aof-rewrite-percentage 100
# AOF文件體積最小多大以上才觸發(fā)重寫(xiě)
auto-aof-rewrite-min-size 64mb
RDB和AOF各有自己的優(yōu)缺點(diǎn),如果對(duì)數(shù)據(jù)安全性要求較高,在實(shí)際開(kāi)發(fā)中往往會(huì)結(jié)合兩者來(lái)使用。
RDB |
AOF |
|
持久化方式 |
定時(shí)對(duì)整個(gè)內(nèi)存做快照 |
記錄每一次執(zhí)行的命令 |
數(shù)據(jù)完整性 |
不完整,在兩次備份之間的時(shí)間段,數(shù)據(jù)可能會(huì)丟失 |
相對(duì)而言是完整的,取決于刷盤(pán)的策略 |
文件大小 |
會(huì)有壓縮,文件體積小 |
會(huì)記錄每一次的命令,文件體積大 |
宕機(jī)恢復(fù)速度 |
很快 |
慢 |
數(shù)據(jù)恢復(fù)優(yōu)先級(jí) |
低,數(shù)據(jù)完整性不如AOF |
高 |
系統(tǒng)資源占用 |
高,大量CPU和內(nèi)存消耗 |
低,主要是磁盤(pán)IO資源,但AOF重寫(xiě)時(shí)會(huì)占用大量CPU和內(nèi)存資源。 |
使用場(chǎng)景 |
可以接受數(shù)分鐘的數(shù)據(jù)丟失,追求更快的啟動(dòng)速度 |
對(duì)數(shù)據(jù)安全性要求較高 |
Redis主從
單節(jié)點(diǎn)Redis的并發(fā)能力是有上限的,要進(jìn)一步提高Redis的并發(fā)能力,就需要搭建主從集群,實(shí)現(xiàn)讀寫(xiě)分離。
開(kāi)啟主從關(guān)系,修改配置文件
在redis.conf中添加一行配置:```slaveof <masterip> <masterport>```
主從數(shù)據(jù)同步原理:全量同步、增量同步
主從第一次建立連接時(shí),會(huì)執(zhí)行全量同步,將master節(jié)點(diǎn)的所有數(shù)據(jù)都拷貝給slave節(jié)點(diǎn)。完整流程:
1.slave節(jié)點(diǎn)請(qǐng)求增量同步
2.master節(jié)點(diǎn)判斷replid,發(fā)現(xiàn)不一致,拒絕增量同步
3.master將完整內(nèi)存數(shù)據(jù)生成RDB,發(fā)送RDB到slave
4.slave清空本地?cái)?shù)據(jù),加載master的RDB
5.master將RDB期間的命令記錄在repl_baklog,并持續(xù)將log中的命令發(fā)送給slave
6.slave執(zhí)行接收到的命令,保持與master之間的同步
master如何得知salve是第一次來(lái)連接呢?
Replication Id:簡(jiǎn)稱replid,是數(shù)據(jù)集的標(biāo)記,id一致則說(shuō)明是同一數(shù)據(jù)集。每一個(gè)master都有唯一的replid,slave則會(huì)繼承master節(jié)點(diǎn)的replid
offset:偏移量,隨著記錄在repl_baklog中的數(shù)據(jù)增多而逐漸增大。slave完成同步時(shí)也會(huì)記錄當(dāng)前同步的offset。如果slave的offset小于master的offset,說(shuō)明slave數(shù)據(jù)落后于master,需要更新。
因此slave做數(shù)據(jù)同步,必須向master聲明自己的replication id 和offset,master才可以判斷到底需要同步哪些數(shù)據(jù)。
master判斷發(fā)現(xiàn)slave發(fā)送來(lái)的replid與自己的不一致,說(shuō)明這是一個(gè)全新的slave,就知道要做全量同步了。master會(huì)將自己的replid和offset都發(fā)送給這個(gè)slave,slave保存這些信息。以后slave的replid就與master一致了。master判斷一個(gè)節(jié)點(diǎn)是否是第一次同步的依據(jù),就是看replid是否一致。
全量同步需要先做RDB,然后將RDB文件通過(guò)網(wǎng)絡(luò)傳輸個(gè)slave,成本太高了。因此除了第一次做全量同步,其它大多數(shù)時(shí)候slave與master都是做增量同步。
repl_backlog原理(master知道slave與自己的數(shù)據(jù)差異)
這個(gè)文件是一個(gè)固定大小的數(shù)組,只不過(guò)數(shù)組是環(huán)形,也就是說(shuō)角標(biāo)到達(dá)數(shù)組末尾后,會(huì)再次從0開(kāi)始讀寫(xiě),這樣數(shù)組頭部的數(shù)據(jù)就會(huì)被覆蓋。repl_baklog中會(huì)記錄Redis處理過(guò)的命令日志及offset,包括master當(dāng)前的offset,和slave已經(jīng)拷貝到的offset。slave與master的offset之間的差異,就是salve需要增量拷貝的數(shù)據(jù)了。
repl_baklog大小有上限,寫(xiě)滿后會(huì)覆蓋最早的數(shù)據(jù)。如果slave斷開(kāi)時(shí)間過(guò)久,導(dǎo)致尚未備份的數(shù)據(jù)被覆蓋,則無(wú)法基于log做增量同步,只能再次全量同步。
主從同步可以保證主從數(shù)據(jù)的一致性,可以從以下幾個(gè)方面來(lái)優(yōu)化Redis主從就集群:
1.在master中配置repl-diskless-sync yes啟用無(wú)磁盤(pán)復(fù)制,避免全量同步時(shí)的磁盤(pán)IO。
2.Redis單節(jié)點(diǎn)上的內(nèi)存占用不要太大,減少RDB導(dǎo)致的過(guò)多磁盤(pán)IO
3.適當(dāng)提高repl_baklog的大小,發(fā)現(xiàn)slave宕機(jī)時(shí)盡快實(shí)現(xiàn)故障恢復(fù),盡可能避免全量同步
4.限制一個(gè)master上的slave節(jié)點(diǎn)數(shù)量,如果實(shí)在是太多slave,則可以采用主-從-從鏈?zhǔn)浇Y(jié)構(gòu),減少master壓力
小結(jié):
全量同步:master將完整內(nèi)存數(shù)據(jù)生成RDB,發(fā)送RDB到slave。后續(xù)命令則記錄在repl_baklog,逐個(gè)發(fā)送給slave。
增量同步:slave提交自己的offset到master,master獲取repl_baklog中從offset之后的命令給slave
執(zhí)行全量同步的時(shí)機(jī):
slave節(jié)點(diǎn)第一次連接master節(jié)點(diǎn)時(shí)
slave節(jié)點(diǎn)斷開(kāi)時(shí)間太久,repl_baklog中的offset已經(jīng)被覆蓋時(shí)
Redis哨兵
Redis提供了哨兵(Sentinel)機(jī)制,其作用如下:
監(jiān)控:Sentinel 會(huì)不斷檢查您的master和slave是否按預(yù)期工作
自動(dòng)故障恢復(fù):如果master故障,Sentinel會(huì)將一個(gè)slave提升為master,當(dāng)故障實(shí)例恢復(fù)后也以新的master為主。
通知:Sentinel充當(dāng)Redis客戶端的服務(wù)發(fā)現(xiàn)來(lái)源,當(dāng)集群發(fā)生故障轉(zhuǎn)移時(shí),會(huì)將最新信息推送給Redis的客戶端。
集群監(jiān)控原理
Sentinel基于心跳機(jī)制監(jiān)測(cè)服務(wù)狀態(tài),每隔1秒向集群的每個(gè)實(shí)例發(fā)送ping命令:如果某sentinel節(jié)點(diǎn)發(fā)現(xiàn)某實(shí)例未在規(guī)定時(shí)間響應(yīng),則認(rèn)為該實(shí)例主觀下線。如果超過(guò)指定數(shù)量(quorum)的sentinel都認(rèn)為該實(shí)例主觀下線,則該實(shí)例客觀下線。quorum值最好超過(guò)Sentinel實(shí)例數(shù)量的一半。
集群故障恢復(fù)原理
一旦發(fā)現(xiàn)master故障,sentinel需要在salve中選擇一個(gè)作為新的master,選擇依據(jù)如下:
1.首先會(huì)判斷slave節(jié)點(diǎn)與master節(jié)點(diǎn)斷開(kāi)時(shí)間長(zhǎng)短,如果超過(guò)指定值(down-after-milliseconds * 10【主從庫(kù)斷連的最大連接超時(shí)時(shí)間】)則會(huì)排除該slave節(jié)點(diǎn)
2.然后判斷slave節(jié)點(diǎn)的slave-priority值,越小優(yōu)先級(jí)越高【一般都為1】,如果是0則永不參與選舉
3.如果slave-prority一樣,則判斷slave節(jié)點(diǎn)的offset值,越大說(shuō)明數(shù)據(jù)越新,優(yōu)先級(jí)越高
4.最后是判斷slave節(jié)點(diǎn)的運(yùn)行id大小,越小優(yōu)先級(jí)越高。
當(dāng)選出一個(gè)新的master后,實(shí)現(xiàn)切換流程:
1.sentinel給備選的slave節(jié)點(diǎn)發(fā)送slaveof no one命令,讓該節(jié)點(diǎn)成為master
2.sentinel給所有其它slave發(fā)送(slaveof ip+端口)命令,讓這些slave成為新master的從節(jié)點(diǎn),開(kāi)始從新的master上同步數(shù)據(jù)。
3.最后,sentinel將故障節(jié)點(diǎn)標(biāo)記為slave(修改故障節(jié)點(diǎn)配置,添加slaveof 新master 命令),當(dāng)故障節(jié)點(diǎn)恢復(fù)后會(huì)自動(dòng)成為新的master的slave節(jié)點(diǎn)。
Redis分片集群
主從和哨兵可以解決高可用、高并發(fā)讀的問(wèn)題。但是對(duì)于海量數(shù)據(jù)存儲(chǔ)問(wèn)題和高并發(fā)寫(xiě)的問(wèn)題,只有使用分片集群可以解決。
分片集群特征:集群中有多個(gè)master,每個(gè)master保存不同數(shù)據(jù);每個(gè)master都可以有多個(gè)slave節(jié)點(diǎn);master之間通過(guò)ping監(jiān)測(cè)彼此健康狀態(tài);客戶端請(qǐng)求可以訪問(wèn)集群任意節(jié)點(diǎn),最終都會(huì)被轉(zhuǎn)發(fā)到正確節(jié)點(diǎn)。
散列插槽
Redis會(huì)把每一個(gè)master節(jié)點(diǎn)映射到0~16383共16384個(gè)插槽(hash slot)上,數(shù)據(jù)key不是與節(jié)點(diǎn)綁定,而是與插槽綁定。redis會(huì)根據(jù)key的有效部分計(jì)算插槽值,分兩種情況:
1.key中包含"{}",且“{}”中至少包含1個(gè)字符,“{}”中的部分是有效部分【可以根據(jù){}里面的內(nèi)容將key分類】
2.key中不包含“{}”,整個(gè)key都是有效部分
例如:key是num,那么就根據(jù)num計(jì)算,如果key是{xy}num,則根據(jù)xy計(jì)算。計(jì)算方式是利用CRC16算法得到一個(gè)hash值,然后對(duì)16384取余,得到的結(jié)果就是slot值。
小結(jié):
Redis如何判斷某個(gè)key應(yīng)該在哪個(gè)實(shí)例?
1.將16384個(gè)插槽分配到不同的實(shí)例
2.根據(jù)key的有效部分計(jì)算哈希值,對(duì)16384取余
3.余數(shù)作為插槽,尋找插槽所在實(shí)例即可
如何將同一類數(shù)據(jù)固定的保存在同一個(gè)Redis實(shí)例?
這一類數(shù)據(jù)使用相同的有效部分,例如key都以{typeId}為前綴。
集群伸縮
添加新節(jié)點(diǎn)到redis
執(zhí)行命令:
redis-cli --cluster add-node 新節(jié)點(diǎn)地址:端口 舊節(jié)點(diǎn)地址:端口
默認(rèn)是加入了一個(gè)master節(jié)點(diǎn)。
轉(zhuǎn)移插槽:
redis-cli --cluster reshard 節(jié)點(diǎn)地址:端口
其實(shí)對(duì)于分片集群來(lái)說(shuō),所有數(shù)據(jù)都是跟著插槽走的。
故障轉(zhuǎn)移
當(dāng)集群中有一個(gè)master宕機(jī),首先是該實(shí)例與其它實(shí)例失去連接,然后是疑似宕機(jī)狀態(tài),最后是確定下線,自動(dòng)提升一個(gè)slave為新的master,當(dāng)改故障master再次啟動(dòng),就會(huì)變?yōu)橐粋€(gè)slave節(jié)點(diǎn)了。
PS: 多級(jí)緩存
傳統(tǒng)的緩存策略一般是請(qǐng)求到達(dá)Tomcat后,先查詢Redis,如果未命中則查詢數(shù)據(jù)庫(kù),但是存在下面的問(wèn)題:
1.請(qǐng)求要經(jīng)過(guò)Tomcat處理,Tomcat的性能成為整個(gè)系統(tǒng)的瓶頸
2.Redis緩存失效時(shí),會(huì)對(duì)數(shù)據(jù)庫(kù)產(chǎn)生沖擊
多級(jí)緩存就是充分利用請(qǐng)求處理的每個(gè)環(huán)節(jié),分別添加緩存,減輕Tomcat壓力,提升服務(wù)性能:
1.瀏覽器訪問(wèn)靜態(tài)資源時(shí),優(yōu)先讀取瀏覽器本地緩存
2.訪問(wèn)非靜態(tài)資源(ajax查詢數(shù)據(jù))時(shí),訪問(wèn)服務(wù)端
3.請(qǐng)求到達(dá)Nginx后,優(yōu)先讀取Nginx本地緩存
4.如果Nginx本地緩存未命中,則去直接查詢Redis(不經(jīng)過(guò)Tomcat)
5.如果Redis查詢未命中,則查詢Tomcat
6.請(qǐng)求進(jìn)入Tomcat后,優(yōu)先查詢JVM進(jìn)程緩存
7.如果JVM進(jìn)程緩存未命中,則查詢數(shù)據(jù)庫(kù)
在多級(jí)緩存架構(gòu)中,Nginx內(nèi)部需要編寫(xiě)本地緩存查詢、Redis查詢、Tomcat查詢的業(yè)務(wù)邏輯,因此這樣的nginx服務(wù)不再是一個(gè)反向代理服務(wù)器,而是一個(gè)編寫(xiě)業(yè)務(wù)的Web服務(wù)器了。
如果tomcat是集群模式,那么要對(duì)tomcat集群做負(fù)載均衡,是因?yàn)橐屆恳粋€(gè)路徑請(qǐng)求進(jìn)來(lái)都訪問(wèn)同一個(gè)tomcat服務(wù),那么JVM緩存就能一定能生效。
關(guān)于Redis緩存預(yù)熱
Redis緩存會(huì)面臨冷啟動(dòng)問(wèn)題:
冷啟動(dòng):服務(wù)剛剛啟動(dòng)時(shí),Redis中并沒(méi)有緩存,如果所有商品數(shù)據(jù)都在第一次查詢時(shí)添加緩存,可能會(huì)給數(shù)據(jù)庫(kù)帶來(lái)較大壓力。
緩存預(yù)熱:在實(shí)際開(kāi)發(fā)中,我們可以利用大數(shù)據(jù)統(tǒng)計(jì)用戶訪問(wèn)的熱點(diǎn)數(shù)據(jù),在項(xiàng)目啟動(dòng)時(shí)將這些熱點(diǎn)數(shù)據(jù)提前查詢并保存到Redis中。
原文鏈接:https://blog.csdn.net/crazy_xieyi/article/details/129202803
- 上一篇:沒(méi)有了
- 下一篇:沒(méi)有了
相關(guān)推薦
- 2022-06-06 CZGL.ProcessMetrics處理監(jiān)控?cái)?shù)據(jù)的三種方式介紹_實(shí)用技巧
- 2023-02-18 Go?gin權(quán)限驗(yàn)證實(shí)現(xiàn)過(guò)程詳解_Golang
- 2022-07-08 Asp.Net?Core7?preview4限流中間件新特性詳解_實(shí)用技巧
- 2022-09-20 RecyclerView實(shí)現(xiàn)側(cè)滑和網(wǎng)絡(luò)斷點(diǎn)續(xù)傳_Android
- 2022-12-23 Kotlin?select使用方法介紹_Android
- 2023-03-12 Pandas中根據(jù)條件替換列中的值的四種方式_python
- 2022-04-03 C++從匯編的視角審視對(duì)象的創(chuàng)建問(wèn)題_C 語(yǔ)言
- 2022-07-07 C++實(shí)現(xiàn)數(shù)組中元素組合出最大值_C 語(yǔ)言
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支