国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

這篇具有很好參考價值的文章主要介紹了微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

系列目錄

微服務(wù) - 概念 · 應(yīng)用 · 架構(gòu) · 通訊 · 授權(quán) · 跨域 · 限流
微服務(wù) - Consul集群化 · 服務(wù)注冊 · 健康檢測 · 服務(wù)發(fā)現(xiàn) · 負載均衡
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)
微服務(wù) - Nginx網(wǎng)關(guān) · 進程機制 · 限流熔斷 · 性能優(yōu)化 · 動態(tài)負載 · 高可用
微服務(wù) - 應(yīng)用性能監(jiān)測 · 鏈路追蹤 · 概念規(guī)范 · 產(chǎn)品接入 · 方法級追蹤 · 創(chuàng)建指標(biāo)跨度

本篇內(nèi)容基于 Redis v7.0 的闡述;官網(wǎng):https://redis.io/
本篇計劃用 Docker 容器輔助部署,所以需要了解點 Docker 知識;官網(wǎng):https://www.docker.com

一、分布式解決 Session 的問題

在單站點中,可以將在線用戶信息存儲在Session中,隨時變更獲取信息;在多站點分布式集群如何做到Session共享呢?架設(shè)一個Session服務(wù),供多服務(wù)使用。

頻繁使用的數(shù)據(jù)存在DB端,頻繁的DB連接,頻繁的IO;數(shù)據(jù)存于內(nèi)存中更能減少性能的消耗,更能提高使用效率。

集群化分布式時,為解決以上現(xiàn)象,建立緩存服務(wù)顯得尤為重要。

建立緩存服務(wù)選擇性很多,如:Redis、MongoDB等,以下以 Redis 為例:

作者:[Sol·wang] - 博客園,原文出處:https://www.cnblogs.com/Sol-wang/

二、內(nèi)存數(shù)據(jù)庫 Redis

Remote Dictionary Server;
遠程字典服務(wù),Key/Value 存儲系統(tǒng)、列存儲、文檔型存儲等,NoSQL開源內(nèi)存數(shù)據(jù)庫。最多的使用場景是作為數(shù)據(jù)緩存,存在于應(yīng)用與DB之間,減少對DB的訪問,提高數(shù)據(jù)操作的性能。

下圖展示了緩存服務(wù)在整體架構(gòu)中的位置:
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

2.1 Redis 特性

高性能 / 高可用 / 持久化 / 集群化,單實例每秒讀寫達10萬次;

豐富的數(shù)據(jù)類型 :String / Hash / Set / Zset / 隊列 / 訂閱 / 發(fā)布;

高性能數(shù)據(jù)結(jié)構(gòu):SDS / Intset / ziplist / listpack / quicklist / skiplist;

支持 ACL:Access Control List;精細化的權(quán)限管理策略;

單線程處理事務(wù):順序執(zhí)行,容易上鎖;

多線程處理輔助功能:連接請求 / 持久化等;

單線程處理事務(wù)的優(yōu)缺點

優(yōu)點:順序執(zhí)行,不存在臟讀臟寫幻讀等情況,不存在死鎖,不存在線程管理的開銷。
缺點:單線程的性能瓶頸,多處理器的資源浪費。

2.2 單線程IO多路復(fù)用

通常情況下,同時連接 Redis 的客戶端有成千上萬的,但 Redis 只有一個主線程處理事務(wù),那如何做到多路連接集中到一個線程處理呢?

當(dāng)多個客戶端同時發(fā)起連接后,這也是需要一個過程的,也是有連接完成的先后,誰連接完成就會告訴 Redis,這里的告訴用的是回調(diào)方式,Redis就會把他的任務(wù)放到單一的隊列中,隊列的另一頭連接著主線程。

在這個過程當(dāng)中,多路的連接匯集到一個有足夠處理能力的隊列中進行傳輸;是不是可以理解為:多路連接重復(fù)利用了單個管道;我想...這里也是體現(xiàn)了 Redis 的多路復(fù)用技術(shù)。當(dāng)然,單單就多路復(fù)用來講,也會是多路集中到一路,然后這一路又分成了多路到各各目標(biāo)。

多路復(fù)用也有不同的算法:select、poll、epoll,Redis用的是epoll算法,所以其中有回調(diào)的動作,目前而言,epoll是最高效的;關(guān)于每個具體的算法,有興趣的同學(xué)可以繼續(xù)研究一下。

2.3 啟動 Redis

用 Docker 啟動 Redis 簡單示例:

1、拉取鏡像docker pull redis

2、運行容器 docker run -d --name=some-redis redis

3、連接到 Redis docker exec -it some-redis redis-cli

Redis Docker版默認是沒有配置文件的,官網(wǎng)說:可以再生成鏡像方式解決...

