Redis之主從集群環境搭建

Redis是?單進程單線程?的,Redis利用隊列技術將并發訪問變為串行訪問,消除了傳統數據庫串行控制的開銷。

Redis為什么是單線程的?

多線程處理會涉及到鎖,而且多線程處理會設計到線程切換而消耗CPU。因為CPU不會Redis的瓶頸,Redis的瓶頸最有可能是機器內存或者網絡帶寬。單線程無法發揮多核CPU性能,不過可以通過在單機開啟Redis實例來解決。

Redis的優勢

**速度快。**因為數據存儲于內存中,類似于HashMap,HashMap的優勢就是查找和操作的時間復雜度都是O(1)

支持豐富的數據類型?,支持string,list,set,sorted set,hash

支持事務?,操作都是原子性,所謂的原子性就是對數據的更改要么全部執行,要么全部不執行

豐富的特性?:可用于緩存,消息,按key設置過期時間,過期后將會自動刪除

Redis和memcached有哪些優勢

memcached所有的值均是簡單的字符串,Reids作為其替代者,支持更為豐富的數據類型

Redis的速度比memcached快很多

Redis可以持久化其數據

Redis支持數據的備份,即master/slave模式的數據備份

Redis key的過期時間和永久有效分別怎么設置?

EXPIRE 和 PERSIST 命令。

Redis 主要消耗什么物理資源?

內存。

為什么Redis需要把所有數據放到內存中?

Redis為了達到最快的讀寫速度將數據都讀到內存中,并通過異步的方式將數據寫入磁盤。

所以redis具有快速和數據持久化的特征。如果不將數據放在內存中,磁盤I/O速度為嚴重影響redis的性能。

在內存越來越便宜的今天,redis將會越來越受歡迎。 如果設置了最大使用的內存,則數據已有記錄數達到內存限值后不能繼續插入新值。

說說Redis哈希槽的概念?

Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節點負責一部分hash槽。

Redis中的管道有什么用?

一次請求/響應服務器能實現處理新的請求即使舊的請求還未被響應。這樣就可以將多個命令發送到服務器,而不用等待回復,最后在一個步驟中讀取該答復。

這就是管道(pipelining),是一種幾十年來廣泛使用的技術。例如許多POP3協議已經實現支持這個功能,大大加快了從服務器下載新郵件的過程。

怎么理解Redis事務?

事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

事務是一個原子操作:事務中的命令要么全部被執行,要么全部都不執行。

Redis 事務相關的命令有哪幾個?

MULTI 、 EXEC 、 DISCARD 、 WATCH

Redis內存回收機制

Redis的內存回收主要圍繞以下兩個方面:

Redis過期策略?:刪除過期時間的key值

Redis淘汰策略?:內存使用到達maxmemory上限時觸發內存淘汰數據

Redis過期策略

Redis過期策略通常有以下三種:

定時過期每個設置過期時間的key都需要創建一個定時器,到過期時間就會立即清除。該策略可以立即清除過期的數據,對內存很友好;但是會占用大量的CPU資源去處理過期的數據,從而影響緩存的響應時間和吞吐量。

惰性過期只有當訪問一個key時,才會判斷該key是否已過期,過期則清除。該策略可以最大化地節省CPU資源,卻對內存非常不友好。極端情況可能出現大量的過期key沒有再次被訪問,從而不會被清除,占用大量內存。

定期過期每隔一定的時間,會掃描一定數量的數據庫的expires字典中一定數量的key,并清除其中已過期的key。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和內存資源達到最優的平衡效果。

Redis中同時使用了?惰性過期?和?定期過期?兩種過期策略。

Redis有哪幾種數據淘汰策略

在Redis中,允許用戶設置最大使用內存大小 server.maxmemory ,當Redis內存數據集大小上升到一定大小的時候,就會執行數據淘汰策略

volatile-lru?:從已設置過期的數據集中挑選最近最少使用的淘汰

volatile-ttl?:從已設置過期的數據集中挑選將要過期的數據淘汰

