建議收藏!看徹底面掌握,最詳細的Redis總結(2021最新版)

Redis簡介

Redis 是一個使用 C 語言編寫的,開源的(BSD許可)高性能非關係型(NoSQL)的鍵值對數據庫。前端

Redis 能夠存儲鍵和五種不一樣類型的值之間的映射。鍵的類型只能爲字符串,值支持五種數據類型:字符串、列表、集合、散列表、有序集合。node

與傳統數據庫不一樣的是 Redis 的數據是存在內存中的,因此讀寫速度很是快,所以 redis 被普遍應用於緩存方向,每秒能夠處理超過 10萬次讀寫操做,是已知性能最快的Key-Value DB。另外,Redis 也常常用來作分佈式鎖。除此以外,Redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集羣方案(Redis 6.0 集羣搭建實踐)。面試

從2010年3月15日起,Redis的開發工做由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。redis

Redis的優缺點

優勢

  • 讀寫性能優異, Redis能讀的速度是110000次/s,寫的速度是81000次/s。
  • 支持數據持久化,支持AOF和RDB兩種持久化方式。
  • 支持事務,Redis的全部操做都是原子性的,同時Redis還支持對幾個操做合併後的原子性執行。
  • 數據結構豐富,除了支持string類型的value外還支持hash、set、zset、list等數據結構。
  • 支持主從複製,主機會自動將數據同步到從機,能夠進行讀寫分離。

缺點

  • 數據庫容量受到物理內存的限制,不能用做海量數據的高性能讀寫,所以Redis適合的場景主要侷限在較小數據量的高性能操做和運算上。
  • Redis 不具有自動容錯和恢復功能,主機從機的宕機都會致使前端部分讀寫請求失敗,須要等待機器重啓或者手動切換前端的IP才能恢復。
  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換IP後還會引入數據不一致的問題,下降了系統的可用性。
  • Redis 較難支持在線擴容,在集羣容量達到上限時在線擴容會變得很複雜。爲避免這一問題,運維人員在系統上線時必須確保有足夠的空間,這對資源形成了很大的浪費。

數據類型

Redis主要有5種數據類型,包括String,List,Set,Zset,Hash,知足大部分的使用要求。詳細的可參考:Redis 的 8 大數據類型,寫得很是好!算法

使用場景

因爲Redis優異的讀寫性能,持久化支持等優點,Redis的使用場景很是多,主要包括計數器,緩存,消息隊列,分佈式鎖等,具體使用場景以下:數據庫

  • 計數器vim

    • 能夠對 String 進行自增自減運算,從而實現計數器功能。
    • Redis 這種內存型數據庫的讀寫性能很是高,很適合存儲頻繁讀寫的計數量。
  • 緩存後端

    • 將熱點數據放到內存中,設置內存的最大使用量以及淘汰策略來保證緩存的命中率。
  • 會話緩存緩存

    • 可使用 Redis 來統一存儲多臺應用服務器的會話信息。
    • 當應用服務器再也不存儲用戶的會話信息,也就再也不具備狀態,一個用戶能夠請求任意一個應用服務器,從而更容易實現高可用性以及可伸縮性。
  • 全頁緩存(FPC)安全

    • 除基本的會話token以外,Redis還提供很簡便的FPC平臺。
    • 以Magento爲例,Magento提供一個插件來使用Redis做爲全頁緩存後端。此外,對WordPress的用戶來講,Pantheon有一個很是好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面。
  • 查找表

    • 例如 DNS 記錄就很適合使用 Redis 進行存儲。
    • 查找表和緩存相似,也是利用了 Redis 快速的查找特性。可是查找表的內容不能失效,而緩存的內容能夠失效,由於緩存不做爲可靠的數據來源。
  • 消息隊列(發佈/訂閱功能)

    • List 是一個雙向鏈表,能夠經過 lpush 和 rpop 寫入和讀取消息
    • 不過最好使用 Kafka、RabbitMQ 等消息中間件。
  • 分佈式鎖實現

    • 在分佈式場景下,沒法使用單機環境下的鎖來對多個節點上的進程進行同步。
    • 可使用 Redis 自帶的 SETNX 命令實現分佈式鎖,除此以外,還可使用官方提供的 RedLock 分佈式鎖實現。
  • 其它

    • Set 能夠實現交集、並集等操做,從而實現共同好友等功能。
    • ZSet 能夠實現有序性操做,從而實現排行榜等功能。

持久化

Redis 是內存型數據庫,爲了以後重用數據(好比重啓機器、機器故障以後回覆數據),或者是爲了防止系統故障而將數據備份到一個遠程位置,須要將內存中的數據持久化到硬盤上。