既然沒有配置文件,那 Redis 啟動完全是按所有配置項的默認值運行的;如下傳參啟動:

# 啟動 redis-server,多參數(shù)配置
docker run -d --name some-redis -p 6379:6379 redis redis-server \
    --bind 0.0.0.0 \        # 支持任意的連接
    --save 60 1 \           # 每60秒 持久化一次
    --protected-mode no \   # 取消保護模式
    --requirepass 123456    # 登錄密碼 123456;連接后用 auth {passwd} 方式登錄

傳參也就是覆蓋了配置項的默認值,以下查看覆蓋后的配置項效果:config get *列出所有配置項

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

Redis 啟動后,都包含 redis-server / redis-client;
所以任意 Redis 都可用 redis-client 連接到其它 redis-server:docker exec -it some-redis redis-cli -h {目標(biāo)IP} -p {目標(biāo)端口}

2.4 重要配置項

通常配置參數(shù)于配置文件中;比如:/etc/redis/redis.conf

配置項 說明
bind 可訪問限制,白名單;注釋后不限制
port 對外端口
timeout 連接后,沒有通信任務(wù)的空閑時間,超出此時長后自動斷開
daemonize 后臺運行(容器運行時忽略
protected-mode 只能本地訪問的保護模式
tcp-backlog 網(wǎng)絡(luò)連接隊列最大連接數(shù)(對應(yīng)Linux內(nèi)核參數(shù) net.core.somaxconn,有關(guān)命令sysctl
tcp-keepalive 網(wǎng)路通信檢測間隔,網(wǎng)絡(luò)是否已斷開(當(dāng)timeout為0才起效吧
pidfile 存放ProcessID編號的文件Pid的存放目錄(后臺運行時才會產(chǎn)生pid文件,容器時是否忽略
loglevel 日志級別
logfile 日志文件目錄
database 數(shù)據(jù)庫個數(shù)
requirepass Client 連接密碼
maxclients 客戶端同時最大連接數(shù)(對應(yīng)Linux user openfile limit,必設(shè);有關(guān)命令ulimit
maxmemory 內(nèi)存最大使用量,推薦70%

三、數(shù)據(jù)類型 / 常用命令

Key/Value 的存儲系統(tǒng),Key相當(dāng)于區(qū)分的變量名稱,類型區(qū)別在于Value;常用數(shù)據(jù)類型有:

String:字符,基礎(chǔ)類型,過期時長,遞增

  • SET/GET key value寫入/取值
  • GET key key key取多個值
  • INCR/DECR key遞增1/遞減1

List:隊列,先進先出,先進后出

  • LPUSH/RPUSH key value頭/尾添加
  • LPOP/RPOP key頭/尾移除
  • LLEN key隊列長度

Set:無序集合,可查詢 交集、并集、差集等

  • SADD|SREM key member member member插入/移除 元素
  • SISMEMBER key member是否存在成員
  • SINTER key1 key2多集合取交集
  • SCARD key元素個數(shù)總數(shù)

ZSet:帶排序的Set集合;比Set多出一個專用的score值,又可排出名次列

  • ZADD key score member score member新增成員及序列數(shù),可覆蓋
  • ZRANGE key start stop按序列范圍取集合
  • ZRANK key member取正序排名;從0開始的名次
  • ZREVRANK key member取倒序排名;從0開始的名次

Hash:可同時設(shè)置/獲取多個屬性值

  • HSET key field value field value成對設(shè)置多個屬性與值
  • HMGET key field [field field]取多個列的值
  • HINCRBY key field -5指定屬性的值,遞增/遞減

四、數(shù)據(jù)結(jié)構(gòu)

為什么 Redis 要有自己的數(shù)據(jù)結(jié)構(gòu)

  • 查詢要快:體現(xiàn)在單條Key用了連續(xù)性的內(nèi)存空間
  • 占用空間少,節(jié)約內(nèi)存:體現(xiàn)在了集合的數(shù)據(jù)壓縮

Redis 中有這么幾種數(shù)據(jù)結(jié)構(gòu):sds (動態(tài)字符串)、hashtable (字典)、linkedlist (鏈表)、intset (整數(shù)集合)、ziplist (壓縮列表)、listpack (緊湊列表)、quicklist (混合列表)、skiplist (跳表);它們分別應(yīng)用于Redis各數(shù)據(jù)類型中,使得Redis在資源利用和運行效率上有著明顯的效果。

以下列出了數(shù)據(jù)類型與數(shù)據(jù)結(jié)構(gòu)的應(yīng)用關(guān)系圖:

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

關(guān)于 Listpack;未來作為 Ziplist 的升級替代品,v7.0版本也會有 Ziplist 的存在,后續(xù)版本中逐漸被替代。

數(shù)據(jù)結(jié)構(gòu)的自動切換

每種數(shù)據(jù)類型也會有多種數(shù)據(jù)結(jié)構(gòu),至于何種數(shù)據(jù)類型在什么情況下用何種數(shù)據(jù)結(jié)構(gòu),取決于存儲的數(shù)據(jù);
比如:List 每元素小于8KB時,自動使用 Ziplist,否則自動切換為 Quicklist;
比如:Set 每元素為數(shù)字,元素小于512個時,自動使用 Intset,否則自動切換為 Hashtable;
比如:Hash 元素小于512個,每元素長度小于64字節(jié),自動使用 Ziplist;否則自動切換為 Hashtable。

影響數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換的配置項

# 配置文件中 各數(shù)據(jù)類型中的數(shù)據(jù)結(jié)構(gòu)
# 能承載的最大長度/個數(shù)/容量
# 超出最大限制后,變更為其它數(shù)據(jù)結(jié)構(gòu)
hash-max-listpack-value 64
hash-max-listpack-entries 512
list-max-listpack-size -2(8KB)
set-max-intset-entries 512
set-max-listpack-value 64
set-max-listpack-entries 128
zset-max-listpack-value 64
zset-max-listpack-entries 128

以下主要以 sds / ziplist / listpack / skiplist 為例的闡述,基本涵蓋了重要的數(shù)據(jù)結(jié)構(gòu),一些擴展性的數(shù)據(jù)結(jié)構(gòu)有興趣的同學(xué)再深入了解下。

4.1 動態(tài)字符串 - SDS

很多計算機語言都一樣,Redis 也是基于C語言寫的;對于String類型,當(dāng)給一個變量拼接一個字符串時,都是以一個新對象在內(nèi)存中重新開辟新的更長的連續(xù)空間來存儲;重新開辟/釋放舊空間這樣的內(nèi)存損耗。。。所以為什么開發(fā)人員會避免strname + "xxx"這樣的拼接方式;字符串長度也是底層每次通過遍歷得出的結(jié)果。。。Redis為了避免這樣的損耗,于是就有了 Simple Dynamic Strings 這樣的解決方案 SDS。

Redis String 會事先分配好比實際字符串更長的內(nèi)存空間,并記錄實際字符串的長度,也記錄存儲后剩余的空間長度。

  1. 取字符串長度時,直接返回記錄的長度值
  2. 追加字符串時,直接使用空閑的剩余空間

預(yù)分配空間有多長?總有用完的時候:

  1. 當(dāng)實際字符串長度<1M時,預(yù)分配實際字符串兩倍的連續(xù)長度,相當(dāng)于本次只會占用一半
  2. 當(dāng)實際字符串長度>1M時,每次預(yù)分配多出1M的長度空間。便于下次直接存儲
  3. 當(dāng)字符串減少縮短時,多出的剩余空間保留,便于下次追加,或手動命令清除空閑空間

這種 空間預(yù)分配策略惰性刪除策略 就是SDS的性能優(yōu)勢。

4.2 壓縮列表 - ziplist

一塊連續(xù)性的內(nèi)存空間存放了整個Value,也就是一個ziplist,如何做的呢?一個集合的示例:

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)
bytes:記錄 ziplist 的總長度
tail:記錄最后一個 entry 的偏移量,便于快速定位
len:記錄 entry 的總個數(shù)
entry:列表元素,數(shù)據(jù)存放的元素
end:單個 ziplist 的結(jié)束符
prevlen:記錄上個 entry 的總長度;這里記錄值所占用的空間長度,取決于上個 entry 的長度,所以1-5會自動切換
encoding:記錄 data 的實際數(shù)據(jù)類型 及長度;如:int時占空間小,可直接存到 encoding,就不用 data 了
data:實際數(shù)據(jù);占用空間小的數(shù)據(jù)類型,可直接放到 encoding 中,所以這時候沒有 data 的存在,省空間。

ziplist 的取值
結(jié)構(gòu)圖中,有總長/個數(shù)/偏移量/結(jié)束符/上個元素長度;所以 ziplist 正序倒序是都可以算出每個 entry 具體位置并取出數(shù)據(jù)。

ziplist 的寫入,插/改/刪 統(tǒng)一為覆蓋方式:
1、為新元素找到被覆蓋元素的位置,位置之前的元素 + 新元素 + 位置之后的元素 = 新的ziplist的完整結(jié)構(gòu)
2、申請新ziplist所需長度的內(nèi)存連續(xù)空間,并存入新空間
3、釋放舊空間

看起來挺不錯的,相比鏈表的非連續(xù)性存儲所帶來的性能提升明顯。。那為什么還會有新的改進版本 listpack 的出現(xiàn)?

ziplist 的弊端

ziplist 的問題出在 prevlen;
也就是上面藍色部分的描述,存了相鄰 entry 的長度;如果 entry 長度過長,相鄰的 prevlen 所占空間長度就會從1變?yōu)?;也就是說 entry 數(shù)據(jù)變更,會影響到相鄰的 entry;最嚴重的情況是很多entry長度恰好都在一個臨界值,會導(dǎo)致相鄰prevlen長度的變化,連鎖反應(yīng)是之后位置上的entry級聯(lián)性的連續(xù)重復(fù)多次變更;
上面提到,變更:就是重新申請新的內(nèi)存連續(xù)空間,釋放舊空間;那么級聯(lián)性的連鎖反應(yīng)呢?一個寫操作,引發(fā)的惡性災(zāi)難事件!??!

4.3 緊湊列表 - listpack

listpack 是 ziplist 的升級版于v7.0中,作為替代品都有什么變化,listpack結(jié)構(gòu)如下圖:
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)
上圖看出,listpack 與 ziplist 的區(qū)別在于:
1、header 取消 tail
2、entry 取消 prevlen
3、當(dāng)前 entry 中增加 encoding + data 的總長度 element-total-len
4、element-total-len 中的首位會標(biāo)識出左側(cè)是否還有值,主要用于逆序讀

element-total-len 編碼
長度 1-5 bytes 是可變的,不固定長度如何讀出整個 element-total-len?這其中0/1標(biāo)識了左側(cè)是否有數(shù)據(jù);
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

listpack 的讀,假設(shè)逆序讀出每個元素的值,已知end固定長度,跳過 1 bytes 到 element-total-len 中讀固定(7)位數(shù),就會知道左側(cè)是否有值,這樣會把 element-total-len 整個讀下來,也就知道了當(dāng)前 entry 長度,那么也就知道了相鄰 entry 的起始位置;繼續(xù)這樣按序把每個 entry 讀出來就完成逆序讀數(shù)據(jù)。

listpack 的寫入,同樣是基于 ziplist 的方式,新元素替換舊元素組成新的長度,存儲到新申請的內(nèi)存連續(xù)空間,釋放舊空間;由于未影響到其它元素,申請一次新空間后完成寫入操作。

這樣以來,listpack 任何寫入的操作,entry 都是在變更自己,不會牽連到其它 entry,這就是對 ziplist 改善的地方。

4.4 跳躍列表 - skiplist

跳表是在鏈表的基礎(chǔ)上追加了更多指針的存儲;鏈表的指針指向了相鄰元素的地址,但跳表又追加了指向間隔元素的指針;這使得跳表在查詢元素的效率上更快。

下表 Linkedlist 與 Skiplist 的查詢區(qū)別:
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)
上圖:兩種查詢的路徑不同,影響到的元素數(shù)量也不同,鏈表搜了11次才找到指定的元素,而跳表僅搜了5次就找到了指定的元素。
比如:元素1 既存了指向下個元素2 的指針,也存了指向元素4 的指針;所以跳表多存的指針讓其可以跳躍搜索,相對于鏈表減少了搜索次數(shù),這就體現(xiàn)了相比鏈表搜索的高效率。

其它數(shù)據(jù)結(jié)構(gòu)

除以上幾種數(shù)據(jù)結(jié)構(gòu)外,Redis也會有Intset、quicklist、Hashtable等,由于基本原理相識,這里簡單描述:
Intset:與ziplist、listpack相似的連續(xù)性集合,主要區(qū)別在于Intset僅支持數(shù)字型;
quicklist:在 ziplist 基礎(chǔ)上擴展的數(shù)據(jù)結(jié)構(gòu),其中每個成員是一個ziplist,插入元素時:插入到前個元素ziplist中的末尾、后ziplist的開頭、或獨立的ziplist。

五、持久化

5.1 RDB 模式

Redis Database:持久化以指定的時間間隔執(zhí)行數(shù)據(jù)集的時間點的快照整庫備份。

觸發(fā)RDB配置save 36000 1 600 10 30 100
以上從右往左,成對解釋:
??當(dāng)30秒內(nèi)寫入了100次,觸發(fā)持久化,如果未滿足條件,繼續(xù)下一對;
??當(dāng)600秒內(nèi)寫入了10次,觸發(fā)持久化,如果未滿足條件,繼續(xù)下一對;
??當(dāng)36000秒內(nèi)寫入了1次,觸發(fā)持久化。

持久化過程:內(nèi)存 -> 臨時文件 -> 磁盤。

影響RDB效率的配置項
??stop-writes-on-bgsave-error yes當(dāng)持久化失敗后強制停止寫入
??rdbcompression yes快照數(shù)據(jù)壓縮,損耗CPU
??rdbchecksum yes是否檢測備份文件,損耗CPU≈10%

關(guān)閉RDB持久化模式:save ""

模式優(yōu)劣

優(yōu)勢:體積小,占用磁盤少。
劣勢:當(dāng)持久化發(fā)生異常時,最后一次的持久化有可能失效,不能確保整體數(shù)據(jù)的絕對完整性。

5.2 AOF 模式

Append Only File:追加記錄服務(wù)器接收到的每個寫入命令,增量保存;如果寫入錯誤,Redis 也會具有自動修復(fù)受損的AOF文件;恢復(fù)時,重新按序執(zhí)行指令,從而重建內(nèi)存庫。

配置開啟AOF模式:appendonly yes

持久化頻率策略配置:appendfysnc always|everysec|no

  • 每次命令追加:每次寫命令立刻記錄,太頻繁,太耗性能
  • 每秒追加一次:每秒集中記錄一次,依然有可觀的性能表現(xiàn)

文件壓縮 Rewrite
主進程 redis-server 創(chuàng)建出一個子進程 bgrewriteaof 對 AOF文件的重新整理,先整理出一個臨時文件,再覆蓋原AOF文件。

Rewrite 的重寫策略:

  • 只針對寫入命令的整理
  • 相同數(shù)據(jù)只記錄最后寫入命令
  • 過期數(shù)據(jù)不記錄
  • 多命令合并記錄

多命令合并示例:如累加命令 Incrby 的累加總和合并成一次累加;如集合命令 rpush 的多次追加合并成一次追加多個。

手動觸發(fā)執(zhí)行重寫命令:bgrewriteaof。

自動觸發(fā)重寫相關(guān)配置:
no-appendfsync-on-rewrite no重寫開關(guān)
auto-aof-rewrite-min-size 64mb重寫觸發(fā)條件,文件超過指定大小
auto-aof-rewrite-percentage 100重寫觸發(fā)條件,文件超過已使用%

AOF文件64MB是不是顯得太小了,可適當(dāng)增加容量如3GB,以防止過多的觸發(fā)壓縮重寫后影響性能;也不可過大,影響數(shù)據(jù)恢復(fù)效率。

模式優(yōu)劣

優(yōu)勢:丟失率低,數(shù)據(jù)較完整。
劣勢:AOF占用磁盤空間大;恢復(fù)時重新全部執(zhí)行一遍命令,恢復(fù)速度慢了點;持久化失敗時,最后一秒寫入命令可能丟失。

Redis 默認開啟 RDB,可同時開啟 RDB + AOF,恢復(fù)數(shù)據(jù)時以 AOF 為優(yōu)先。

由于是單線程方式,Redis 會創(chuàng)建子線程負責(zé)持久化處理,不管是哪種持久化方式,在創(chuàng)建子進程的瞬間,都會有阻塞的現(xiàn)象。

六、分布式集群

6.1 虛擬插槽

Redis 分布式給出一個 16384 長度的集合,每個元素稱為一個 Slot,將所有 Slots 分段平均映射到各個 Master 節(jié)點上;數(shù)據(jù)通過對 Key 的算法映射到各Slot,也就存到了對應(yīng)的 Master 節(jié)點上,所以每個節(jié)點實例負責(zé)其中一部分的Slot讀寫。

通過控制節(jié)點與槽 Slot 的關(guān)系,決定每個 Master 節(jié)點所承載的數(shù)據(jù)量;這在集群節(jié)點維護的時候非常有用。

6.2 創(chuàng)建集群

集群必須了解的conf配置項:

# 每個節(jié)點必須的配置項
cluster-enabled yes
# 節(jié)點失去連接超時時間
cluster-node-timeout 15000
# 節(jié)點間傳輸效率 默認 no(yes:單次多量發(fā)送/no:單次少量多次發(fā)送)
tcp-nodelay no
# DOCKER/NAT support
# (地址端口可能被轉(zhuǎn)發(fā))靜態(tài)配置公共地址
cluster-announce-ip <外部訪問IP>
cluster-announce-port <外部訪問端口>
cluster-announce-bus-port <節(jié)點互通外部端口>

按 Redis 要求的最低 Master 節(jié)點數(shù)量3實例,多主多從的模式,需要創(chuàng)建6個運行實例:(6371-6376,16371-16376)

# 實例示例1(6371,16371)
docker run -d --name clu-rds-1 \
    -p 6371:6371 -p 16371:16371 \        # 容器分別開放 對外連接端口 和 節(jié)點間通信端口
    redis \
    redis-server \                       # 啟動 Redis 服務(wù)命令
    --bind 0.0.0.0 \                     # 不限連接的客戶端來源
    --port 6371 \                        # 實例對外連接端口
    --protected-mode no \                # 非保護模式
    --cluster-enabled yes \              # 開啟集群
    --cluster-announce-ip 13.13.1.16 \   # 對外的訪問IP
    --cluster-announce-port 6371 \       # 集群對外的連接端口
    --cluster-announce-bus-port 16371    # 集群節(jié)點間通訊端口(通常為:10000+Port)

Docker 查看6個容器實例:
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

Docker 3主3從模式 創(chuàng)建集群:

docker exec -it clu-rds-1 \
    # 連接到任意實例
    redis-cli -p 6371 \
    # 創(chuàng)建集群 并指定 1主幾從
    --cluster create --cluster-replicas 1 \
    # 要包含的所有(6個)運行實例<ip:port>
    13.13.1.16:6371 13.13.1.16:6372 13.13.1.16:6373 \
    13.13.1.16:6374 13.13.1.16:6375 13.13.1.16:6376

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

連接到任意容器節(jié)點,查看集群成員:docker exec -it <container-name> redis-cli -p <container-port> cluster nodes

微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

6.3 節(jié)點管理

# 集群信息
redis-cli -p <port> cluster info
# 查看現(xiàn)有節(jié)點成員
redis-cli -p <port> cluster nodes
# 加入新成員,從節(jié)點
redis-cli --cluster add-node <new-node-ip:port> <cluster-member-ip:port> \
    --cluster-slave --cluster-master-id <to-master-id>
# 刪除集群成員節(jié)點
redis-cli --cluster del-node <del-ip:port> <del-node-id>
# 重新分配節(jié)點與插槽映射
redis-cli --cluster reshard <member-ip:port>
# 查看某節(jié)點同步信息
redis-cli -p <port> info replication
# 停止某節(jié)點實例運行
redis-cli -p <port> shutdown

分布式帶來的影響

事務(wù)支持有限;
跨節(jié)點的多Key操作有限;如:SET集合不能計算兩KEY的交集等

6.4 分布式鎖

6.4.1 為什么會需要鎖?

??場景 A:

多用戶對同一產(chǎn)品下單購買,庫存有10個,同一時間進來100個用戶各買一個;
購買前都會看下庫存是否夠買,才會生成訂單,否則提醒無貨;
當(dāng)前10個用戶還沒有下單成功并未扣庫存完成時,后90個用戶看到有庫存,也繼續(xù)生成訂單;
最后賣出100各產(chǎn)品,實際庫存不夠。。。

如何確保有庫存,不超賣。
對庫存加鎖,每個用戶按序進來扣庫存,當(dāng)前用戶扣完庫存后,釋放自己加的鎖,以視完成操作繼續(xù)后續(xù)用戶,下個用戶再進來看庫存是否能購買。

??場景 B:

當(dāng)某個用戶下單扣庫存時,倘若發(fā)送了異常,導(dǎo)致未能釋放自己加上去的鎖,那么。。。沒人負責(zé)釋放此鎖了,后續(xù)不能查扣庫存,誰也不能下單了。

如何確保防止出現(xiàn)死鎖?
對庫存鎖加過期時間,時間超出后,自動強制解鎖。

是的,加鎖、過期自動解鎖,是確保以上場景能夠順利進行的必要條件,共享數(shù)據(jù)被多用戶處理的時候,同一時間點,只能被一個用戶訪問處理,多用戶有序訪問處理,及時更新處理結(jié)果。

共享鎖:數(shù)據(jù)統(tǒng)一放緩存中做業(yè)務(wù)處理,在緩存中加鎖,供所有服務(wù)利用。

6.4.2 SET NX EX 命令

  • SET:String 類型的KV操作
  • NX:Key唯一,僅當(dāng)沒有Key時才能寫入
  • EX:Key 的有效時長,到期后自動刪除

所以完整的命令為:set {business-key} {value} nx ex {過期時長}
返回失敗,表示上個用戶正使用
返回成功,表示自己已開始使用

符合分布式鎖的必要條件

1、當(dāng) get {business-key} 有值時,表示已有用戶在占用,需要等待
2、當(dāng) 占用用戶處理完成后,正常釋放自己加的鎖,del {business-key}
3、當(dāng) 占用用戶處理發(fā)生異常退出時,等ex {過期時長}后,系統(tǒng)自動解鎖,后續(xù)用戶繼續(xù)購買

命令演示案例:(ttl:剩余過期時間秒)
微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)