volatile-random?:從已設置過期的數據集中任意挑選數據淘汰

allkeys-lru?:從數據集中挑選最近最少使用的數據淘汰

allkeys-random?:從數據集中任意挑選數據淘汰

noenviction?:禁止淘汰數據

Redis支持哪幾種持久化方式

RDB持久化原理是將Redis在內存中的數據記錄定時dump到磁盤上的RDB文件。 指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功后,再替換之前的文件,用二進制壓縮存儲。

AOF(append only file)持久化原理是將Redis的操作日志以追加的方式寫入文件。 以日志的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。當服務器重啟的時候會重新執行這些命令來恢復原始的數據。AOF命令以Reids協議追加保存每次寫的操作到文件末尾。Redis還能對AOF文件進行后臺重寫,使得AOF文件的體積不至于過大。

Redis兩種持久化方式優缺點?

RDB持久化

優點:RDB文件緊湊,體積小,網絡傳輸快,適合全量復制;恢復速度比AOF快很多。當然,與AOF相比,RDB最重要的優點之一是對性能的影響相對較小

缺點:RDB文件的致命缺點在與其數據快照的持久化方式決定了必然做不到實時持久化,而在數據越來越重要的今天,數據的大量丟失很多時候是無法接受的,因此AOF持久化稱為主流。此外,RDB文件需要滿足特定格式,兼容性差。

AOF持久化與RDB持久化相對應,AOF的優點在于支持秒級持久化、兼容性好,缺點是文件大,恢復速度慢,對性能影響大

如何選擇Redis持久化方式策略?

在介紹持久化策略之前,首先要明白無論是RDB還是AOF,持久化的開啟都是要付出性能方面的代價的。對比RDB持久化,一方面是bdsave在進行fork操作時Redis主進程會阻塞,另一方面,子進程向硬盤寫數據也會帶來IO壓力;對于AOF持久化,向硬盤寫數據的頻率大大提高(everysec策略下為秒級),IO壓力更大,設置可能造成AOF追加阻塞文件。此外,AOF文件的重寫與RDB的basave類似,會有fork時的阻塞和子進程的IO壓力問題。相對來說,由于AOF向硬盤中寫數據的頻率更高,因此對Redis主進程性能的影響會更大。

在實際生產環境中,根據數據量、應用對數據的安全要求、預算限制等不同情況,會有各種各樣的持久化策略;如完全不使用任何持久化,使用RDB或AOF一種,或同事開啟RDB和AOF持久化等。此外,持久化的選擇必須與Redis的主從策略一起考慮,因為主從復制與持久化同樣具有數據備份的功能,而且主機master和從機slave可以獨立的選擇持久化方案。

為什么要做Redis分區?

分區可以讓Redis管理更大的內存,Redis將可以使用所有機器的內存。如果沒有分區,你最多只能使用一臺機器的內存。分區使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網絡帶寬也會隨著計算機和網卡的增加而成倍增長。

Redis集群的主從復制模型是怎樣的?

為了是在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群是用了主從復制模型,每個節點都會有N-1個復制品

Redis集群會有寫操作丟失嗎?為什么?

Redis并不能保證數據強一致性,這意味著在實際中集群在特定的條件下可能會丟失寫操作

Redis集群之間是如何復制的

異步復制。

Redis如何做內存優化

盡可能使用散列表(hashes),散列表(是說列表里面存儲的數少)使用的內存非常小,所以你應該盡可能的將你的數據模型抽象到一個散列表里面,比如你的web系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶所有信息存儲到一張散列表中。

Redis常用的使用場景

Session共享(單點登錄)

頁面緩存

隊列

排行榜/計算器

發布/訂閱

Redis有哪些架構模式?講講各自的特點?

單機版

特點:簡單

存在問題:

內存容量有限

處理能力有限

無法高可用

主從復制

