自學(xué)做網(wǎng)站界面百度自動(dòng)駕駛技術(shù)
目錄
一、基礎(chǔ)
1、Redis 是什么
2、說(shuō)一下你對(duì)redis的理解
3、Redis 為什么這么快?
4、項(xiàng)目中如何使用緩存?
5、為什么使用緩存?
6、Redis key 和value 可以存儲(chǔ)最大值分別多是多少?
7、Redis和memcache有什么區(qū)別?
8、說(shuō)說(shuō)redis常用應(yīng)用場(chǎng)景
二、數(shù)據(jù)類型
1、redis有哪些數(shù)據(jù)類型,分別適用于什么場(chǎng)景?
2、說(shuō)說(shuō)Redis底層數(shù)據(jù)結(jié)構(gòu)?
三、架構(gòu)
1、redis 持久化機(jī)制
2、redis集群高可用
(1)Replication-Sentinel哨兵模式
(2)Redis-Cluster集群模式
3、redis事務(wù)怎么理解?
4、redis的過(guò)期策略及內(nèi)存淘汰機(jī)制?
1.過(guò)期策略
2.內(nèi)存淘汰機(jī)制:
5、布隆過(guò)濾器是什么?
6、如何保證數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)的一致性
1.延時(shí)雙刪
2.采用canal組件監(jiān)控MySQL的binlog日志,把更新后的數(shù)據(jù)同步到redis里面
3.基于 RocketMQ 的可靠性消息通信,來(lái)實(shí)現(xiàn)最終一致性。
7、redis 分布式鎖如何實(shí)現(xiàn)
四、場(chǎng)景
1、緩存穿透、緩存擊穿、緩存雪崩
(2)緩存擊穿
(3)緩存雪崩
2、怎么使用redis實(shí)現(xiàn)消息隊(duì)列
3、什么是bigkey,有什么影響?
4、怎么處理熱key?
5、緩存預(yù)熱怎么做呢?
6、Redis里面有1億個(gè)key,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開(kāi)頭的,如何將它們?nèi)空页鰜?lái)?
一、基礎(chǔ)
1、Redis 是什么
Redis是一個(gè)開(kāi)源的,基于內(nèi)存的,也可進(jìn)行持久化的,使用C語(yǔ)言編寫(xiě)的鍵值對(duì)存儲(chǔ)數(shù)據(jù)庫(kù)。
2、說(shuō)一下你對(duì)redis的理解
(1)Redis 是一個(gè)高性能的基于 Key-Value 結(jié)構(gòu)存儲(chǔ)的 Nosql 開(kāi)源數(shù)據(jù)庫(kù)
(2)目前市面上絕大部分公司都采用 Redis 來(lái)實(shí)現(xiàn)分布式緩存,從而提高數(shù)據(jù)的檢索效率
(3)Redis 之所以這么流行,主要有幾個(gè)特點(diǎn):
- 它是基于內(nèi)存存儲(chǔ),在進(jìn)行數(shù)據(jù) IO 操作時(shí),能夠 10WQPS
-
提供了非常豐富的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),如 String、List、Hash、Set、ZSet 等。
-
Redis 底層采用單線程實(shí)現(xiàn)數(shù)據(jù)的 IO,所以在數(shù)據(jù)算法層面并不需要要考慮并發(fā)安全性,所以底層算法上的時(shí)間復(fù)雜度基本上都是常量
??(4) Redis 雖然是內(nèi)存存儲(chǔ),但是它也可以支持持久化,避免因?yàn)榉?wù)器故障導(dǎo)致數(shù)據(jù)丟失的問(wèn)題
基于這些特點(diǎn),Redis 一般用來(lái)實(shí)現(xiàn)分布式緩存,從而降低應(yīng)用程序?qū)﹃P(guān)系型數(shù)據(jù)庫(kù)檢索帶來(lái)的性能影響。除此之外,Redis 還可以實(shí)現(xiàn)分布式鎖、分布式隊(duì)列、排行榜、查找附近的人等功能,為復(fù)雜應(yīng)用提供非常方便和成熟的解決方案
3、Redis 為什么這么快?
(1)基于內(nèi)存實(shí)現(xiàn)
(2)高效的數(shù)據(jù)結(jié)構(gòu)
SDS 簡(jiǎn)單動(dòng)態(tài)字符串
Redis 是用 C 語(yǔ)言開(kāi)發(fā)完成的,但在 Redis 字符串中,并沒(méi)有使用 C 語(yǔ)言中的字符串,而是用一種稱為SDS(Simple Dynamic String)的結(jié)構(gòu)體來(lái)保存字符串。
哈希表(字典)
Redis 作為 k-v 型內(nèi)存數(shù)據(jù)庫(kù),所有的鍵值就是用字典來(lái)存儲(chǔ)。字典就是哈希表,比如 HashMap,通過(guò) key 就可以直接獲取到對(duì)應(yīng)的value。而哈希表的特性,在O(1)時(shí)間復(fù)雜度就可以獲得對(duì)應(yīng)的值。
跳表
作為 Redis 中特有的數(shù)據(jù)結(jié)構(gòu)-跳躍表,其在鏈表的基礎(chǔ)上增加了多級(jí)索引來(lái)提升查找效率。這是跳躍表的簡(jiǎn)單原理圖,每一層都有一條有序的鏈表,最底層的鏈表包含了所有的元素。這樣跳躍表就可以支持在 O(logN) 的時(shí)間復(fù)雜度里查找到對(duì)應(yīng)的節(jié)點(diǎn)。
下面這張是跳表真實(shí)的存儲(chǔ)結(jié)構(gòu)圖:
網(wǎng)上對(duì)跳表的各種理論講解都比較多,,其基本原理為添加多級(jí)索引來(lái)加快查找速度實(shí)現(xiàn)O(logN)的時(shí)間復(fù)雜度, 通過(guò)隨機(jī)函數(shù)確定節(jié)點(diǎn)插入到幾級(jí)索引中來(lái)防止跳表退化為單鏈表。
雙向鏈表
列表 List 更多是被當(dāng)作隊(duì)列或棧來(lái)使用的。隊(duì)列和棧的特性一個(gè)先進(jìn)先出,一個(gè)先進(jìn)后出。雙向鏈表很好的支持了這些特性。
壓縮列表
ziplist 是 Redis 為了節(jié)約內(nèi)存而開(kāi)發(fā)的,是由一系列特殊編碼的連續(xù)內(nèi)存塊(而不是像雙端鏈表一樣每個(gè)節(jié)點(diǎn)是指針)組成的順序型數(shù)據(jù)結(jié)構(gòu) ,如下圖:
壓縮列表是經(jīng)過(guò)特殊編碼,專門為了提升內(nèi)存使用效率設(shè)計(jì)的。所有的操作都是通過(guò)指針與解碼出來(lái)的偏移量進(jìn)行的。并且壓縮列表的內(nèi)存是連續(xù)分配的,遍歷的速度很快
(3)IO多路復(fù)用
(4)合理的線程模型,單線程避免線程上下文切換、IO多路復(fù)用
(5)漸進(jìn)式rehash、緩存時(shí)間戳
4、項(xiàng)目中如何使用緩存?
變動(dòng)頻率低、查詢頻率高的數(shù)據(jù)做緩存,減輕DB壓力
5、為什么使用緩存?
高性能:數(shù)據(jù)庫(kù)查詢耗時(shí),緩存查詢極快
高并發(fā):mysql單機(jī)QPS 2000左右,redis輕松幾萬(wàn)
6、Redis key 和value 可以存儲(chǔ)最大值分別多是多少?
-
key 的大小上限為 512M,但一般建議 key 大小不要超過(guò) 1KB,這樣既可以節(jié)約存儲(chǔ)空間,又有利于 Redis 進(jìn)行檢索
-
value 的最大值也是 512M。對(duì)于 String 類型value 值上限為 512M,而集合、鏈表、哈希等 key 類型,單個(gè)元素 value 上限也為 512M
7、Redis和memcache有什么區(qū)別?
-
Redis 支持復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
Redis 相比 Memcached 來(lái)說(shuō),擁有更多的數(shù)據(jù)結(jié)構(gòu),能支持更豐富的數(shù)據(jù)操作。如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作, Redis 會(huì)是不錯(cuò)的選擇。
-
Redis 原生支持集群模式
在 Redis3.x 版本中,便能支持 cluster 模式,而 Memcached 沒(méi)有原生的集群模式,需要依靠客戶端來(lái)實(shí)現(xiàn)往集群中分片寫(xiě)入數(shù)據(jù)。
-
性能對(duì)比
由于 Redis 只使用單核,而 Memcached 可以使用多核,所以平均每一個(gè)核上 Redis 在存儲(chǔ)小數(shù)據(jù)時(shí)比Memcached 性能更高。而在 100k 以上的數(shù)據(jù)中,Memcached 性能要高于 Redis。雖然Redis 最近也在存儲(chǔ)大數(shù)據(jù)的性能上進(jìn)行優(yōu)化,但是比起 Memcached,還是稍有遜色
8、說(shuō)說(shuō)redis常用應(yīng)用場(chǎng)景
-
緩存
-
排行榜
-
計(jì)數(shù)器
-
分布式會(huì)話
-
分布式鎖
-
社交網(wǎng)絡(luò)
-
消息隊(duì)列
-
位操作
二、數(shù)據(jù)類型
1、redis有哪些數(shù)據(jù)類型,分別適用于什么場(chǎng)景?
String
這是最簡(jiǎn)單的類型,就是普通的 set 和 get,做簡(jiǎn)單的 KV 緩存。場(chǎng)景:緩存、計(jì)數(shù)、限流等
set college szu
Hash
這個(gè)是類似 map 的一種結(jié)構(gòu),這個(gè)一般就是可以將結(jié)構(gòu)化的數(shù)據(jù),比如一個(gè)對(duì)象(前提是這 個(gè)對(duì)象沒(méi)嵌套其他的對(duì)象)給緩存在 Redis 里,然后每次讀寫(xiě)緩存的時(shí)候,可以就操作 hash里的某個(gè)字段。場(chǎng)景:用戶信息、商品信息等
hset person name bingo
hset person age 20
hset person id 1
hget person name
person = {
"name": "bingo",
"age": 20,
"id": 1
}
List
Lists 是有序列表,這個(gè)可以玩兒出很多花樣。
比如可以通過(guò) list 存儲(chǔ)一些列表型的數(shù)據(jù)結(jié)構(gòu),類似粉絲列表、文章的評(píng)論列表之類的東西。
比如可以通過(guò) lrange 命令,讀取某個(gè)閉區(qū)間內(nèi)的元素,可以基于 list 實(shí)現(xiàn)分頁(yè)查詢,這個(gè)是很
棒的一個(gè)功能,基于 Redis 實(shí)現(xiàn)簡(jiǎn)單的高性能分頁(yè),可以做類似微博那種下拉不斷分頁(yè)的東
西,性能高,就一頁(yè)一頁(yè)走
# 0開(kāi)始位置,-1結(jié)束位置,結(jié)束位置為-1時(shí),表示列表的最后一個(gè)位置,即查看所有。
lrange mylist 0 -1
比如可以搞個(gè)簡(jiǎn)單的消息隊(duì)列,從 list 頭懟進(jìn)去,從 list 尾巴那里弄出來(lái)。
lpush mylist 1
lpush mylist 2
lpush mylist 3 4 5
# 1
rpop mylist
Set
Sets 是無(wú)序集合,自動(dòng)去重,可以基于 set 玩兒交集、并集、差集的操作。常用于進(jìn)行標(biāo)簽管理等
#-------操作一個(gè)set-------
# 添加元素
sadd mySet 1
# 查看全部元素
smembers mySet
# 判斷是否包含某個(gè)值
sismember mySet 3
# 刪除某個(gè)/些元素
srem mySet 1
srem mySet 2 4
# 查看元素個(gè)數(shù)
scard mySet# 隨機(jī)刪除一個(gè)元素
spop mySet
#-------操作多個(gè)set-------
# 將一個(gè)set的元素移動(dòng)到另外一個(gè)set
smove yourSet mySet 2
# 求兩set的交集
sinter yourSet mySet
# 求兩set的并集
sunion yourSet mySet
# 求在yourSet中而不在mySet中的元素
sdiff yourSet mySet
Sorted Set
Sorted Sets 是排序的 set,去重但可以排序,寫(xiě)進(jìn)去的時(shí)候給一個(gè)分?jǐn)?shù),自動(dòng)根據(jù)分?jǐn)?shù)排序。排行榜。
zadd board 85 zhangsan
zadd board 72 lisi
zadd board 96 wangwu
zadd board 63 zhaoliu
2、說(shuō)說(shuō)Redis底層數(shù)據(jù)結(jié)構(gòu)?
Redis有動(dòng)態(tài)字符串(sds)、鏈表(list)、字典(ht)、跳躍表(skiplist)、整數(shù)集合(intset)、壓縮列表(ziplist) 等底層數(shù)據(jù)結(jié)構(gòu)。 Redis并沒(méi)有使用這些數(shù)據(jù)結(jié)構(gòu)來(lái)直接實(shí)現(xiàn)鍵值對(duì)數(shù)據(jù)庫(kù),而是基于這些數(shù)據(jù)結(jié)構(gòu)創(chuàng)建了一個(gè)對(duì)象系統(tǒng),來(lái)表示所有的key-value
我們常用的數(shù)據(jù)類型和編碼對(duì)應(yīng)的映射關(guān)系:
三、架構(gòu)
1、redis 持久化機(jī)制
(1)Redis 的持久化機(jī)制
Redis 的持久化機(jī)制有:RDB、AOF、混合持久化(RDB+AOF,Redis 4.0引入)。RDB 和 AOF 都是 Redis 里面提供的持久化機(jī)制,RDB 是通過(guò)快照方式實(shí)現(xiàn)持久化、AOF 是通過(guò)命令追加的方式實(shí)現(xiàn)持久化
- RDB
RDB 持久化機(jī)制會(huì)根據(jù)快照觸發(fā)條件,把內(nèi)存里面的數(shù)據(jù)快照寫(xiě)入到磁盤,以二進(jìn)制的壓縮文件進(jìn)行存儲(chǔ)
RDB 快照的觸發(fā)方式有很多,比如
-
執(zhí)行 bgsave 命令觸發(fā)異步快照,執(zhí)行 save 命令觸發(fā)同步快照,同步快照會(huì)阻塞客戶端的執(zhí)行指令。
-
根據(jù) redis.conf 文件里面的配置,自動(dòng)觸發(fā) bgsave
-
主從復(fù)制的時(shí)候觸發(fā)
-
AOF
AOF持久化機(jī)制是近乎實(shí)時(shí)的方式來(lái)完成持久化的,就是客戶端執(zhí)行一個(gè)數(shù)據(jù)變更的操作,Redis Server 就會(huì)把這個(gè)命令追加到 aof 緩沖區(qū)的末尾,然后再把緩沖區(qū)的數(shù)據(jù)寫(xiě)入到磁盤的 AOF 文件里面,至于最終什么時(shí)候真正持久化到磁盤,是根據(jù)刷盤的策略來(lái)決定的
為了避免追加的方式導(dǎo)致 AOF 文件過(guò)大的問(wèn)題,Redis 提供了 AOF 重寫(xiě)機(jī)制(如圖),也就是說(shuō)當(dāng) AOF 文件的大小達(dá)到某個(gè)閾值的時(shí)候,就會(huì)把這個(gè)文件里面相同的指令進(jìn)行壓縮
AOF三種策略
為了控制Redis服務(wù)器在遇到意外停機(jī)時(shí)丟失的數(shù)據(jù)量,Redis為AOF持久化提供了appendfsync選項(xiàng),這個(gè)選項(xiàng)的值可以是always,everysec或者noappendfsync
-
always:總是寫(xiě)入aof文件,并通過(guò)事件循環(huán)磁盤同步,即使Redis遭遇意外停機(jī)時(shí),最多只丟失一事件循環(huán)內(nèi)的執(zhí)行的數(shù)據(jù)
-
appendfsync everysec:每一秒寫(xiě)入aof文件,并完成磁盤同步,即使Redis遭遇意外停機(jī)時(shí),最多只丟失一秒鐘內(nèi)的執(zhí)行的數(shù)據(jù)
-
appendfsync no:服務(wù)器不主動(dòng)調(diào)用fdatasync,由操作系統(tǒng)決定任何將緩沖區(qū)里面的命令寫(xiě)入到硬盤里,這種模式下,服務(wù)器遭遇意外停機(jī)時(shí),丟失的命令的數(shù)量是不確定的
(2)RDB和AOF 比較
-
RDB 是每隔一段時(shí)間觸發(fā)持久化,因此數(shù)據(jù)安全性低,AOF 可以做到實(shí)時(shí)持久化,數(shù)據(jù)安全性較高
-
RDB 文件默認(rèn)采用壓縮的方式持久化,AOF 存儲(chǔ)的是執(zhí)行指令,所以 RDB 在數(shù)據(jù)恢復(fù)的時(shí)候性能比 AOF 要好
(3)混合持久化
只發(fā)生于 AOF 重寫(xiě)過(guò)程。使用了混合持久化,重寫(xiě)后的新 AOF 文件前半段是 RDB 格式的全量數(shù)據(jù),后半段是 AOF 格式的增量數(shù)據(jù)。
2、redis集群高可用
Redis高可用常見(jiàn)的有三種方式:
(1)Replication-Sentinel哨兵模式
Redis sentinel 是一個(gè)分布式系統(tǒng)中監(jiān)控 redis 主從服務(wù)器,并在主服務(wù)器下線時(shí)自動(dòng)進(jìn)行故障轉(zhuǎn)移。
Redis sentinel 其中三個(gè)特性:
-
監(jiān)控(Monitoring):
Sentinel 會(huì)不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
-
提醒(Notification):
當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問(wèn)題時(shí), Sentinel 可以通過(guò) API 向管理員或者其他應(yīng)用程序發(fā)送通知。
-
自動(dòng)故障遷移(Automatic failover):
當(dāng)一個(gè)主服務(wù)器不能正常工作時(shí), Sentinel 會(huì)開(kāi)始一次自動(dòng)故障遷移操作。
哨兵本身也有單點(diǎn)故障的問(wèn)題,可以使用多個(gè)哨兵進(jìn)行監(jiān)控,哨兵不僅會(huì)監(jiān)控redis集群,哨兵之間也會(huì)相互監(jiān)控。
每一個(gè)哨兵都是一個(gè)獨(dú)立的進(jìn)程,作為進(jìn)程,它會(huì)獨(dú)立運(yùn)行。
特點(diǎn):
-
保證高可用
-
監(jiān)控各個(gè)節(jié)點(diǎn)
-
自動(dòng)故障遷移
缺點(diǎn):
-
主從模式,切換需要時(shí)間丟數(shù)據(jù)
-
沒(méi)有解決 master 寫(xiě)的壓力
Redis哨兵系統(tǒng)是怎么實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移的?
1.認(rèn)定主節(jié)點(diǎn)主觀下線
因?yàn)槊扛?s,哨兵節(jié)點(diǎn)會(huì)給主節(jié)點(diǎn)發(fā)送PING命令,如果在一定時(shí)間間隔內(nèi),都沒(méi)有收到回復(fù),那么哨兵節(jié)點(diǎn)就認(rèn)為主節(jié)點(diǎn)主觀下線。
2.認(rèn)定主節(jié)點(diǎn)客觀下線
哨兵節(jié)點(diǎn)認(rèn)定主節(jié)點(diǎn)主觀下線后,會(huì)向其他哨兵節(jié)點(diǎn)發(fā)送sentinel is-master-down-by-addr命令,獲取其他哨兵節(jié)點(diǎn)對(duì)該主節(jié)點(diǎn)的狀態(tài),當(dāng)認(rèn)定主節(jié)點(diǎn)下線的哨兵數(shù)量達(dá)到一定數(shù)值時(shí)(這個(gè)閥值是Sentinel配置中quorum參數(shù)的值,通常我們?cè)O(shè)置為哨兵總節(jié)點(diǎn)數(shù)的1/2),就認(rèn)定主節(jié)點(diǎn)客觀下線。
3.進(jìn)行領(lǐng)導(dǎo)者哨兵選舉
認(rèn)定主節(jié)點(diǎn)客觀下線后,各個(gè)哨兵之間相互通信,選舉出一個(gè)領(lǐng)導(dǎo)者哨兵,由它來(lái)對(duì)主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移操作。
選舉使用的是Raft算法,基本思路是所有哨兵節(jié)點(diǎn)A會(huì)向其他哨兵節(jié)點(diǎn)發(fā)送命令,申請(qǐng)成為該哨兵節(jié)點(diǎn)B的領(lǐng)導(dǎo)者,如果B還沒(méi)有同意過(guò)其他哨兵節(jié)點(diǎn),那么就同意A成為領(lǐng)導(dǎo)者,最終得票超過(guò)半數(shù)以上的哨兵節(jié)點(diǎn)會(huì)贏得選舉,如果本次投票,沒(méi)有選舉出領(lǐng)導(dǎo)者哨兵,那么就開(kāi)始新一輪的選舉,直到選舉出哨兵節(jié)點(diǎn)(實(shí)際開(kāi)發(fā)中,最先判定主節(jié)點(diǎn)客觀下線的哨兵節(jié)點(diǎn),一般就能成為領(lǐng)導(dǎo)者。)
-
領(lǐng)導(dǎo)者哨兵進(jìn)行故障轉(zhuǎn)移
領(lǐng)導(dǎo)者哨兵節(jié)點(diǎn)首先會(huì)從從節(jié)點(diǎn)中選出一個(gè)節(jié)點(diǎn)作為新的主節(jié)點(diǎn)。選擇的規(guī)則是:
-
1.首先排除一些不健康的節(jié)點(diǎn)。(下線的,斷線的,最近5s沒(méi)有回復(fù)哨兵節(jié)點(diǎn)的INFO命令的,與舊的主服務(wù)器斷開(kāi)連接時(shí)間較長(zhǎng)的)
-
2.然后根據(jù)優(yōu)先級(jí),復(fù)制偏移量,runid最小,來(lái)選出一個(gè)從節(jié)點(diǎn)作為主節(jié)點(diǎn)。
向這個(gè)從節(jié)點(diǎn)發(fā)送slaveof no one命令,讓其成為主節(jié)點(diǎn),通過(guò)slaveof 命令讓其他從節(jié)點(diǎn)成為它的從節(jié)點(diǎn),將已下線的主節(jié)點(diǎn)更新為新的主節(jié)點(diǎn)的從節(jié)點(diǎn),將其他從節(jié)點(diǎn)的復(fù)制目標(biāo)改為新的主節(jié)點(diǎn),將舊的主服務(wù)器改為從服務(wù)器。
(2)Redis-Cluster集群模式
redis在3.0上加入了 Cluster 集群模式,實(shí)現(xiàn)了 Redis 的分布式存儲(chǔ),也就是說(shuō)每臺(tái) Redis 節(jié)點(diǎn)上存儲(chǔ)不同的數(shù)據(jù)。
cluster模式為了解決單機(jī)Redis容量有限的問(wèn)題,將數(shù)據(jù)按一定的規(guī)則分配到多臺(tái)機(jī)器,內(nèi)存/QPS不受限于單機(jī),可受益于分布式集群高擴(kuò)展性。
RedisCluster 是 Redis 的親兒子,它是 Redis 作者自己提供的 Redis 集群化方案。
相對(duì)于 Codis 的不同,它是去中心化的,如圖所示,該集群有三個(gè) Redis 節(jié)點(diǎn)組成, 每個(gè)節(jié)點(diǎn)負(fù)責(zé)整個(gè)集群的一部分?jǐn)?shù)據(jù),每個(gè)節(jié)點(diǎn)負(fù)責(zé)的數(shù)據(jù)多少可能不一樣。這三個(gè)節(jié)點(diǎn)相 互連接組成一個(gè)對(duì)等的集群,它們之間通過(guò)一種特殊的二進(jìn)制協(xié)議相互交互集群信息。
如上圖,官方推薦,集群部署至少要 3 臺(tái)以上的master節(jié)點(diǎn),最好使用 3 主 3 從六個(gè)節(jié)點(diǎn)的模式。
Redis Cluster 將所有數(shù)據(jù)劃分為 16384 的 slots,它比 Codis 的 1024 個(gè)槽劃分得更為精細(xì),每個(gè)節(jié)點(diǎn)負(fù)責(zé)其中一部分槽位。槽位的信息存儲(chǔ)于每個(gè)節(jié)點(diǎn)中,它不像 Codis,它不 需要另外的分布式存儲(chǔ)來(lái)存儲(chǔ)節(jié)點(diǎn)槽位信息。 Redis Cluster是一種服務(wù)器Sharding技術(shù)(分片和路由都是在服務(wù)端實(shí)現(xiàn)),采用多主多從,每一個(gè)分區(qū)都是由一個(gè)Redis主機(jī)和多個(gè)從機(jī)組成,片區(qū)和片區(qū)之間是相互平行的。
Redis Cluster集群采用了P2P的模式,完全去中心化。
3 主 3 從六個(gè)節(jié)點(diǎn)的Redis集群(Redis-Cluster) Redis 集群是一個(gè)提供在多個(gè)Redis節(jié)點(diǎn)間共享數(shù)據(jù)的程序集。下圖以三個(gè)master節(jié)點(diǎn)和三個(gè)slave節(jié)點(diǎn)作為示例。
Redis 集群有16384個(gè)哈希槽,每個(gè)key通過(guò)CRC16校驗(yàn)后對(duì)16384取模來(lái)決定放置哪個(gè)槽。集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash槽,如圖中slots所示。
為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無(wú)法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有1-n個(gè)從節(jié)點(diǎn)。例如master-A節(jié)點(diǎn)不可用了,集群便會(huì)選舉slave-A節(jié)點(diǎn)作為新的主節(jié)點(diǎn)繼續(xù)服務(wù)。
3、redis事務(wù)怎么理解?
multi 開(kāi)啟事務(wù)
exec 提交事務(wù)
discard 回滾事務(wù)
4、redis的過(guò)期策略及內(nèi)存淘汰機(jī)制?
1.過(guò)期策略
-
定期刪除:每隔 100ms 就隨機(jī)抽取一些設(shè)置了過(guò)期時(shí)間的 key,檢查其是否過(guò)期,如果過(guò)期就刪除
-
惰性刪除:獲取 key 的時(shí)候,如果此時(shí) key 已經(jīng)過(guò)期,就刪除,不會(huì)返回任何東西
2.內(nèi)存淘汰機(jī)制:
-
noeviction: 當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),新寫(xiě)入操作會(huì)報(bào)錯(cuò)
-
allkeys-lru:移除最近最少使用的 key
-
allkeys-random:隨機(jī)移除某個(gè) key
-
volatile-lru:在設(shè)置了過(guò)期時(shí)間的鍵空間中,移除最近最少使用的 key
-
volatile-random:在設(shè)置了過(guò)期時(shí)間的鍵空間中,隨機(jī)移除某個(gè) key
-
volatile-ttl:設(shè)置了過(guò)期時(shí)間的鍵空間中,有更早過(guò)期時(shí)間的 key 優(yōu)先移除
5、布隆過(guò)濾器是什么?
布隆過(guò)濾器可以理解為一個(gè)有誤差的set結(jié)構(gòu),使用布隆過(guò)濾器來(lái)判斷元素是否存在其中時(shí),如果返回結(jié)果是存在,實(shí)際可能存在也可能不存在,返回結(jié)果不存在時(shí),實(shí)際結(jié)果肯定是不存在。
布隆過(guò)濾器實(shí)際上是一個(gè)大型的位數(shù)組,添加key時(shí),通過(guò)幾個(gè)hash函數(shù)對(duì)key計(jì)算得到多個(gè)hash值,將每個(gè)hash值與布隆過(guò)濾器的位數(shù)組的size取模得到下標(biāo),然后將數(shù)組中這些下標(biāo)位置的值都設(shè)置為1。
創(chuàng)建key為userid的布隆過(guò)濾器,0.01是誤判率,10000是初始大小
127.0.0.1:6379> bf.reserve userid 0.01 100000
調(diào)用exist指令判斷181920是否存在于布隆過(guò)濾器,如果返回0,不存在,那么說(shuō)明一定不存在,如果返回1,代表可能存在,也可能不存在。
127.0.0.1:6379> bf.add userid '181920' (integer) 1
布隆過(guò)濾器也有一些缺點(diǎn):
-
它在判斷元素是否在集合中時(shí)是有一定錯(cuò)誤幾率,因?yàn)楣K惴ㄓ幸欢ǖ呐鲎驳母怕省?/p>
-
不支持刪除元素。
6、如何保證數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)的一致性
1.延時(shí)雙刪
-
先刪除緩存
-
更新數(shù)據(jù)庫(kù)
-
線程等待 N秒(等待時(shí)間根據(jù)具體業(yè)務(wù)來(lái)判斷)
-
再刪除緩存
2.采用canal組件監(jiān)控MySQL的binlog日志,把更新后的數(shù)據(jù)同步到redis里面
-
更新數(shù)據(jù)庫(kù)
-
更新redis的數(shù)據(jù)
-
canal組件從binlog加載數(shù)據(jù),然后同步到redis
3.基于 RocketMQ 的可靠性消息通信,來(lái)實(shí)現(xiàn)最終一致性。
7、redis 分布式鎖如何實(shí)現(xiàn)
1、加鎖時(shí)要設(shè)置過(guò)期時(shí)間SET lock_key unique_value EX expire_time NX
2、操作共享資源
3、釋放鎖:Lua腳本,先GET判斷鎖是否歸屬自己,再DEL釋放鎖
集群模式+Redlock實(shí)現(xiàn)高可靠的分布式鎖
讓客戶端和多個(gè)獨(dú)立的Redis實(shí)例依次請(qǐng)求加鎖,如果客戶端能夠和半數(shù)以上的實(shí)例成功地完成加鎖操作,那么我們就認(rèn)為,客戶端成功地獲得分布式鎖了,否則加鎖失敗。
https://blog.csdn.net/fuzhongmin05/article/details/119251590
四、場(chǎng)景
1、緩存穿透、緩存擊穿、緩存雪崩
(1)緩存穿透
緩存穿透是指查詢一個(gè)根本不存在的數(shù)據(jù),緩存層和持久層都不會(huì)命中。
解決方案:參數(shù)校驗(yàn)、緩存空對(duì)象及布隆過(guò)濾器
(2)緩存擊穿
在緩存失效的瞬間,有大量線程來(lái)重建緩存,造成后端負(fù)載加大,甚至可能會(huì)讓?xiě)?yīng)用崩潰。
解決方案:永不過(guò)期或分布式互斥鎖
(3)緩存雪崩
緩存層宕機(jī)或者大量緩存同時(shí)失效,請(qǐng)求直接到達(dá)存儲(chǔ)層,存儲(chǔ)層壓力過(guò)大導(dǎo)致系統(tǒng)雪崩。
解決方案:緩存高可用、避免緩存同時(shí)失效及采用多級(jí)緩存
2、怎么使用redis實(shí)現(xiàn)消息隊(duì)列
-
基于List的LPUSH+BRPOP實(shí)現(xiàn)
-
基于Zset
-
PUB/SUB
-
基于Stream類型
3、什么是bigkey,有什么影響?
-
字符串類型:單個(gè)value值很大,一般超過(guò)10KB就是bigkey
-
非字符串類型:體現(xiàn)在元素過(guò)多
危害:
-
內(nèi)存空間不均勻,redis cluster中,bigkey造成節(jié)點(diǎn)內(nèi)存空間使用不均與
-
超時(shí)阻塞,redis單線程,操作bigkey比較好使,阻塞redis的可能性增大
-
網(wǎng)絡(luò)擁塞,每次獲取bigkey產(chǎn)生的網(wǎng)絡(luò)流量較大
4、怎么處理熱key?
-
什么是熱Key?所謂的熱key,就是訪問(wèn)頻率比較的key。
-
怎么處理熱key?
對(duì)熱key的處理,最關(guān)鍵的是對(duì)熱點(diǎn)key的監(jiān)控,可以從這些端來(lái)監(jiān)控?zé)狳c(diǎn)key:
-
客戶端 客戶端其實(shí)是距離key“最近”的地方,因?yàn)镽edis命令就是從客戶端發(fā)出的,例如在客戶端設(shè)置全局字典(key和調(diào)用次數(shù)),每次調(diào)用Redis命令時(shí),使用這個(gè)字典進(jìn)行記錄。
-
代理端 像Twemproxy、Codis這些基于代理的Redis分布式架構(gòu),所有客戶端的請(qǐng)求都是通過(guò)代理端完成的,可以在代理端進(jìn)行收集統(tǒng)計(jì)。
-
Redis服務(wù)端 使用monitor命令統(tǒng)計(jì)熱點(diǎn)key是很多開(kāi)發(fā)和運(yùn)維人員首先想到,monitor命令可以監(jiān)控到Redis執(zhí)行的所有命令。
只要監(jiān)控到了熱key,對(duì)熱key的處理就簡(jiǎn)單了:
-
把熱key打散到不同的服務(wù)器,降低壓?
-
加??級(jí)緩存,提前加載熱key數(shù)據(jù)到內(nèi)存中,如果redis宕機(jī),?內(nèi)存查詢
5、緩存預(yù)熱怎么做呢?
所謂緩存預(yù)熱,就是提前把數(shù)據(jù)庫(kù)里的數(shù)據(jù)刷到緩存里,通常有這些方法:
-
直接寫(xiě)個(gè)緩存刷新頁(yè)面或者接口,上線時(shí)手動(dòng)操作
-
數(shù)據(jù)量不大,可以在項(xiàng)目啟動(dòng)的時(shí)候自動(dòng)進(jìn)行加載
-
定時(shí)任務(wù)刷新緩存
6、Redis里面有1億個(gè)key,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開(kāi)頭的,如何將它們?nèi)空页鰜?lái)?
使用keys指令可以掃出指定模式的key列表。
對(duì)方接著追問(wèn):
如果這個(gè)redis正在給線上的業(yè)務(wù)提供服務(wù),那使用keys指令會(huì)有什么問(wèn)題?
這個(gè)時(shí)候你要回答redis關(guān)鍵的一個(gè)特性:
redis的單線程的。
keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間,線上服務(wù)會(huì)停頓,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)。
這個(gè)時(shí)候可以使用scan指令,scan指令可以無(wú)阻塞的提取出指定模式的key列表,但是會(huì)有一定的重復(fù)概率,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會(huì)比直接用keys指令長(zhǎng)。