也可以在 Value 中保存用戶的標(biāo)識,解鎖的時候只能解除自己的鎖,防止某些場景下解鎖錯誤。

分布式Id

由于 Redis Incrment (Incr/Incrby),過期時長等,可以限制用戶短時間內(nèi)的下單量等場景,也可以生成唯一標(biāo)識,用到各服務(wù)中。

6.4.3 Lua 腳本

持續(xù)更新。。。

七、高并發(fā)帶來的問題

7.1 緩存穿透

現(xiàn)象

DB沒有查詢結(jié)果或為NULL,導(dǎo)致查詢結(jié)果沒有進入到緩存;當(dāng)大批量的這種請求時,就會每次“穿透”緩存“直抵”DB,引發(fā)DB的高并發(fā)查詢導(dǎo)致宕機,這種現(xiàn)象就叫緩存穿透。

方案

黑名單策略(IP/用戶名),防止惡意行為

對結(jié)果為空的DB查詢,給出默認值于緩存中

7.2 緩存擊穿

現(xiàn)象

單個訪問量大的 Key (熱門數(shù)據(jù))過期后,緩存需要重建該Key,大量的訪問到DB引發(fā)高并發(fā)查詢,導(dǎo)致DB宕機,這種情況稱為緩存擊穿。

方案