Redis的復制(replication)功能允許用戶根據一個Redis服務器來創建任意多個該服務器的復制品,其中被復制的服務器為主服務器(master),而通過復制創建出來的服務器復制品則為從服務器(slave)。主要主從服務器之間的網絡連接正常,主從服務器兩者會具有相同的數據,主服務器就會一直將發生在自己身上的數據更新同步給從服務器,從而一直保證主從服務器的數據相同。

問題:

無法保證高可用

沒有解決master寫的壓力

哨兵

Redis sentinel 是一個分布式系統中監控 redis 主從服務器,并在主服務器下線時自動進行故障轉移。其中三個特性:

監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。

提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。

自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作。

特點:

保證高可用

監控各個節點

自動故障遷移

缺點:

主從模式,切換需要時間,會丟數據

沒有解決master寫的壓力

集群(proxy型)

Twemproxy 是一個 Twitter 開源的一個 redis 和 memcache 快速/輕量級代理服務器; Twemproxy 是一個快速的單線程代理程序,支持 Memcached ASCII 協議和 redis 協議。

特點:

多種 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins

支持失敗節點自動刪除

后端 Sharding 分片邏輯對業務透明,業務方的讀寫方式和操作單個 Redis 一致

缺點:

增加了新的 proxy,需要維護其高可用。

failover 邏輯需要自己實現,其本身不能支持故障的自動轉移可擴展性差,進行擴縮容都需要手動干預

集群(直連型)

從redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有節點連接。

特點:

無中心架構(不存在哪個節點影響性能瓶頸),少了 proxy 層。

數據按照 slot 存儲分布在多個節點,節點間數據共享,可動態調整數據分布。

可擴展性,可線性擴展到 1000 個節點,節點可動態添加或刪除。

高可用性,部分節點不可用時,集群仍可用。通過增加 Slave 做備份數據副本

實現故障自動 failover,節點之間通過 gossip 協議交換狀態信息,用投票機制完成 Slave到 Master的角色提升。

缺點:

資源隔離性較差,容易出現相互影響的情況。

數據通過異步復制,不保證數據的強一致性

使用過Redis分布式鎖嗎,它是怎么實現的?

先拿setnx來爭搶鎖,搶到之后,再用expire給鎖加一個過期時間防止鎖忘記了釋放。 如果在setnx之后執行expire之前進程意外crash或者要重啟維護了,那會怎么樣? set指令有非常復雜的參數,這個應該是可以同時把setnx和expire合成一條指令來用的!

使用過 Redis 做異步隊列么,你是怎么用的?有什么缺點?

般使用 list 結構作為隊列,rpush 生產消息,lpop 消費消息。當 lpop 沒有消息的時候,要適當 sleep一會再重試。

缺點:

在消費者下線的情況下,生產的消息會丟失,得使用專業的消息隊列如 rabbitmq 等。

能不能生產一次消費多次呢?

使用 pub/sub 主題訂閱者模式,可以實現 1:N 的消息隊列。

什么是緩存穿透?如何避免?

緩存穿透

一般的緩存系統,都是按照key去緩存查詢,如果不存在對應的value,就應該去后端系統查找(比如DB)。一些惡意的請求會故意查詢不存在的key,請求量很大,就會對后端系統造成很大的壓力。這就叫做緩存穿透。

如何避免?

對查詢結果為空的情況也進行緩存,緩存時間設置短一點,或者該key對應的數據insert了之后清理緩存。

對一定不存在的key進行過濾。可以把所有的可能存在的key放到一個大的Bitmap中,查詢時通過該bitmap過濾。

什么是緩存雪崩?何如避免?

緩存雪崩當緩存服務器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候,會給后端系統帶來很大壓力,導致系統崩潰。

如何避免?

在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。

做二級緩存,A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期 3:不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻

緩存并發

這里的并發指的是多個redis的client同時set key引起的并發問題。其實redis自身就是單線程操作,多個client并發操作,按照先到先執行的原則,先到的先執行,其余的阻塞。當然,另外的解決方案是把redis.set操作放在隊列中使其串行化,必須的一個一個執行。

