-
1 # java架構設計
-
2 # 半寸灰1
掛掉?一般都是配置不足,如果你伺服器和redis在同同一機器,機器記憶體和伺服器記憶體 幾乎佔了機器的全部記憶體,這時候你訪問取一個比較大的資料肯定會掛的。加錢吧
-
3 # 會點程式碼的大叔
要保證Redis不會掛掉,也就是提高Redis的高可用性,可以從這麼幾個方面考慮。
叢集式部署方式Redis單副本:也就是隻部署一臺Redis,不需要節點之間的資料同步,架構簡單,部署方便;但是單臺機器畢竟是有風險的,按照題目中【海量資料】的場景,是不能達到高可用要求的。
Redis主從:主從例項可以部署在不同的物理伺服器上,充分利用多臺伺服器的資源,在主庫發生故障的時候,可以進行主備切換,從而保證系統的穩定執行,甚至可以做到讀寫分離,主庫專門用作寫操作,一臺或多臺備庫進行讀操作;但是當主庫發生故障的時候(如果沒有HA方案的話),是需要手動進行主備切換的。
Redis Sentinel:部署架構分為兩部分【Sentinel叢集】和【資料叢集】;Sentinel叢集是由多個Sentinel節點組成的分散式叢集,通常是2N+1臺伺服器,可以實現故障發現和轉移、客戶端通知等功能;資料叢集用於儲存資料;它能夠解決主從模式下的自動切換問題,並且資料叢集是可以橫向擴充套件的;當然這個架構實現和部署起來,也更為複雜一些;並且這個架構不能做到讀寫分離。
Redis Cluster:Redis 3.0叢集,是分散式叢集解決方案之一,物理架構中配置2N個節點(主從一一對應),主節點提供讀寫操作,從節點作為備份;資料分佈儲存在多個節點上,是一種無中心的架構,如果有部分節點發生故障,能夠實現故障自動轉移和切換,用投票機制完成備庫升級為主庫(下文的Redis分片章節,還會介紹到Redis Cluster)。
Redis分片Redis在3.0之前只支援單例項,在此之前,在資料量比較大的情況,通常有幾種方案可以做到把資料分片儲存到多臺伺服器上。
客戶端分片:分片邏輯被放到了客戶端上,由客戶端根據路由規則,把資料儲存不同的Redis例項中,讀取的時候也是根據規則,去對應的例項上讀取資料;但是當Redis例項數量發生變化的時候(增加例項或減少例項),需要手動地調整分片的規則程式;並且這種部署方式,也增加了運維的成本。
Redis代理元件:在這種架構中,客戶端不再直接訪問Redis例項,而是訪問代理元件,由它管理路由的規則;客戶端不需要關心有幾個Redis例項,資料被路由到哪個例項上;但是由於在客戶端和Redis之間增加了一層代理,多多少少也會產生一些效能上的損耗。
Redis Cluster:上文中提到的Redis 3.0叢集,這裡對資料的儲存和路由方式,再介紹幾句:Redis把所有的Key分成了16384個slot,每個Redis例項負責其中一部分slot;每個Redis都知道每個slot在哪個節點上儲存(例項節點定期做資料交換);當客戶端訪問到一個Redis例項的時候,如果資料不在這個例項上,那麼會透過重定向命令引導客戶端訪問資料所在的例項。
熱點資料挑戰單節點的極限雖然我們已經把資料分散儲存到多臺Redis例項上了,但是如果有一個熱點資料被頻繁訪問,超過了單例項的伺服器極限,那麼該如何解決呢?通常的手段就是做讀寫分離,部署多臺只讀節點,對外提供服務。
回覆列表
海量資料下正確的訪問redis要注意的事情有很多,基本上可以從服務治理,資料,redis正確使用三個方面來講。
服務治理既然是海量資料,那麼服務肯定要拆分成多個服務,最常見的採用“大中臺,小前臺”的概念,中臺分各個服務中心,各個中心去維護自己中心負責的服務,向上遊前臺提供資料和服務。比如一個做內容付費的公司可以有內容中心、商品中心、交易中心
使用者中心、促銷中心、基礎中心、開放平臺等,中心之間採用RPC通訊或者資料共享。
資料劃分 在服務治理的基礎上,各個中心負責維護自己的資料,那麼資料的儲存有MySQL、MongoDB(儲存非結構化資料)、Redis,這些資料儲存介質都做成獨立例項,互不影響。那麼海量資料分散到各個中心了,壓力也會相對少一些,做到每個中心都有自己獨立的一個或多個數據庫例項、Redis例項。每個中心再根據自己中心的資料做好分庫分表、快取同步等工作。下圖是一張資料庫和redis快取同步的方案,透過實時重新整理+定時任務同步補償機制,將大部分熱點業務資料實時同步至redis。redis的正確使用在做好服務治理和資料劃分的基礎上,這個時候就是重點講如何正確使用redis的時候了,個人列舉了部分細則僅供大家參考:
熟練使用五種資料結構(String、Set|、Hash、List、ZSet)以及每種資料結構的適用場景和注意事項;
防止快取雪崩,即避免大批次快取同一時間段集中過期,導致大量請求都懟到資料庫上,導致資料庫連線數爆滿、宕機;
防止快取穿透,避免redis中熱點key存入了null或者不存在,導致大量請求繞過redis請求資料庫去了;
避免大key的存在:比如一個redis叢集是16G,共8個節點,每個節點平均分配2G的記憶體,這時候如果有一個大的hash key佔用記憶體超過2G了,這個時候儘管叢集還有剩餘的空間,這個大key的寫入依舊會失敗,單個key是無法做到叢集的,另外再想想如果一個hash儲存了大量的資料,考慮一下效能問題?
禁止使用keys、flushall、flushdb等,運維同學透過redis的rename機制禁掉命令,或者使用scan的方式漸進式處理;
批次讀寫redis請採用pipeline管道的方式;
在程式碼中採用執行緒連線池的方式定義每一個redis bean
volatile-lru :在設定了過期時間的鍵空間中,移除最近最少使用的key。allkeys-lru : 移除最近最少使用的key (推薦)volatile-random : 在設定了過期時間的鍵空間中,隨機移除一個鍵,不推薦allkeys-random : 直接在鍵空間中隨機移除一個鍵,沒人用volatile-ttl : 在設定了過期時間的鍵空間中,有更早過期時間的key優先移除 不推薦noeviction : 不做過鍵處理,只返回一個寫操作錯誤。 不推薦如果是你,你會使用哪種過期策略?
所以,個人認為redis用好並不難,難的是把服務治理好,redis跟著服務走就可以了。