當(dāng)然也可以使用隊列,就降低了并發(fā)的性能;也可以設(shè)置過期時間為永不過期;以下的重點是緩存重建Key的過程:雙重鎖機制

雙重鎖邏輯闡述(也常應(yīng)用于單例模式中)
第一把鎖處理首個請求動作是否已有緩存,并擋住了第二或大量的后續(xù)請求動作;
當(dāng)首個請求動作處理完成后結(jié)果于緩存中,并釋放鎖,處于等待的大量的請求動作會陸續(xù)進來,這就不對了,等待的請求動作應(yīng)該直接用首個請求處理的結(jié)果才對;
所以,后續(xù)的請求進來后應(yīng)該再次鎖驗證緩存中是否已有數(shù)據(jù),也就是第二次的鎖是為了解決并發(fā)時被阻塞的請求動作,防止重復(fù)查詢DB更新緩存。

7.3 緩存雪崩

現(xiàn)象

緩存中的熱門 Key 短時間內(nèi)大批量的同時過期,緩存運行正常,導(dǎo)致DB查詢壓力短時間內(nèi)上升至宕機的現(xiàn)象。

方案

隨機的過期時間,分散過期時間,避免統(tǒng)一生成過期時間

為熱度追加排名,時時調(diào)整熱度數(shù)據(jù),自動延長過期時間文章來源地址http://www.zghlxwxcb.cn/news/detail-417415.html