緩存預熱

緩存預熱就是系統上線后,將相關的緩存數據直接加載到緩存系統。

這樣就可以避免在用戶請求的時候,先查詢數據庫,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!

解決思路:

直接寫個緩存刷新頁面,上線時手工操作下;

數據量不大,可以在項目啟動的時候自動進行加載;

目的就是在系統上線前,將數據加載到緩存中。

Redis回收進程如何工作的?

客戶端執行數據寫入操作

redis server接收到寫入操作之后,檢查maxmemory的限制,如果超過了限制,那么就根據對應的policy清理掉部分數據

寫入操作完成執行。

Redis是單線程的,如何提高多核CPU的利用率?

可以在同一個服務器部署多個Redis的實例,并把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的, 所以,如果你想使用多個CPU,你可以考慮一下分片(shard)。

修改配置不重啟Redis會實時生效嗎?

針對運行實例,有許多配置選項可以通過 CONFIG SET 命令進行修改,而無需執行任何形式的重啟。 從 Redis 2.2 開始,可以從 AOF 切換到 RDB 的快照持久性或其他方式而不需要重啟 Redis。檢索 CONFIG GET * 命令獲取更多信息。 但偶爾重新啟動是必須的,如為升級 Redis 程序到新的版本,或者當你需要修改某些目前 CONFIG 命令還不支持的配置參數的時候。

Redis的內存用完了會發生什么?

如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者你可以將Redis當緩存來使用配置淘汰機制,當Redis達到內存上限時會沖刷掉舊的內容。

分布式Redis是前期做還是后期規模上來了再做好?為什么?

既然Redis是如此的輕量(單實例只使用1M內存),為防止以后的擴容,最好的辦法就是一開始就啟動較多實例。即便你只有一臺服務器,你也可以一開始就讓Redis以分布式的方式運行,使用分區,在同一臺服務器上啟動多個實例。一開始就多設置幾個Redis實例,例如32或者64個實例,對大多數用戶來說這操作起來可能比較麻煩,但是從長久來看做這點犧牲是值得的。這樣的話,當你的數據不斷增長,需要更多的Redis服務器時,你需要做的就是僅僅將Redis實例從一臺服務遷移到另外一臺服務器而已(而不用考慮重新分區的問題)。一旦你添加了另一臺服務器,你需要將你一半的Redis實例從第一臺機器遷移到第二臺機器。

Redis與其他key-value存儲有什么不同?

Redis有著更為復雜的數據結構并且提供對他們的原子性操作,這是一個不同于其他數據庫的進化路徑。Redis的數據類型都是基于基本數據結構的同時對程序員透明,無需進行額外的抽象。Redis運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡內存,應為數據量不能大于硬件內存。在內存數據庫方面的另一個優點是, 相比在磁盤上相同的復雜的數據結構,在內存中操作起來非常簡單,這樣Redis可以做很多內部復雜性很強的事情。 同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因為他們并不需要進行隨機訪問。

關注獲得更多分享

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、Redis高可用概述 在介紹Redis高可用之前,先說明一下在Redis的語境中高可用的含義。 我們知道,在w...
    空語閱讀 1,608評論 0 2
  • 企業級redis集群架構的特點 海量數據 高并發 高可用 要達到高可用,持久化是不可減少的,持久化主要是做災難恢復...
    lucode閱讀 2,221評論 0 7
  • 1.1 資料 ,最好的入門小冊子,可以先于一切文檔之前看,免費。 作者Antirez的博客,Antirez維護的R...
    JefferyLcm閱讀 17,099評論 1 51
  • 五種數據結構簡介 Redis是使用C編寫的,內部實現了一個struct結構體redisObject對象,通過結構體...
    彥幀閱讀 6,981評論 0 14
  • Redis是啥 Redis是一個開源的key-value存儲系統,由于擁有豐富的數據結構,又被其作者戲稱為數據結構...
    一凡呀閱讀 1,181評論 0 5