Redis 提供了RDB和AOF兩種持久化方式。默認是隻開啓RDB,當Redis重啓時,它會優先使用AOF文件來還原數據集。

Redis持久化詳解能夠參考:Redis持久化

過時鍵的刪除策略

Redis中有個設置時間過時的功能,即對存儲在 redis 數據庫中的值能夠設置一個過時時間。做爲一個緩存數據庫,這是很是實用的。如咱們通常項目中的 token 或者一些登陸信息,尤爲是短信驗證碼都是有時間限制的,按照傳統的數據庫處理方式,通常都是本身判斷過時,這樣無疑會嚴重影響項目性能。

Redis有三種不一樣的刪除策略:當即刪除,惰性刪除,定時刪除

  • (1):當即刪除。在設置鍵的過時時間時,建立一個回調事件,當過時時間達到時,由時間處理器自動執行鍵的刪除操做。
  • (2):惰性刪除。鍵過時了就過時了,無論。每次從dict字典中按key取值時,先檢查此key是否已通過期,若是過時了就刪除它,並返回nil,若是沒過時,就返回鍵值。
  • (3):定時刪除。每隔一段時間,對expires字典進行檢查,刪除裏面的過時鍵。

能夠看到,第二種爲被動刪除,第一種和第三種爲主動刪除,且第一種實時性更高。下面對這三種刪除策略進行具體分析。

  • 當即刪除

當即刪除能保證內存中數據的最大新鮮度,由於它保證過時鍵值會在過時後立刻被刪除,其所佔用的內存也會隨之釋放。可是當即刪除對cpu是最不友好的。由於刪除操做會佔用cpu的時間,若是恰好碰上了cpu很忙的時候,好比正在作交集或排序等計算的時候,就會給cpu形成額外的壓力。

並且目前redis事件處理器對時間事件的處理方式–無序鏈表,查找一個key的時間複雜度爲O(n),因此並不適合用來處理大量的時間事件。

  • 惰性刪除

惰性刪除是指,某個鍵值過時後,此鍵值不會立刻被刪除,而是等到下次被使用的時候,纔會被檢查到過時,此時才能獲得刪除。因此惰性刪除的缺點很明顯:浪費內存。dict字典和expires字典都要保存這個鍵值的信息。

舉個例子,對於一些按時間點來更新的數據,好比log日誌,過時後在很長的一段時間內可能都得不到訪問,這樣在這段時間內就要拜拜浪費這麼多內存來存log。這對於性能很是依賴於內存大小的redis來講,是比較致命的。

  • 定時刪除

從上面分析來看,當即刪除會短期內佔用大量cpu,惰性刪除會在一段時間內浪費內存,因此定時刪除是一個折中的辦法。

定時刪除是:每隔一段時間執行一次刪除操做,並經過限制刪除操做執行的時長和頻率,來減小刪除操做對cpu的影響。另外一方面定時刪除也有效的減小了因惰性刪除帶來的內存浪費。

  • Redis使用的策略

redis使用的過時鍵值刪除策略是:惰性刪除加上按期刪除,二者配合使用。

數據淘汰策略

能夠設置內存最大使用量,當內存使用量超出時,會施行數據淘汰策略。

Redis 具體有 6 種淘汰策略:

做爲內存數據庫,出於對性能和內存消耗的考慮,Redis 的淘汰算法實際實現上並不是針對全部 key,而是抽樣一小部分而且從中選出被淘汰的 key。

Redis 4.0 引入了 volatile-lfu 和 allkeys-lfu 淘汰策略,LFU 策略經過統計訪問頻率,將訪問頻率最少的鍵值對淘汰。

您須要根據系統的特徵,來選擇合適的淘汰策略。 固然,在運行過程當中也能夠經過命令動態設置淘汰策略,並經過 INFO 命令監控緩存的 miss 和 hit,來進行調優。

淘汰策略的內部實現

  • 客戶端執行一個命令,致使 Redis 中的數據增長,佔用更多內存
  • Redis 檢查內存使用量,若是超出 maxmemory 限制,根據策略清除部分 key
  • 繼續執行下一條命令,以此類推

在這個過程當中,內存使用量會不斷地達到 limit 值,而後超過,而後刪除部分 key,使用量又降低到 limit 值之下。

若是某個命令致使大量內存佔用(好比經過新key保存一個很大的set),在一段時間內,可能內存的使用量會明顯超過 maxmemory 限制。

Redis與Memcached的區別

二者都是非關係型內存鍵值數據庫,如今公司通常都是用 Redis 來實現緩存,並且 Redis 自身也愈來愈強大了!Redis 與 Memcached 的區別請參考:Redis與Memcached的區別

事務