到了這里,關(guān)于微服務(wù) - Redis緩存 · 數(shù)據(jù)結(jié)構(gòu) · 持久化 · 分布式 · 高并發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 《分布式緩存(一)- Redis的持久化》

    Redis有兩種持久化方案: RDB持久化 AOF持久化 RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡單來說就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中。當(dāng)Redis實例

    2024年02月06日
    瀏覽(24)
  • Redis-持久化、主從集群、哨兵模式、分片集群、分布式緩存

    Redis-持久化、主從集群、哨兵模式、分片集群、分布式緩存

    數(shù)據(jù)丟失問題 : Redis是內(nèi)存存儲,服務(wù)重啟可能會丟失數(shù)據(jù) 解決方案:利用Redis數(shù)據(jù)持久化,將數(shù)據(jù)寫入磁盤 并發(fā)能力問題 : 單節(jié)點Redis并發(fā)能力雖然不錯,單也無法滿足如618這樣的高并發(fā)場景 解決方案:搭建主從集群,實現(xiàn)讀寫分離 故障恢復(fù)問題 : 如果Redis宕機,則服

    2024年02月16日
    瀏覽(23)
  • Redis從入門到精通(十三)Redis分布式緩存(一)RDB和AOF持久化、Redis主從集群的搭建與原理分析

    Redis從入門到精通(十三)Redis分布式緩存(一)RDB和AOF持久化、Redis主從集群的搭建與原理分析

    單機Redis存在四大問題: 1)數(shù)據(jù)丟失問題; 2)并發(fā)能力問題; 3)故障恢復(fù)問題; 4)存儲能力問題。 而Redis分布式緩存,即基于Redis集群來解決單機Redis存在的問題: 1)數(shù)據(jù)丟失問題:實現(xiàn)Redis數(shù)據(jù)持久化; 2)并發(fā)能力問題:搭建主從集群,實現(xiàn)讀寫分離; 3)故障恢復(fù)問

    2024年04月12日
    瀏覽(24)
  • Redis集群(分布式緩存):詳解持久化、主從同步原理、哨兵機制、Cluster分片集群,實現(xiàn)高并發(fā)高可用

    Redis集群(分布式緩存):詳解持久化、主從同步原理、哨兵機制、Cluster分片集群,實現(xiàn)高并發(fā)高可用

    ? ? ? ? 單機式Redis存在以下問題,因此需要Redis集群化來解決這些問題 ???????Redis數(shù)據(jù)快照,簡單來說就是 把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中 。當(dāng)Redis實例故障重啟后,從 磁盤讀取快照文件,恢復(fù)數(shù)據(jù) ??煺瘴募Q為RDB文件,默認是保存在當(dāng)前運行目錄。 ?? ?(1)

    2024年02月08日
    瀏覽(26)
  • el-pagination 組件數(shù)據(jù)持久化,緩存當(dāng)前頁面數(shù)據(jù)

    vue 文件演示: 一般在 handleCurrentChange ,即 @current-change 事件中緩存當(dāng)前的頁面頁碼數(shù)據(jù) 緩存的方法有: window.localStorage 、 sessionStorage 提示: 如果你只想將數(shù)據(jù)保存在當(dāng)前會話中,可以使用 sessionStorage 屬性, 該數(shù)據(jù)對象臨時保存同一窗口(或標(biāo)簽頁)的數(shù)據(jù),在關(guān)閉窗口或標(biāo)簽

    2024年02月13日
    瀏覽(17)
  • 【2023】Redis數(shù)據(jù)持久化

    Redis是基于內(nèi)存的NoSQL數(shù)據(jù)庫,讀寫速度很快,但是存儲在內(nèi)存中的Redis數(shù)據(jù)會在服務(wù)器重啟后丟失。 然而在一些場景中,需要長久的保存數(shù)據(jù),所以需要把內(nèi)存中的數(shù)據(jù)持久化的保存在硬盤中。 Redis持久化提供兩種方式: 1??:AOF(Append Only File)只追加文件 2??:RDB(

    2024年02月10日
    瀏覽(26)
  • redis數(shù)據(jù)安全(一)數(shù)據(jù)持久化

    redis數(shù)據(jù)安全(一)數(shù)據(jù)持久化

    ?一、Redis數(shù)據(jù)安全措施: 1、將數(shù)據(jù)持久化至硬盤 2、將數(shù)據(jù)復(fù)制至其他機器; 復(fù)制是在數(shù)據(jù)持久化的基礎(chǔ)上進行的。 二、將數(shù)據(jù)持久化至硬盤 1、介紹:Redis是一個基于內(nèi)存的數(shù)據(jù)庫,它的數(shù)據(jù)是存放在內(nèi)存中,內(nèi)存有個問題就是關(guān)閉服務(wù)或者斷電會丟失。Redis的數(shù)據(jù)也支持

    2024年01月20日
    瀏覽(23)
  • Redis持久化說明及其單臺Linux服務(wù)器搭建Redis集群架構(gòu)

    Redis持久化說明及其單臺Linux服務(wù)器搭建Redis集群架構(gòu)

    說明:RDB快照主要以二進制文件的形式進行存儲數(shù)據(jù),主要以文件名dump.rdb進行存儲,主要設(shè)置redis.conf里面設(shè)置’save 60 1000’命令可以開啟, 表示在60秒內(nèi)操作1000次進行一次備份數(shù)據(jù)。在客戶端執(zhí)行save(同步)和bgsave(異步操作)。 redis.conf 啟動redis相關(guān)命令 說明:主要把文件生

    2024年02月10日
    瀏覽(32)
  • Redis 7 教程 數(shù)據(jù)持久化

    Redis 7 教程 數(shù)據(jù)持久化

    ????????RDB 持久化以指定的時間間隔執(zhí)行數(shù)據(jù)集的時間點快照 。 ? ? ? ? 把某一時刻的數(shù)據(jù)和狀態(tài)以文件的形式寫到磁盤上,即使出現(xiàn)故障宕機,快照文件也不會丟失,數(shù)據(jù)的可靠性得到保證??煺瘴募褪荝DB(Redis DataBase)文件(dump.rdb) ? ? ? ? ?在指定的時間間隔內(nèi)將

    2024年02月11日
    瀏覽(23)
  • redis原理(四)數(shù)據(jù)安全之?dāng)?shù)據(jù)持久化

    redis原理(四)數(shù)據(jù)安全之?dāng)?shù)據(jù)持久化

    目錄 一、RDB快照持久化 原理 二、RDB快照持久化配置(redis.conf): 三、觸發(fā)RDB備份: 1、自動備份,需配置備份規(guī)則: 2、手動執(zhí)行命令備份(save | bgsave): 3、flushall命令: 四、RDB的備份恢復(fù): 五、RDB優(yōu)缺點: 以下配置以Redis-x64-3.2.100.zip為例,介紹下 RDB快照持久化? 一、

    2024年01月17日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包