先來(lái)了解1) 什么是 Redis Redis(Remote Dictionary Server)是一個(gè)使用C語(yǔ)言 編寫的,開源的(BSD許可)高性能非關(guān)系型(NoSQL) 的鍵值對(duì)數(shù)據(jù)庫(kù) Redis可以存儲(chǔ)鍵和五種不同類型的值之間的映射。 Redis 支持很多特性,例如將內(nèi)存中的數(shù)據(jù)持久化到硬盤中,使用復(fù)制來(lái)擴(kuò)展讀性能,使用分片來(lái)擴(kuò)展寫性能。所以讀寫速度非???,因此Redis被廣泛應(yīng)用于緩存方向,每秒可以處理超過(guò)10萬(wàn)次讀寫操作,是已知性能最快的key-value 數(shù)據(jù)庫(kù)。另外 Redis 也經(jīng)常用來(lái)做分布式鎖,而且 Redis 支持事務(wù),持久化,LUA腳本,LRU驅(qū)動(dòng)事件,多種集群方案等。
2)Redis為什么那么快 完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作 數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單,Redis中的數(shù)據(jù)結(jié)構(gòu)是專門為各種場(chǎng)景設(shè)計(jì)的 采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗CPU,不用去考慮各種鎖的問(wèn)題,不存在加鎖釋放鎖操作,沒(méi)有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗 使用多路 I/O 復(fù)用模型,非阻塞 IO
3)Redis 的優(yōu)缺點(diǎn) 優(yōu)點(diǎn): 讀寫速度快,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類似于HashMap 支持豐富的數(shù)據(jù)類型,支持 String,List,Hash,Set,SortSet(Zset) 支持事務(wù)(一致性和隔離性),利用好RDB和AOF也能實(shí)現(xiàn)持久性 支持主從復(fù)制,主機(jī)會(huì)自動(dòng)將數(shù)據(jù)同步到從機(jī),可以進(jìn)行讀寫分離
缺點(diǎn): 緩存和數(shù)據(jù)庫(kù)雙寫一致性問(wèn)題 緩存雪崩、穿透、擊穿問(wèn)題 Redis 較難支持在線擴(kuò)容,在集群容量達(dá)到上限時(shí)擴(kuò)容會(huì)變得很復(fù)雜 主機(jī)宕機(jī)前會(huì)有部分?jǐn)?shù)據(jù)未能及時(shí)同步到從機(jī),切換IP后還會(huì)引入數(shù)據(jù)不一致問(wèn)題,降低了系統(tǒng)的可用性 緩存的并發(fā)競(jìng)爭(zhēng)問(wèn)題
4)Redis與Memcache的區(qū)別 數(shù)據(jù)類型 Memcached僅支持字符串類型 Redis 支持五種不同的數(shù)據(jù)類型,可以更靈活地解決問(wèn)題 數(shù)據(jù)持久化 Memcached 不支持持久化 Redis 支持兩種持久化策略:RDB快照 和 AOF 日志 分布式 Memcached 不支持分布式,只能通過(guò)在客戶端使用一致性哈希來(lái)實(shí)現(xiàn)分布式存儲(chǔ),這種方式在存儲(chǔ)和查詢時(shí)都需要先在客戶端計(jì)算一次數(shù)據(jù)所在的節(jié)點(diǎn) Redis Cluster 支持分布式 內(nèi)存管理機(jī)制 Redis 中,并不是所有數(shù)據(jù)都一直存儲(chǔ)在內(nèi)存中,可以將一些很久沒(méi)用的 value 交換到磁盤 Memcached 的數(shù)據(jù)一直會(huì)在內(nèi)存中,它將內(nèi)存分割成特定長(zhǎng)度的塊來(lái)存儲(chǔ)數(shù)據(jù),以完全解決內(nèi)存碎片的問(wèn)題,但是這種方式會(huì)使得內(nèi)存的利用率不高,例如塊的大小為 128 bytes,只存儲(chǔ) 100 bytes 的數(shù)據(jù),那么剩下的 28 bytes 就浪費(fèi)了
5)Redis有哪些數(shù)據(jù)類型 > set test cbucok ---------------------------- > get test'cbuc' ---------------------------- > del test(integer) 1 ---------------------------- >get test(nil)
> rpush test c1(integer) 1 ---------------------------- > rpush test c2(integer) 2 ---------------------------- > rpush test c2(integer) 3 ---------------------------- > lrange test 0 -11) 'c1'2) 'c2'3) 'c3' ---------------------------- > lindex test 1'c2' ---------------------------- > lpop test'c1' ---------------------------- > lrange test 0 -1'c2''c2'
> hset test name cbuc(integer) 1 ---------------------------- > hset test age 23(integer) 1 ---------------------------- > hgetall test1)'name'2)'cbuc'3)'age'4)'23' ---------------------------- > hdel test age(integer) 1 ---------------------------- > hget test name 'cbuc' ---------------------------- > hgetall test1)'name'2)'cbuc'
> sadd test c1(integer) 1 > sadd test c2(integer) 1 > sadd test c1(integer) 0 ---------------------------- >smembers test1)'c1'2)'c2' ---------------------------- > sismember test c3(integer) 0 > sismember test c1(integer) 1 ---------------------------- > srem test c1(integer) 1 ---------------------------- > smembers test1)'c2'
> zadd test 92 math(integer) 1 > zadd test 88 english(integer) 1 > zadd test 92 score(integer) 1 ---------------------------- > zrange test 0 -1 withscores1)'english'2)'88'3)'math'4)'92' ---------------------------- > zrangebyscore test 80 90 withscores1)'english'2)'88' ---------------------------- > zrem test english(integer) 1 ---------------------------- > zrange test 0 -1 withscores3)'math'4)'92'
高級(jí)用法: BitMap位圖是支持按 bit 位來(lái)存儲(chǔ)信息,可以用來(lái)實(shí)現(xiàn) 布隆過(guò)濾器(BloomFilter) HyperLogLog供不精確的去重計(jì)數(shù)功能,比較適合用來(lái)做大規(guī)模數(shù)據(jù)的去重統(tǒng)計(jì),例如統(tǒng)計(jì) UV Geospatial可以用來(lái)保存地理位置,并作位置距離計(jì)算或者根據(jù)半徑計(jì)算位置等。可以用來(lái)實(shí)現(xiàn)附近的人,或者計(jì)算最優(yōu)地圖路徑
6)什么是Redis持久化 持久化就是把內(nèi)存中的數(shù)據(jù)寫到磁盤中去,防止服務(wù)宕機(jī)了內(nèi)存數(shù)據(jù)丟失。 7)Redis的持久化機(jī)制 Redis提供兩種持久化機(jī)制:RDB快照(默認(rèn))和AOF(機(jī)制) RDB RDB(Redis DataBase)是Redis中默認(rèn)的持久化方式。按照一定的時(shí)間將內(nèi)存的數(shù)據(jù)以快照的形式保存到磁盤中,會(huì)產(chǎn)生dump.rdb數(shù)據(jù)文件,可以通過(guò)配置文件中的save參數(shù)來(lái)定義快照的周期。
原理: fork和cow。fork 是指 redis間隔一段時(shí)間會(huì) fork 一個(gè)子進(jìn)程,子線程將數(shù)據(jù)寫到磁盤上一個(gè)臨時(shí)RDB文件中,當(dāng)子進(jìn)程寫完臨時(shí)文件后,將原來(lái)的RDB替換掉,這樣的好處是可以 cow(copy-on-wirte) 優(yōu)點(diǎn): 方便持久化,只有一個(gè)文件 dump.rdb 容災(zāi)性好,一個(gè)文件可以保存到安全的磁盤中 性能最大化,fork 子進(jìn)程來(lái)完成寫操作,讓主進(jìn)程繼續(xù)處理命令,所以是IO最大化。使用單獨(dú)的進(jìn)程來(lái)進(jìn)行持久化,主進(jìn)程不會(huì)進(jìn)行任何IO操作,保證 redis 的高性能
缺點(diǎn): 數(shù)據(jù)安全性低,RDB是間隔一段時(shí)間來(lái)進(jìn)行持久化,如果持久化之間 redis 發(fā)生故障,會(huì)發(fā)生數(shù)據(jù)丟失,所以這種方式更適合數(shù)據(jù)要求不嚴(yán)謹(jǐn)?shù)臅r(shí)候用 保存時(shí)間長(zhǎng),如果數(shù)據(jù)量很大,保存快照的時(shí)間會(huì)很長(zhǎng)
AOF AOF(Append-Only-File),是將 Redis 執(zhí)行的每次寫命令記錄到單獨(dú)的日志文件中,當(dāng)重啟 Redis 會(huì)重新將持久化的日志中文件恢復(fù)數(shù)據(jù)
原理: 將寫命令添加到 AOF 文件(Append Only File)的末尾。使用AOF持久化需要設(shè)置同步選項(xiàng),從而確保寫命令同步到磁盤文件上的時(shí)機(jī)。這是因?yàn)閷?duì)文件進(jìn)行寫入并不會(huì)馬上將內(nèi)容同步到磁盤上,而是先存儲(chǔ)到緩沖區(qū),然后由操作系統(tǒng)決定什么時(shí)候同步到磁盤。同步選項(xiàng): 選項(xiàng) 同步頻率 no 讓操作系統(tǒng)決定何時(shí)同步 always 每個(gè)寫命令都同步 everysec 每秒同步一次 no: 并不能給服務(wù)器性能帶來(lái)多大的提升,而且也會(huì)增加系統(tǒng)奔潰時(shí)數(shù)據(jù)丟失的數(shù)量 always: 嚴(yán)重減低服務(wù)器性能 everysec: 這個(gè)選項(xiàng)比較合適,可以保證系統(tǒng)奔潰時(shí)只會(huì)丟失一秒左右的數(shù)據(jù),并且 Redis 每秒執(zhí)行一次同步對(duì)服務(wù)器性能幾乎沒(méi)有任何影響
隨著服務(wù)器寫請(qǐng)求的增多,AOF文件會(huì)越來(lái)越大。Redis提供了一種將AOF重寫的特性auto-aof-rewrite,能夠去除AOF文件中的冗余寫命令 優(yōu)點(diǎn): 缺點(diǎn): 兩者比較 8)如何選擇合適的持久化方式 一般來(lái)說(shuō)兩者都會(huì)配置。如果單獨(dú)用 RDB 的話你會(huì)丟失很多數(shù)據(jù),單獨(dú)用 AOF,你數(shù)據(jù)恢復(fù)沒(méi)有 RDB 來(lái)的快,如果系統(tǒng)出現(xiàn)問(wèn)題的時(shí)候我們可以先用 RDB 恢復(fù),然后用 AOF 補(bǔ)全數(shù)據(jù)。冷熱備份一起用,才能保證高健壯性的系統(tǒng)。 9)Redis的過(guò)期鍵刪除策略 定時(shí)刪除每個(gè)設(shè)置過(guò)期時(shí)間的 key 都需要?jiǎng)?chuàng)建一個(gè)定時(shí)器,到過(guò)期時(shí)間就會(huì)立即清除。該策略可以立即清除過(guò)期的數(shù)據(jù),對(duì)內(nèi)存很友好;但是會(huì)占用大量的CPU資源來(lái)處理過(guò)期的數(shù)據(jù),從而影響緩存的響應(yīng)時(shí)間和吞吐量 惰性刪除只有當(dāng)訪問(wèn)一個(gè) key 時(shí),才會(huì)判斷該 key 是否已過(guò)期,是則刪除。該策略可以最大化節(jié)省CPU資源,卻對(duì)內(nèi)存非常不友好。極端情況下可能出現(xiàn)大量的過(guò)期 key 沒(méi)有再次被訪問(wèn),從而不會(huì)被清除,占用大量?jī)?nèi)存 定期刪除每隔一定時(shí)間,會(huì)掃描一定數(shù)量的 expires 字典中的 key,并清除其中已過(guò)期的 key。該策略是前兩者的一個(gè)折中方法。通過(guò)調(diào)整定時(shí)掃描的時(shí)間間隔和每次掃描的限定耗時(shí),可以在不同情況下使得CPU和內(nèi)存資源達(dá)到最優(yōu)的平衡效果。
Redis 一般同時(shí)使用 惰性過(guò)期 和 定期過(guò)期 兩種過(guò)期策略 10)Redis 內(nèi)存淘汰策略 設(shè)置過(guò)期時(shí)間的鍵空間選擇性移除 volatile-lru:嘗試回收最少使用的鍵使得新添加的數(shù)據(jù)有空間存放。 volatile-random:回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放 volatile-ttl:優(yōu)先回收存活時(shí)間較短的鍵使得新添加的數(shù)據(jù)有空間存放
全局的鍵空間選擇性移除 allkeys-lru:嘗試回收最少使用的鍵使得新添加的數(shù)據(jù)有空間存放。 allkeys-random:回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放 noeviction:當(dāng)內(nèi)存達(dá)到限制并且客戶端嘗試執(zhí)行,會(huì)返回錯(cuò)誤
11)Redis 事務(wù) Redis 事務(wù)的本質(zhì)是通過(guò) MULTI、EXEC、WATCH、DISCARD四個(gè)原語(yǔ)實(shí)現(xiàn)的。事務(wù)支持一次執(zhí)行多個(gè)命令,一個(gè)事務(wù)中所有命令都會(huì)被序列化。在事務(wù)執(zhí)行過(guò)程,會(huì)按照順序串行化執(zhí)行隊(duì)列中的命令,其他客戶端提交的命令請(qǐng)求不會(huì)插入到事務(wù)執(zhí)行命令序列中??偨Y(jié):Redis 事務(wù)就是一次性、順序性、排他性的執(zhí)行一個(gè)隊(duì)列中的一系列命令。 Redis 不支持回滾,Redis 在事務(wù)失敗時(shí)不進(jìn)行回滾,而是繼續(xù)執(zhí)行余下的命令,所以 Redis 的內(nèi)部可以保持簡(jiǎn)單且快速。 如果在一個(gè)事務(wù)中的命令出現(xiàn)錯(cuò)誤,那么所有的命令都不會(huì)執(zhí)行 如果在一個(gè)事務(wù)中出現(xiàn)運(yùn)行錯(cuò)誤,那么正確的命令會(huì)被執(zhí)行四個(gè)原語(yǔ) WATCH: 是一個(gè)樂(lè)觀鎖,可以為 Redis 事務(wù)提供 check-and-set(CAS)行為,可以監(jiān)控一個(gè)或多個(gè)鍵。一旦其中有一個(gè)鍵被修改(或刪除),之后的事務(wù)就不會(huì)執(zhí)行,監(jiān)控一直持續(xù)到EXEC命令 MULTI: 用于開啟一個(gè)事務(wù),它總是返回OK。MULTI執(zhí)行之后,客戶端可以繼續(xù)向服務(wù)器發(fā)送任意多條命令,這些命令不會(huì)立即被執(zhí)行,而是被放到一個(gè)隊(duì)列中,當(dāng) EXEC命令被調(diào)用時(shí),所有隊(duì)列中的命令才會(huì)被執(zhí)行 EXEC: 執(zhí)行所有事務(wù)塊內(nèi)的命令,返回事務(wù)塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列,當(dāng)操作被打斷時(shí),返回控制 nil DISCARD: 調(diào)用 DISCARD ,客戶端可以清空事務(wù)隊(duì)列,并放棄執(zhí)行事務(wù),并且客戶端會(huì)從事務(wù)狀態(tài)中退出
12)Redis設(shè)置過(guò)期時(shí)間和永久有效 EXPIRE 和 PERSIST 命令 13)緩存雪崩 緩存雪崩是指緩存同一時(shí)間大面積的失效,所以,后面的請(qǐng)求都會(huì)落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉解決方法: 緩存數(shù)據(jù)的過(guò)期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過(guò)期現(xiàn)象發(fā)生 一般并發(fā)量不是特別多的時(shí)候,使用最多的解決方案是加鎖排隊(duì) 搭建集群,如果一臺(tái) Redis 掛掉之后,還有其他的可以繼續(xù)工作
14)緩存擊穿 緩存擊穿是指緩存中沒(méi)有但數(shù)據(jù)庫(kù)中有的數(shù)據(jù)(一般是緩存時(shí)間到期),這時(shí)由于并發(fā)用戶特別多,同時(shí)讀緩存沒(méi)讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫(kù)去取數(shù)據(jù),引起數(shù)據(jù)庫(kù)壓力瞬間增大解決方法: 設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過(guò)期 可以使用互斥鎖更新,保證同一個(gè)進(jìn)程中針對(duì)同一個(gè)數(shù)據(jù)不會(huì)并發(fā)請(qǐng)求到 DB,減小 DB 壓力 使用隨機(jī)退避方式,失效時(shí)隨機(jī) sleep 一個(gè)很短的時(shí)間,再次查詢,如果失敗再執(zhí)行更新
15)緩存穿透 緩存穿透是指緩存和數(shù)據(jù)庫(kù)中都沒(méi)有的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉解決方法: 對(duì)于不存在的數(shù)據(jù),在緩存中保存一個(gè)數(shù)據(jù)進(jìn)行標(biāo)記,并設(shè)置上過(guò)期時(shí)間,防止相同的數(shù)據(jù)請(qǐng)求再次訪問(wèn) DB。 使用 BloomFilter 過(guò)濾器,布隆過(guò)濾器的特點(diǎn)是存在性檢測(cè),如果布隆過(guò)濾器中不存在,那么數(shù)據(jù)一定不存在;如果布隆過(guò)濾器中存在,實(shí)際數(shù)據(jù)也有可能會(huì)不存在。
16)Redis主從架構(gòu) 單機(jī)的 Redis,能夠承載的 QPS 大概在上萬(wàn)到幾萬(wàn)不等,對(duì)于緩存來(lái)說(shuō),一般都是用來(lái)支撐讀高并發(fā)的。如果一臺(tái)機(jī)器讀寫合一的那會(huì)很容易發(fā)生問(wèn)題。因此會(huì)采用主從架構(gòu),讓 master 去處理寫操作,然后把數(shù)據(jù)同步到 slave 上,slave 負(fù)責(zé)讀操作。這樣就會(huì)分發(fā)掉大量的請(qǐng)求,而且在擴(kuò)容的時(shí)候還可以輕松實(shí)現(xiàn)水平擴(kuò)容。 當(dāng)啟動(dòng)一臺(tái) slave 的時(shí)候,它會(huì)發(fā)送一個(gè) psync 命令到 master ,如果是第一次同步,主節(jié)點(diǎn)會(huì)做一次bgsave,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存buffer,待完成后將RDB文件全量同步到復(fù)制節(jié)點(diǎn),復(fù)制節(jié)點(diǎn)接收完成后將RDB鏡像加載到內(nèi)存然后寫入本地磁盤。處理完成后,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過(guò)程。后續(xù)的增量數(shù)據(jù)通過(guò)AOF日志同步即可,類似于數(shù)據(jù)庫(kù)的binlog。 17)Redis實(shí)現(xiàn)分布式鎖 簡(jiǎn)單來(lái)說(shuō)就是先拿setnx來(lái)爭(zhēng)搶鎖,搶到之后,再用expire給鎖加一個(gè)過(guò)期時(shí)間防止鎖忘記了釋放SETNX 是【SET if Not eXists】(如果不存在,則 SET)的簡(jiǎn)寫。當(dāng)且僅當(dāng) key 不存在,將 key 的值設(shè)為 value。 若給定的 key 已經(jīng)存在,則 SETNX 不做任何動(dòng)作。返回值:設(shè)置成功,返回 1 。設(shè)置失敗,返回 0 。 18)Redis的同步機(jī)制 Redis可以使用主從同步,從從同步。第一次同步時(shí),主節(jié)點(diǎn)會(huì)做一次bgsave,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存buffer,待完成后將RDB文件全量同步到復(fù)制節(jié)點(diǎn),復(fù)制節(jié)點(diǎn)接收完成后將RDB鏡像加載到內(nèi)存然后寫入本地磁盤。處理完成后,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過(guò)程。后續(xù)的增量數(shù)據(jù)通過(guò)AOF日志同步即可,類似于數(shù)據(jù)庫(kù)的binlog。 19)Redis集群原理 Redis Sentinel(哨兵)著眼于高可用,在master 宕機(jī)時(shí)會(huì)自動(dòng)將slave提升為master,繼續(xù)提供服務(wù)。Redis Cluster(集群)著眼于擴(kuò)展性,在單個(gè)redis內(nèi)存不足時(shí),使用Cluster進(jìn)行分片存儲(chǔ)。選主策略: 20)Redis 哨兵模式 哨兵必須用三個(gè)實(shí)例去保證自己的健壯性,哨兵 + 主從 并不能保證數(shù)據(jù)不丟失 ,但是可以保證集群的高可用。工作原理: 每個(gè) Sentinel 節(jié)點(diǎn)以每秒一次的頻率向它所知的主服務(wù)器、從服務(wù)器和其他 Sentinel 節(jié)點(diǎn)發(fā)送一個(gè) PING 命令 如果 一個(gè)實(shí)例舉例最后一次有效回復(fù) PING 命令的時(shí)間超過(guò) down-after-milliseconds 所指定的值,那么這個(gè)實(shí)例就會(huì)被標(biāo)記為主觀下線 如果一個(gè)主服務(wù)器被標(biāo)記為主觀下線,那么正在監(jiān)視這個(gè)服務(wù)器的所有 Sentinel 節(jié)點(diǎn)會(huì)以每秒一次的頻率確認(rèn)主服務(wù)器的確進(jìn)入了主觀下線狀態(tài) 如果有足夠數(shù)量的 Sentinel (至少要達(dá)到配置文件中指定的數(shù)量)在指定的時(shí)間范圍內(nèi)同意這一判斷,那么這個(gè)主服務(wù)器就會(huì)被標(biāo)記為客觀下線 當(dāng)主服務(wù)器被標(biāo)記為客觀下線后,Sentinel 節(jié)點(diǎn)會(huì)向下線主服務(wù)器的所有從服務(wù)器發(fā)送 INFO 命令的頻率從 10 秒一次改為每秒一次 Sentinel 節(jié)點(diǎn)會(huì)協(xié)商客觀下線主服務(wù)器的狀態(tài),如果處于 SDOWN 狀態(tài),則投票自動(dòng)選出新的主節(jié)點(diǎn),將剩下從節(jié)點(diǎn)指向新的主節(jié)點(diǎn)進(jìn)行數(shù)據(jù)復(fù)制。 當(dāng)沒(méi)有足夠數(shù)量的 Sentinel 節(jié)點(diǎn)泳衣主服務(wù)器下線是,主服務(wù)器的客觀下線狀態(tài)就會(huì)被移除。或者當(dāng)主服務(wù)器重新向 Sentinel 的 PING 命令返回有效回復(fù)時(shí),主服務(wù)器的主觀下線狀態(tài)就會(huì)被移除
21)腦裂問(wèn)題及解決 何為腦裂: Redis 的集群腦裂是指因?yàn)榫W(wǎng)絡(luò)問(wèn)題,導(dǎo)致 redis master 節(jié)點(diǎn)跟 redis slave 節(jié)點(diǎn)和 sentinel 集群處于不用的網(wǎng)絡(luò)分區(qū),此時(shí)因?yàn)?sentinel 集群無(wú)法感知到 master 的存在,所以將 slave 節(jié)點(diǎn)提升為 master 節(jié)點(diǎn)。此時(shí)存在兩個(gè)不同的 master 節(jié)點(diǎn),就像是一個(gè)大腦分裂成了兩個(gè)。這時(shí)如果客戶端還在基于原來(lái)的 master 節(jié)點(diǎn)繼續(xù)寫入數(shù)據(jù),那么新的 master 節(jié)點(diǎn)將無(wú)法同步這些數(shù)據(jù),當(dāng)網(wǎng)絡(luò)問(wèn)題解決之后,sentinel集群就會(huì)將原先的 master 節(jié)點(diǎn)降為 slave 節(jié)點(diǎn),此時(shí)再?gòu)男碌?master 中同步數(shù)據(jù),將會(huì)造成大量的數(shù)據(jù)丟失
解決: 通常采用隔離(Fencing)機(jī)制 共享存儲(chǔ)Fencing:確保只有一個(gè) Master 往共享存儲(chǔ)中寫數(shù)據(jù) 客戶端Fencing:確保只有一個(gè) Master 可以響應(yīng)客戶端的請(qǐng)求 Slave Fencing:確保只有一個(gè) Master 可以向 Slave 下發(fā)命令 配置文件中修改參數(shù)
min-replicas-to-write 3 # 表示連接到 master 的最少slave數(shù)量min-replicas-max-lag 10 # 表示 slave 連接到 master 的最大延遲時(shí)間
按照上面配置,要求至少3個(gè)slave節(jié)點(diǎn),且數(shù)據(jù)復(fù)制和同步的延遲不能超過(guò)10秒,否則的話 master 就會(huì)拒絕寫請(qǐng)求,配置了這兩個(gè)參數(shù)之后,如果發(fā)生集群腦裂,原先的 master 節(jié)點(diǎn)接收到客戶端的寫入請(qǐng)求或拒絕,就可以減少數(shù)據(jù)同步之后的數(shù)據(jù)丟失。 來(lái)源:掘金 作者:蔡不菜丶
|