Redis 經過 MULTI、EXEC、WATCH 等命令來實現事務(transaction)功能。事務提供了一種將多個命令請求打包,而後一次性、按順序地執行多個命令的機制,而且在事務執行期間,服務器不會中斷事務而改去執行其餘客戶端的命令請求,它會將事務中的全部命令都執行完畢,而後纔去處理其餘客戶端的命令請求。

事務中的多個命令被一次性發送給服務器,而不是一條一條發送,這種方式被稱爲流水線,能夠減小客戶端與服務器之間的網絡通訊次數從而提高性能。

在傳統的關係式數據庫中,經常使用 ACID 性質來檢驗事務功能的可靠性和安全性。在 Redis 中,事務老是具備原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation),而且當 Redis 運行在某種特定的持久化模式下時,事務也具備持久性(Durability)。

  • 事件

Redis 服務器是一個事件驅動程序。

  • 文件事件

服務器經過套接字與客戶端或者其它服務器進行通訊,文件事件就是對套接字操做的抽象。

Redis 基於 Reactor 模式開發了本身的網絡事件處理器,使用 I/O 多路複用程序來同時監聽多個套接字,並將到達的事件傳送給文件事件分派器,分派器會根據套接字產生的事件類型調用相應的事件處理器。

  • 時間事件

服務器有一些操做須要在給定的時間點執行,時間事件是對這類定時操做的抽象。

時間事件又分爲:

  • 定時事件:是讓一段程序在指定的時間以內執行一次
  • 週期性事件:是讓一段程序每隔指定時間就執行一次

目前Redis只使用週期性事件,而沒有使用定時事件。 一個事件時間主要由三個屬性組成:

  • id:服務器爲時間事件建立的全局惟一ID
  • when:毫秒精度的UNIX時間戳,記錄了時間事件的到達時間
  • timeProc:時間事件處理器,一個函數

實現服務器將全部時間事件都放在一個無序鏈表中,每當時間事件執行器運行時,遍歷整個鏈表,查找全部已到達的時間事件,並調用相應的事件處理器。(該鏈表爲無序鏈表,不按when屬性的大小排序)

  • 事件的調度與執行

服務器須要不斷監聽文件事件的套接字才能獲得待處理的文件事件,可是不能一直監聽,不然時間事件沒法在規定的時間內執行,所以監聽時間應該根據距離如今最近的時間事件來決定。

Sentinel

Sentinel(哨兵)能夠監聽集羣中的服務器,並在主服務器進入下線狀態時,自動從從服務器中選舉出新的主服務器。

Redis集羣生產環境高可用方案實戰過程

分片

分片是將數據劃分爲多個部分的方法,能夠將數據存儲到多臺機器裏面,這種方法在解決某些問題時能夠得到線性級別的性能提高。

假設有 4 個 Redis 實例 R0,R1,R2,R3,還有不少表示用戶的鍵 user:1,user:2,… ,有不一樣的方式來選擇一個指定的鍵存儲在哪一個實例中。

最簡單的方式是範圍分片,例如用戶 id 從 0~1000 的存儲到實例 R0 中,用戶 id 從 1001~2000 的存儲到實例 R1 中,等等。可是這樣須要維護一張映射範圍表,維護操做代價很高。

還有一種方式是哈希分片,使用 CRC32 哈希函數將鍵轉換爲一個數字,再對實例數量求模就能知道應該存儲的實例。

根據執行分片的位置,能夠分爲三種分片方式:

  • 客戶端分片:客戶端使用一致性哈希等算法決定鍵應當分佈到哪一個節點。
  • 代理分片:將客戶端請求發送到代理上,由代理轉發請求到正確的節點上。
  • 服務器分片:Redis Cluster。

複製

經過使用 slaveof host port 命令來讓一個服務器成爲另外一個服務器的從服務器。

一個從服務器只能有一個主服務器,而且不支持主主複製。

  • 鏈接過程

    • 主服務器建立快照文件,發送給從服務器,並在發送期間使用緩衝區記錄執行的寫命令。快照文件發送完畢以後,開始向從服務器發送存儲在緩衝區中的寫命令
    • 從服務器丟棄全部舊數據,載入主服務器發來的快照文件,以後從服務器開始接受主服務器發來的寫命令
    • 主服務器每執行一次寫命令,就向從服務器發送相同的寫命令
  • 主從鏈

隨着負載不斷上升,主服務器可能沒法很快地更新全部從服務器,或者從新鏈接和從新同步從服務器將致使系統超載。爲了解決這個問題,能夠建立一箇中間層來分擔主服務器的複製工做。中間層的服務器是最上層服務器的從服務器,又是最下層服務器的主服務器。

Redis中緩存雪崩、緩存穿透等問題的解決方案

緩存雪崩

緩存雪崩是指緩存同一時間大面積的失效,因此,後面的請求都會落到數據庫上,形成數據庫短期內承受大量請求而崩掉。

解決方案
  • 緩存數據的過時時間設置隨機,防止同一時間大量數據過時現象發生。
  • 通常併發量不是特別多的時候,使用最多的解決方案是加鎖排隊。
  • 給每個緩存數據增長相應的緩存標記,記錄緩存的是否失效,若是緩存標記失效,則更新數據緩存。
緩存穿透

緩存穿透是指緩存和數據庫中都沒有的數據,致使全部的請求都落到數據庫上,形成數據庫短期內承受大量請求而崩掉。

解決方案
  • 接口層增長校驗,如用戶鑑權校驗,id作基礎校驗,id<=0的直接攔截;
  • 從緩存取不到的數據,在數據庫中也沒有取到,這時也能夠將key-value對寫爲key-null,緩存有效時間能夠設置短點,如30秒(設置太長會致使正常狀況也無法使用)。這樣能夠防止攻擊用戶反覆用同一個id暴力攻擊
  • 採用布隆過濾器,將全部可能存在的數據哈希到一個足夠大的 bitmap 中,一個必定不存在的數據會被這個 bitmap 攔截掉,從而避免了對底層存儲系統的查詢壓力

附加

  • 對於空間的利用到達了一種極致,那就是Bitmap和布隆過濾器(Bloom Filter)。
  • Bitmap: 典型的就是哈希表
  • 缺點是,Bitmap對於每一個元素只能記錄1bit信息,若是還想完成額外的功能,恐怕只能靠犧牲更多的空間、時間來完成了。

布隆過濾器(推薦)

  • 就是引入了k(k>1)k(k>1)個相互獨立的哈希函數,保證在給定的空間、誤判率下,完成元素判重的過程。
  • 它的優勢是空間效率和查詢時間都遠遠超過通常的算法,缺點是有必定的誤識別率和刪除困難。
  • Bloom-Filter算法的核心思想就是利用多個不一樣的Hash函數來解決「衝突」。
  • Hash存在一個衝突(碰撞)的問題,用同一個Hash獲得的兩個URL的值有可能相同。爲了減小衝突,咱們能夠多引入幾個Hash,若是經過其中的一個Hash值咱們得出某元素不在集合中,那麼該元素確定不在集合中。只有在全部的Hash函數告訴咱們該元素在集合中時,才能肯定該元素存在於集合中。這即是Bloom-Filter的基本思想。
  • Bloom-Filter通常用於在大數據量的集合中斷定某元素是否存在。
緩存擊穿

緩存擊穿是指緩存中沒有但數據庫中有的數據(通常是緩存時間到期),這時因爲併發用戶特別多,同時讀緩存沒讀到數據,又同時去數據庫去取數據,引發數據庫壓力瞬間增大,形成過大壓力。和緩存雪崩不一樣的是,緩存擊穿指併發查同一條數據,緩存雪崩是不一樣數據都過時了,不少數據都查不到從而查數據庫。

解決方案
  • 設置熱點數據永遠不過時。
  • 加互斥鎖,互斥鎖
緩存預熱

緩存預熱就是系統上線後,將相關的緩存數據直接加載到緩存系統。這樣就能夠避免在用戶請求的時候,先查詢數據庫,而後再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!

解決方案
  • 直接寫個緩存刷新頁面,上線時手工操做一下;
  • 數據量不大,能夠在項目啓動的時候自動進行加載;
  • 定時刷新緩存;
緩存降級

當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然須要保證服務仍是可用的,即便是有損服務。系統能夠根據一些關鍵數據進行自動降級,也能夠配置開關實現人工降級。

緩存降級的最終目的是保證核心服務可用,即便是有損的。並且有些服務是沒法降級的(如加入購物車、結算)。

在進行降級以前要對系統進行梳理,看看系統是否是能夠丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;好比能夠參考日誌級別設置預案:

通常:好比有些服務偶爾由於網絡抖動或者服務正在上線而超時,能夠自動降級;

警告:有些服務在一段時間內成功率有波動(如在95~100%之間),能夠自動降級或人工降級,併發送告警;

錯誤:好比可用率低於90%,或者數據庫鏈接池被打爆了,或者訪問量忽然猛增到系統能承受的最大閥值,此時能夠根據狀況自動降級或者人工降級;

嚴重錯誤:好比由於特殊緣由數據錯誤了,此時須要緊急人工降級。

服務降級的目的,是爲了防止Redis服務故障,致使數據庫跟着一塊兒發生雪崩問題。所以,對於不重要的緩存數據,能夠採起服務降級策略,例如一個比較常見的作法就是,Redis出現問題,不去數據庫查詢,而是直接返回默認值給用戶。

熱點數據和冷數據

熱點數據,緩存纔有價值

對於冷數據而言,大部分數據可能尚未再次訪問到就已經被擠出內存,不只佔用內存,並且價值不大。頻繁修改的數據,看狀況考慮使用緩存

對於熱點數據,好比咱們的某IM產品,生日祝福模塊,當天的壽星列表,緩存之後可能讀取數十萬次。再舉個例子,某導航產品,咱們將導航信息,緩存之後可能讀取數百萬次。

數據更新前至少讀取兩次,緩存纔有意義。這個是最基本的策略,若是緩存尚未起做用就失效了,那就沒有太大價值了。

那存不存在,修改頻率很高,可是又不得不考慮緩存的場景呢?有!好比,這個讀取接口對數據庫的壓力很大,可是又是熱點數據,這個時候就須要考慮經過緩存手段,減小數據庫的壓力,好比咱們的某助手產品的,點贊數,收藏數,分享數等是很是典型的熱點數據,可是又不斷變化,此時就須要將數據同步保存到Redis緩存,減小數據庫壓力。

緩存熱點key

緩存中的一個Key(好比一個促銷商品),在某個時間點過時的時候,剛好在這個時間點對這個Key有大量的併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。

解決方案

對緩存查詢加鎖,若是KEY不存在,就加鎖,而後查DB入緩存,而後解鎖;其餘進程若是發現有鎖就等待,而後等解鎖後返回數據或者進入DB查詢

以上內容參考連接:https://blog.csdn.net/ThinkWo...

Redis 優化最佳實踐

咱們就來總結一下,在使用Redis時的最佳實踐方式,主要包含兩個層面:業務層面、運維層面。

因爲我以前寫過不少UGC後端服務,在大量場景下用到了Redis,這個過程當中也踩過不少坑,因此在使用過程當中也總結了一套合理的使用方法。

後來作基礎架構,開發Codis、Redis相關的中間件,在這個階段關注領域從使用層面下沉到Redis的開發和運維,更多聚焦在Redis的內部實現和運維過程當中產生的各類問題,在這塊也積累了一些經驗。

下面就針對這兩塊,分享一下我認爲比較合理的Redis使用和運維方法,不必定最全面,也可能與你使用Redis的方法不一樣,但如下這些方法都是我在踩坑以後總結的實際經驗,供你參考。關注公衆號Java技術棧回覆redis獲取系列Redis教程。

業務層面主要是開發人員須要關注,也就是開發人員在寫業務代碼時,如何合理地使用Redis。開發人員須要對Redis有基本的瞭解,才能在合適的業務場景使用Redis,從而避免業務層面致使的延遲問題。

在開發過程當中,業務層面的優化建議以下:

  • key的長度儘可能要短,在數據量很是大時,過長的key名會佔用更多的內存
  • 必定避免存儲過大的數據(大value),過大的數據在分配內存和釋放內存時耗時嚴重,會阻塞主線程
  • Redis 4.0以上建議開啓lazy-free機制,釋放大value時異步操做,不阻塞主線程
  • 建議設置過時時間,把Redis當作緩存使用,尤爲在數量很大的時,不設置過時時間會致使內存的無限增加
  • 不使用複雜度太高的命令,例如SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE,使用這些命令耗時較久,會阻塞主線程
  • 查詢數據時,一次儘可能獲取較少的數據,在不肯定容器元素個數的狀況下,避免使用LRANGE key 0 -1,ZRANGE key 0 -1這類操做,應該設置具體查詢的元素個數,推薦一次查詢100個如下元素
  • 寫入數據時,一次儘可能寫入較少的數據,例如HSET key value1 value2 value3...,-控制一次寫入元素的數量,推薦在100如下,大數據量分多個批次寫入
  • 批量操做數據時,用MGET/MSET替換GET/SET、HMGET/MHSET替換HGET/HSET,減小請求來回的網絡IO次數,下降延遲,對於沒有批量操做的命令,推薦使用pipeline,一次性發送多個命令到服務端
  • 禁止使用KEYS命令,須要掃描實例時,建議使用SCAN,線上操做必定要控制掃描的頻率,避免對Redis產生性能抖動
  • 避免某個時間點集中過時大量的key,集中過時時推薦增長一個隨機時間,把過時時間打散,下降集中過時key時Redis的壓力,避免阻塞主線程
  • 根據業務場景,選擇合適的淘汰策略,一般隨機過時要比LRU過時淘汰數據更快
  • 使用鏈接池訪問Redis,並配置合理的鏈接池參數,避免短鏈接,TCP三次握手和四次揮手的耗時也很高
  • 只使用db0,不推薦使用多個db,使用多個db會增長Redis的負擔,每次訪問不一樣的db都須要執行SELECT命令,若是業務線不一樣,建議拆分多個實例,還能提升單個實例的性能
  • 讀的請求量很大時,推薦使用讀寫分離,前提是能夠容忍從節數據更新不及時的問題
  • 寫請求量很大時,推薦使用集羣,部署多個實例分攤寫壓力

運維層面

目的是合理規劃Redis的部署和保障Redis的穩定運行,主要優化以下:

  • 不一樣業務線部署不一樣的實例,各自獨立,避免混用,推薦不一樣業務線使用不一樣的機器,根據業務重要程度劃分不一樣的分組來部署,避免某一個業務線出現問題影響其餘業務線
  • 保證機器有足夠的CPU、內存、帶寬、磁盤資源,防止負載太高影響Redis性能
  • 以master-slave集羣方式部署實例,並分佈在不一樣機器上,避免單點,slave必須設置爲readonly
  • master和slave節點所在機器,各自獨立,不要交叉部署實例,一般備份工做會在slave上作,作備份時會消耗機器資源,交叉部署會影響到master的性能
  • 推薦部署哨兵節點增長可用性,節點數量至少3個,並分佈在不一樣機器上,實現故障自動故障轉移
  • 提早作好容量規劃,一臺機器部署實例的內存上限,最好是機器內存的一半,主從全量同步時會佔用最多額外一倍的內存空間,防止網絡大面積故障引起全部master-slave的全量同步致使機器內存被吃光
  • 作好機器的CPU、內存、帶寬、磁盤監控,在資源不足時及時報警處理,Redis使用Swap後性能急劇降低,網絡帶寬負載太高訪問延遲明顯增大,磁盤IO太高時開啓AOF會拖慢Redis的性能
  • 設置最大鏈接數上限,防止過多的客戶端鏈接致使服務負載太高
  • 單個實例的使用內存建議控制在20G如下,過大的實例會致使備份時間久、資源消耗多,主從全量同步數據時間阻塞時間更長
  • 設置合理的slowlog閾值,推薦10毫秒,並對其進行監控,產生過多的慢日誌須要及時報警 設置合理的複製緩衝區repl-backlog大小,適當調大repl-backlog能夠下降主從全量複製的機率
  • 設置合理的slave節點client-output-buffer-limit大小,對於寫入量很大的實例,適當調大能夠避免主從複製中斷問題
  • 備份時推薦在slave節點上作,不影響master性能
  • 不開啓AOF或開啓AOF配置爲每秒刷盤,避免磁盤IO消耗下降Redis性能
  • 當實例設置了內存上限,須要調大內存上限時,先調整slave再調整master,不然會致使主從節點數據不一致
  • 對Redis增長監控,監控採集info信息時,使用長鏈接,頻繁的短鏈接也會影響Redis性能,redis性能監控指標,參考這個文章
  • 線上掃描整個實例數時,記得設置休眠時間,避免掃描時QPS突增對Redis產生性能抖
  • 作好Redis的運行時監控,尤爲是expired\_keys、evicted\_keys、latest\_fork\_usec指標,短期內這些指標值突增可能會阻塞整個實例,引起性能問題

以上就是我在使用Redis和開發Redis相關中間件時,總結出來Redis推薦的實踐方法,以上提出的這些方面,都或多或少在實際使用中遇到過。

可見,要想穩定發揮Redis的高性能,須要在各個方面作好工做,但凡某一個方面出現問題,必然會影響到Redis的性能,這對咱們使用和運維提出了更高的要求。

若是你在使用Redis過程當中,遇到更多的問題或者有更好的使用經驗,能夠留言一塊兒探討!

出處:kaito-kidd.com/2020/07/04/redis-best-practices/

Redis其它總結

阿里雲Redis開發規範學習總結

目前 Redis 可視化工具最全的橫向評測

Redis 性能測試工具介紹

Redis 可視化管理工具

Redis 愈來愈慢?常見延遲問題定位與分析

Redis 分佈式集羣部署

原理:

  • Redis集羣採用一致性哈希槽的方式將集羣中每一個主節點都分配必定的哈希槽,對寫入的數據進行哈希後分配到某個主節點進行存儲。
  • 集羣使用公式(CRC16 key)& 16384計算鍵key數據那個槽。
  • 16384個slot均勻分佈在各個節點上。
  • 集羣中每一個主節點將承擔一部分槽點的維護,而槽點中存儲着數據,每一個主節點都有至少一個從節點用於高可用。

節點通訊方式:
  • 開啓一個端口 設置的端口號+10000,用於集羣之間節點通訊交換信息。
  • 每一個節點默認每秒10次選擇隨機5個節點發送ping消息,將自身信息和知道的集羣信息傳遞,收到ping消息後返回pong消息作回覆,最後經過這種隨機的消息交換,最終每一個節點將得到全部信息。
  • 當某個主節點掛掉,全部節點將會發現主節點掛掉了,做爲主節點的從節點,就會接替主節點的工做,而後告訴全部其它節點,他成爲了主。這樣其它存活節點,就將它們維護的信息表更新從節點將接任作主,若是都掛掉集羣將報錯。當從一個節點操做,根據一致性哈希計算後將存儲在其中一個主節點中,從節點將同步主的數據。

  • redis cluster是去中心化的,集羣中的每一個節點都是平等的關係,每一個節點都保存各自的數據和整個集羣的狀態。每一個節點都和其餘全部節點鏈接,並且這些鏈接保持活躍。

  • 搭建集羣時,會爲每個分片的主節點,對應一個從節點。實現slaveof功能,同時當主節點down,實現sentinel哨兵的自動failover切換功能

Redis分佈式集羣(部署):

端口號:7000-7005

本次分佈式分片集羣在一臺LInux系統便可,只須要安裝多個實例做爲集羣配置。

安裝ruby環境支持:
yum -y install ruby rubygems

yum安裝2.0.0版本,可是gem須要2.2.2版本以上,因此選擇編譯

下載並安裝ruby環境:
wget https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.gz
tar xf ruby-2.6.1.tar.gz && cd ruby-2.6.1/
./configure --prefix=/usr/local/ruby
make && make install && echo $?
echo 'export PATH=$PATH:/usr/local/ruby/bin' >> /etc/profile
source /etc/profile
修改gem工具國內源:
# 查看gem工具源地址
gem sources -l
# 添加一個阿里雲的gem工具源
gem sources -a http://mirrors.aliyun.com/rubygems/
# 刪除gem工具默認國外源
gem sources --remove https://rubygems.org/
# 下載當前最新版本集羣插件
gem install redis -v 4.1.0
集羣節點準備:
mkdir /data/700{0..5}
配置7000端口實例:
vim /data/7000/redis.conf
port 7000
daemonize yes
pidfile /data/7000/redis.pid
loglevel notice
logfile "/data/7000/redis.log"
dbfilename dump.rdb
dir /data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
拷貝其餘端口實例:
# 拷貝配置文件
cp /data/7000/redis.conf /data/7001/
cp /data/7000/redis.conf /data/7002/
cp /data/7000/redis.conf /data/7003/
cp /data/7000/redis.conf /data/7004/
cp /data/7000/redis.conf /data/7005/

# 修改配置文件內容
sed -i 's#7000#7001#g' /data/7001/redis.conf
sed -i 's#7000#7002#g' /data/7002/redis.conf
sed -i 's#7000#7003#g' /data/7003/redis.conf
sed -i 's#7000#7004#g' /data/7004/redis.conf
sed -i 's#7000#7005#g' /data/7005/redis.conf
啓動全部實例:
redis-server /data/7000/redis.conf
redis-server /data/7001/redis.conf
redis-server /data/7002/redis.conf
redis-server /data/7003/redis.conf
redis-server /data/7004/redis.conf
redis-server /data/7005/redis.conf
建立命令軟連接:
(這個命令過時了,如今使用redis-cli命令)(可選執行命令)
ln -s /usr/local/redis-5.0.2/src/redis-trib.rb /usr/sbin/
查看進程:
ps -ef |grep redis-server

加入全部實例節點到集羣管理:
# --replicas 1",1是表明每個主有一個從,後面的是全部節點的地址與端口信息
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

分佈式主從規則爲,前三個實例節點是主,對應的後面三個實例節點爲從節點,若是replicas 2,那就多加3個實例節點

查看主節點狀態:
redis-cli -p 7000 cluster nodes|grep master

查看從節點狀態:
redis-cli -p 7000 cluster nodes|grep slave

Redis-分佈式集羣(管理)

集羣節點增長準備:

mkdir /data/700{6..7}

拷貝其餘端口實例:

# 拷貝配置文件
cp /data/7000/redis.conf /data/7006/
cp /data/7000/redis.conf /data/7007/

# 修改配置文件內容
sed -i 's#7000#7006#g' /data/7006/redis.conf
sed -i 's#7000#7007#g' /data/7007/redis.conf

啓動新節點實例:

redis-server /data/7006/redis.conf
redis-server /data/7007/redis.conf
查看進程:
ps -ef |grep redis-server

添加主節點:(7000實例是管理節點)
#'把7006實例添加到7000實例這個主節點所在集羣內(此時已經有了4個主節點)
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
查看主節點狀態:
redis-cli -p 7000 cluster nodes|grep master

轉移slot(從新分片):
#'操做集羣管理節點重新分配,並在交互界面指定分片大小、選擇接收分片的節點ID
redis-cli --cluster reshard 127.0.0.1:7000

How many slots do you want to move (from 1 to 16384)? 4096
#經過人工手動計算數據分片總大小除以主節點後的數字

What is the receiving node ID? 2129d28f0a86fc89571e49a59a0739812cff7953
#選擇接收數據分片的節點ID,(這是新增節點7006實例的ID號)

Source node #1: all
#選擇從哪些源主節點從新分片給新主節點)(all是全部節點)

Do you want to proceed with the proposed reshard plan (yes/no)? yes           
#確認修改以上的操做
從新查看主節點狀態:(能夠看到集羣數據的從新分片)
redis-cli -p 7000 cluster nodes|grep master

添加從節點:
#'把7007實例節點添加到7006實例主節點內,並指定對應7006實例主節點坐在集羣的管理節點
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id 2129d28f0a86fc89571e49a59a0739812cff7953
查看從節點狀態:
redis-cli -p 7000 cluster nodes|grep slave

集羣節點刪除準備:

移動要刪除節點的數據分片:
#'操做集羣管理節點重新分配,並在交互界面指定分片大小、選擇接收分片的節點ID
redis-cli --cluster reshard 127.0.0.1:7000

#方法是根據要刪除master節點的分片位置,而後一個組分一個節點 , 也能夠直接移動全部數據片到一個節點

How many slots do you want to move (from 1 to 16384)? 1365                    
#經過人工手動查看數據分片總大小

What is the receiving node ID? e64f9074a3733fff7baa9a4848190e56831d5447
#選擇接收數據分片的節點ID,(這是新增節點7006實例的ID號)

Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
#選擇從哪些源主節點從新分片給新主節點(這是要刪除的主節點的ID號)

Source node #2: done
#這是結束命令

Do you want to proceed with the proposed reshard plan (yes/no)? yes           
#確認修改以上的操做
從新查看主節點狀態:(能夠看到集羣數據的從新分片)
redis-cli -p 7000 cluster nodes|grep master

繼續移動數據片:
#'操做集羣管理節點重新分配,並在交互界面指定分片大小、選擇接收分片的節點ID
redis-cli --cluster reshard 127.0.0.1:7000

# 方法是根據要刪除master節點的分片位置,而後一個組分一個節點 , 也能夠直接移動全部數據片到一個節點

How many slots do you want to move (from 1 to 16384)? 1366                    #經過人工手動查看數據分片總大小

What is the receiving node ID? f6c1aaea3a8c56e0c7dee8ad7ae17e26dd04244c
#選擇接收數據分片的節點ID,(這是新增節點7006實例的ID號)

Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
#選擇從哪些源主節點從新分片給新主節點(這是要刪除的主節點的ID號)

Source node #2: done
#這是結束命令

Do you want to proceed with the proposed reshard plan (yes/no)? yes           
#確認修改以上的操做
從新查看主節點狀態:(能夠看到集羣數據的從新分片)
redis-cli -p 7000 cluster nodes|grep master

最後一次移動數據片:
#'操做集羣管理節點重新分配,並在交互界面指定分片大小、選擇接收分片的節點ID
redis-cli --cluster reshard 127.0.0.1:7000

#方法是根據要刪除master節點的分片位置,而後一個組分一個節點 , 也能夠直接移動全部數據片到一個節點

How many slots do you want to move (from 1 to 16384)? 1365                    
#經過人工手動查看數據分片總大小

What is the receiving node ID? 5a0df4ea0af5f35c1248e45e88d44c3f2e10169f
Source node #1: 2129d28f0a86fc89571e49a59a0739812cff7953
Source node #2: done                
從新查看主節點狀態:(能夠看到集羣數據的從新分片)
redis-cli -p 7000 cluster nodes|grep master

刪除清空數據片的主節點:
#'刪除已經清空數據的7006實例
redis-cli --cluster del-node 127.0.0.1:7006 2129d28f0a86fc89571e49a59a0739812cff7953

#刪除沒有主庫的7007實例
redis-cli --cluster del-node 127.0.0.1:7007 821bcf78c5e4c0b08aa7a5d514214b657ebec4ab

其餘配置管理:

#內存信息查看
redis-cli -p 6382 -a redhat info memory

#設置最大隻能使用100MB的內存
redis-cli -p 6382 -a redhat config set maxmemory 102400000

史上最全、最新的Redis面試題(最新版)

相關文章
相關標籤/搜索