『壹』 什麼是分布式緩存
分布式緩存能夠處理大量的動態數據,因此比較適合應用在Web 2.0時代中的社交網站等需要由用戶生成內容的場景。從本地緩存擴展到分布式緩存後,關注重點從CPU、內存、緩存之間的數據傳輸速度差異也擴展到了業務系統、資料庫、分布式緩存之間的數據傳輸速度差異。
常用的分布式緩存包括Redis和Memcached。
Memcached
Memcached是一個高性能的分布式內存對象緩存系統,用於動態Web應用以減輕資料庫負載。Memcached通過在內存中緩存數據和對象來減少讀取資料庫的次數,從而提高動態、資料庫驅動網站的速度。
特點:哈希方式存儲;全內存操作;簡單文本協議進行數據通信;只操作字元型數據;集群由應用進行控制,採用一致性哈希演算法。
限制性:數據保存在內存當中的,一旦機器重啟,數據會全部丟失;只能操作字元型數據,數據類型貧乏;以root許可權運行,而且Memcached本身沒有任何許可權管理和認證功能,安全性不足;能存儲的數據長度有限,最大鍵長250個字元,儲存數據不能超過1M。
Redis
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
特點:
Redis支持的數據類型包括:字元串、string、hash、set、sortedset、list;Redis實現持久化的方式:定期將內存快照寫入磁碟;寫日誌;Redis支持主從同步。
限制性:單核運行,在存儲大數據的時候性能會有降低;不是全內存操作;主從復制是全量復制,對實際的系統運營造成了一定負擔。
『貳』 Redis的主要功能
緩存:這應該是 Redis 最主要的功能了,也是大型網站必備機制,合理地使用緩存不僅可以加 快數據的訪問速度,而且能夠有效地降低後端數據源的壓力。共享Session:對於一些依賴 session 功能的服務來說,如果需要從單機變成集群的話,可以選擇 redis 來統一管理 session。消息隊列系統:消息隊列系統可以說是一個大型網站的必備基礎組件,因為其具有業務 解耦、非實時業務削峰等特性。Redis提供了發布訂閱功能和阻塞隊列的功 能,雖然和專業的消息隊列比還不夠足夠強大,但是對於一般的消息隊列功 能基本可以滿足。比如在分布式爬蟲系統中,使用 redis 來統一管理 url隊列。分布式鎖:在分布式服務中。可以利用Redis的setnx功能來編寫分布式的鎖,雖然這個可能不是太常用。 當然還有諸如排行榜、點贊功能都可以使用 Redis 來實現,但是 Redis 也不是什麼都可以做,比如數據量特別大時,不適合 Redis,我們知道 Redis 是基於內存的,雖然內存很便宜,但是如果你每天的數據量特別大,比如幾億條的
用戶行為日誌數據,用 Redis 來存儲的話,成本相當的高。
『叄』 面試中問到Redis持久化的原理,本篇在做詳細解答
我們知道redis是一個 高效的分布式內存資料庫 ,由於是操作內存所以性能非常之快,通常用它來做分布式緩存,用來提高微服務的高性能,但是因為是內存操作,所以當出現伺服器故障,斷電等情況就會造成 內存數據丟失 ,不可恢復,因此redis 引入了持久化機制來將內存數據寫入圓帶磁碟,從而保障了Redis的數據不被丟失。
Redis有兩種持久化的方式,一種是RDB,另外種是AOF。
RDB是將Redis內存中數據的快照存儲在磁碟內,是Redis的默認持久化方案。
RDB持久化默認有三種策略
可在redis.conf中配置,會以一段時間內達到指定修改的次數為規則來觸發快照操作,快照文件名為mp.rdb。每當Redis服務重啟的時候都會從該文件中把數據載入到內存中。
在60秒內有10000次操作即觸發RDB持久化。
沒有滿足第一種條件時,在900秒內有1次操作即觸發RDB持久化。
沒有滿足第二種條件時,在300秒內有10次操作即觸發RDB持久化。
RDB持久化除了可以根據配置中的策略來觸發外,還可以使用save和bgsave命令手動來觸發。這兩個命令的區別在於save會阻塞伺服器進程。在執行save命令的過程中,伺服器不能處理任何請求,但是bgsave(background save,後台保存)命令會通過一個子進程在後台處理數據RDB持久化。本質上save和bgsave調用的都是rdbSave函數,所以Redis不允許save和bgsave命令同時執行,當然這也是為了避免RDB文件數據出現不一致性的問題。
每次都是一個大文件,備份寫入IO操作筆記大,很容易耗時,影響進程資源使用。
如果最近一次進程崩潰,那麼最近一次數據備份後的數據就被丟失。
文件直接就可以當冷備使用
AOF(Append Only File)以獨立日誌的方式記錄每次的寫命令,可以很好地解決了數據持久化的實時性。系統重啟時可以重新執行AOF文件中的命令來恢復數據。AOF會先把命令追加畝飢在AOF緩沖區,然後根據對應策略寫入硬碟。
AOF的實現流程有三個步驟
步驟一
把命令追加到AOF緩沖區,
步驟二
將緩沖區的內容寫入程序緩沖區
步驟三
將程序緩沖區的內容寫入文件
當AOF持久化功能處於開啟狀態時,伺服器每執行完一個命令就會將命令以迅腔返協議格式追加寫入redisServer結構體的aof_buf緩沖區。而在服務重啟的時候會把AOF文件載入到緩沖區中。
AOF有 三種觸發機制
·always:每次發生數據變更都會被立即記錄到磁碟,性能較差,但數據完整性比較好。
·everysec:每秒鍾將aof_buf緩沖區的內容寫入AOF文件,如果宕機,就會有1秒內的數據丟失。
·no:將數據同步操作交給操作系統來處理,性能最好,但是數據可靠性最差。在配置文件中設置appendonly=yes後,若沒有指定apendfsync,默認會使用everysec選項。
寫入指令隨著時間的推移,記錄了很多重復的指令,導致數據量非常大。
RDB優先順序高於AOF
RDB小,AOF較大
RDB慢,AOF快
RDB快,AOF慢
『肆』 Redis分布式緩存搭建
花了兩天時間整理了之前記錄的Redis單體與哨兵模式的搭建與使用,又補齊了集群模式的使用和搭建經驗,並對集群的一些個原理做了理解。
筆者安裝中遇到的一些問題:
如果make報錯,可能是沒裝gcc或者gcc++編輯器,安裝之 yum -y install gcc gcc-c++ kernel-devel ,有可能還是提示一些個c文件編譯不過,gcc -v查看下版本,如果不到5.3那麼升級一下gcc:
在 /etc/profile 追加一行 source /opt/rh/devtoolset-9/enable
scl enable devtoolset-9 bash
重新make clean, make
這回編譯通過了,提示讓你最好make test一下/
執行make test ,如果提示 You need tcl 8.5 or newer in order to run the Redis test
那就升級tcl, yum install tcl
重新make test,如果還有error就刪了目錄,重新tar包解壓重新make , make test
o/ All tests passed without errors! ,表示編譯成功。
然後make install即可。
直接運行命令: ./redis-server /usr/redis-6.0.3/redis.conf &
redis.conf 配置文件里 bind 0.0.0.0 設置外部訪問, requirepass xxxx 設置密碼。
redis高可用方案有兩種:
常用搭建方案為1主1從或1主2從+3哨兵監控主節點, 以及3主3從6節點集群。
(1)sentinel哨兵
/usr/redis-6.0.3/src/redis-sentinel /usr/redis-6.0.3/sentinel2.conf &
sentinel2.conf配置:
坑1:master節點也會在故障轉移後成為從節點,也需要配置masterauth
當kill master進程之後,經過sentinel選舉,slave成為了新的master,再次啟動原master,提示如下錯誤:
原因是此時的master再次啟動已經是slave了,需要向現在的新master輸入密碼,所以需要在master.conf
中配置:
坑2:哨兵配置文件要暴露客戶端可以訪問到的master地址
在 sentinel.conf 配置文件的 sentinel monitor mymaster 122.xx.xxx.xxx 6379 2 中,配置該哨兵對應的master名字、master地址和埠,以及達到多少個哨兵選舉通過認為master掛掉。其中master地址要站在redis訪問者(也就是客戶端)的角度、配置訪問者能訪問的地址,例如sentinel與master在一台伺服器(122.xx.xxx.xxx)上,那麼相對sentinel其master在本機也就是127.0.0.1上,這樣 sentinel monitor mymaster 127.0.0.1 6379 2 邏輯上沒有問題,但是如果另外伺服器上的springboot通過lettuce訪問這個redis哨兵,則得到的master地址為127.0.0.1,也就是springboot所在伺服器本機,這顯然就有問題了。
附springboot2.1 redis哨兵配置:
坑3:要注意配置文件.conf會被哨兵修改
redis-cli -h localhost -p 26379 ,可以登到sentinel上用info命令查看一下哨兵的信息。
曾經遇到過這樣一個問題,大致的信息如下
slaves莫名其妙多了一個,master的地址也明明改了真實對外的地址,這里又變成127.0.0.1 !
最後,把5個redis進程都停掉,逐個檢查配置文件,發現redis的配置文件在主從哨兵模式會被修改,master的配置文件最後邊莫名其妙多了一行replicaof 127.0.0.1 7001, 懷疑應該是之前配置錯誤的時候(見坑2)被哨兵動態加上去的! 總之,實踐中一定要多注意配置文件的變化。
(2)集群
當數據量大到一定程度,比如幾十上百G,哨兵模式不夠用了需要做水平拆分,早些年是使用codis,twemproxy這些第三方中間件來做分片的,即 客戶端 -> 中間件 -> Redis server 這樣的模式,中間件使用一致性Hash演算法來確定key在哪個分片上。後來Redis官方提供了方案,大家就都採用官方的Redis Cluster方案了。
Redis Cluster從邏輯上分16384個hash slot,分片演算法是 CRC16(key) mod 16384 得到key應該對應哪個slot,據此判斷這個slot屬於哪個節點。
每個節點可以設置1或多個從節點,常用的是3主節點3從節點的方案。
reshard,重新分片,可以指定從哪幾個節點移動一些hash槽到另一個節點去。重新分片的過程對客戶端透明,不影響線上業務。
搭建Redis cluster
redis.conf文件關鍵的幾個配置:
啟動6個集群節點
[root@VM_0_11_centos redis-6.0.3]# ps -ef|grep redis
root 5508 1 0 21:25 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7001 [cluster]
root 6903 1 0 21:32 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7002 [cluster]
root 6939 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7003 [cluster]
root 6966 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7004 [cluster]
root 6993 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7005 [cluster]
root 7015 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7006 [cluster]
這時候這6個節點還是獨立的,要把他們配置成集群:
說明: -a xxxx 是因為筆者在redis.conf中配置了requirepass xxxx密碼,然後 --cluster-replicas 1 中的1表示每個master節點有1個從節點。
上述命令執行完以後會有一個詢問: Can I set the above configuration? yes同意自動做好的分片即可。
最後 All 16384 slots covered. 表示集群中16384個slot中的每一個都有至少有1個master節點在處理,集群啟動成功。
查看集群狀態:
坑1:暴露給客戶端的節點地址不對
使用lettuce連接發現連不上,查看日誌 Connection refused: no further information: /127.0.0.1:7002 ,跟之前哨兵配置文件sentinel.conf里邊配置master地址犯的錯誤一樣,集群啟動的時候帶的地址應該是提供給客戶端訪問的地址。
我們要重建集群:先把6個redis進程停掉,然後刪除 nodes-7001.conf 這些節點配置文件,刪除持久化文件 mp.rdb 、 appendonly.aof ,重新啟動6個進程,在重新建立集群:
然後,還是連不上,這次報錯 connection timed out: /172.xx.0.xx:7004 ,發現連到企鵝雲伺服器的內網地址上了!
解決辦法,修改每個節點的redis.conf配置文件,找到如下說明:
所以增加配置:
然後再重新構建集群,停進程、改配置、刪除節點文件和持久化文件、啟動進程、配置集群。。。再來一套(累死了)
重新使用Lettuce測試,這次終於連上了!
坑2:Lettuce客戶端在master節點故障時沒有自動切換到從節點
name這個key在7002上,kill這個進程模擬master下線,然後Lettuce一直重連。我們期望的是應該能自動切換到其slave 7006上去,如下圖:
重新啟動7002進程,
7006已成為新master,7002成為它的slave,然後Lettuce也能連接上了。
解決辦法,修改Lettuce的配置:
筆者用的是springboot 2.1 spring-boot-starter-data-redis 默認的Lettuce客戶端,當使用Redis cluster集群模式時,需要配置一下 RedisConnectionFactory 開啟自適應刷新來做故障轉移時的自動切換從節點進行連接。
重新測試:停掉master 7006,這次Lettuce可以正常切換連到7002slave上去了。(仍然會不斷的在日誌里報連接錯誤,因為需要一直嘗試重連7006,但因為有7002從節點頂上了、所以應用是可以正常使用的)
Redis不保證數據的強一致性
Redis並不保證數據的強一致性,也就是取CAP定理中的AP
關於一致性Hash演算法,可以參考 一致性Hash演算法 - (jianshu.com)
Redis cluster使用的是hash slot演算法,跟一致性Hash演算法不太一樣,固定16384個hash槽,然後計算key落在哪個slot里邊(計算key的CRC16值再對16384取模),key找的是slot而不是節點,而slot與節點的對應關系可以通過reshard改變並通過gossip協議擴散到集群中的每一個節點、進而可以為客戶端獲知,這樣key的節點定址就跟具體的節點個數沒關系了。也同樣解決了普通hash取模演算法當節點個數發生變化時,大量key對應的定址都發生改動導致緩存失效的問題。
比如集群增加了1個節點,這時候如果不做任何操作,那麼新增加的這個節點上是沒有slot的,所有slot都在原來的節點上且對應關系不變、所以沒有因為節點個數變動而緩存失效,當reshard一部分slot到新節點後,客戶端獲取到新遷移的這部分slot與新節點的對應關系、定址到新節點,而沒遷移的slot仍然定址到原來的節點。
關於熱遷移,猜想,內部應該是先做復制遷移,等遷移完了,再切換slot與節點的對應關系,復制沒有完成之前仍按照原來的slot與節點對應關系去原節點訪問。復制結束之後,再刪除原節點上已經遷移的slot所對應的key。
與哨兵模式比較類似,當1個節點發現某個master節點故障了、會對這個故障節點進行pfail主觀宕機,然後會通過gossip協議通知到集群中的其他節點、其他節點也執行判斷pfail並gossip擴散廣播這一過程,當超過半數節點pfail時那麼故障節點就是fail客觀宕機。接下來所有的master節點會在故障節點的從節點中選出一個新的主節點,此時所有的master節點中超過半數的都投票選舉了故障節點的某個從節點,那麼這個從節點當選新的master節點。
所有節點都持有元數據,節點之間通過gossip這種二進制協議進行通信、發送自己的元數據信息給其他節點、故障檢測、集群配置更新、故障轉移授權等等。
這種去中心化的分布式節點之間內部協調,包括故障識別、故障轉移、選主等等,核心在於gossip擴散協議,能夠支撐這樣的廣播協議在於所有的節點都持有一份完整的集群元數據,即所有的節點都知悉當前集群全局的情況。
Redis高可用方案 - (jianshu.com)
面試題:Redis 集群模式的工作原理能說一下么 - 雲+社區 - 騰訊雲 (tencent.com)
深度圖解Redis Cluster原理 - detectiveHLH - 博客園 (cnblogs.com)
Redis學習筆記之集群重啟和遇到的坑-阿里雲開發者社區 (aliyun.com)
雲伺服器Redis集群部署及客戶端通過公網IP連接問題
『伍』 分布式緩存redis是無狀態類應用嗎
是。
Redis緩存伺服器技術來管理芹梁用戶端和服鄭粗務器之間所產生的無狀態會話,喊首鎮並通過實驗證實了採用該技術能有效管理用戶訪問系統所產生的無狀態會話。分布式緩存的應用就是必然的redis集群目前可以知道的redis實現的集群方式是有兩種的,一種是主從復制,一種是分片主從復制。
『陸』 細說分布式redis
IT培訓>資料庫教程
細說分布式Redis架構設計和踩過的那些坑
作者:課課家教育2015-12-14 10:15:25
摘要:本文章主要分成五個步驟內容講解
Redis、RedisCluster和Codis;
我們更愛一致性;
Codis在生產環境中的使用的經驗和坑們;
對於分布式資料庫和分布式架構的一些看法;
Q & A環節。
Codis是一個分布式Redis解決方案,與官方的純P2P的模式不同,Codis採用的是Proxy-based的方案。今天我們介紹一下Codis及下一個大版本RebornDB的設計,同時會介紹一些Codis在實際應用場景中的tips。最後拋磚引玉,會介紹一下我對分布式存儲的一些觀點和看法,望各位首席們雅正。
細說分布式Redis架構設計和踩過的那些坑_redis 分布式_ redis 分布式鎖_分布式緩存redis
一、 Redis,RedisCluster和Codis
Redis:想必大家的架構中,Redis已經是一個必不可少的部件,豐富的數據結構和超高的性能以及簡單的協議,讓Redis能夠很好的作為資料庫的上游緩存層。但是我們會比較擔心Redis的單點問題,單點Redis容量大小總受限於內存,在業務對性能要求比較高的情況下,理想情況下我們希望所有的數據都能在內存裡面,不要打到資料庫上,所以很自然的就會尋求其他方案。 比如,SSD將內存換成了磁碟,以換取更大的容量。更自然的想法是將Redis變成一個可以水平擴展的分布式緩存服務,在Codis之前,業界只有Twemproxy,但是Twemproxy本身是一個靜態的分布式Redis方案,進行擴容/縮容時候對運維要求非常高,而且很難做到平滑的擴縮容。Codis的目標其實就是盡量兼容Twemproxy的基礎上,加上數據遷移的功能以實現擴容和縮容,最終替換Twemproxy。從豌豆莢最後上線的結果來看,最後完全替換了Twem,大概2T左右的內存集群。
Redis Cluster :與Codis同期發布正式版的官方cl
『柒』 什麼是Redis
redis 就是一個資料庫,不過與傳統資料庫不同的是 redis 的數據是存在內存和部分文件中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向。另外,redis 也經常用來做分布式鎖。redis 提供了多種數據類型來支持不同的業務場景。除此之外,redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集群方案。
『捌』 分布式緩存的作用
分布式緩存主要用於在高並發環境下,減輕資料庫的壓力,提高系統的響應速度和並發吞吐。當大量的讀、寫請求湧向資料庫時,磁碟的處理速度與內存顯然不在一個量級,因此,在資料庫之前加一層緩存,能夠顯著提高系統的響應速度,並降低資料庫的壓力。作為傳統的關系型資料庫,Mysql提供完整的ACID操作,支持豐富的數據類型、強大的關聯查詢、where語句等,能夠非常客易地建立查詢索引,執行復雜的內連接、外連接、求和、排序、分組等操作,並且支持存儲過程、函數等功能,產品成熟度高,功能強大。但是,對於需要應對高並發訪問並且存儲海量數據的場景來說,出於對性能的考慮,不得不放棄很多傳統關系型資料庫原本強大的功能,犧牲了系統的易用性,並且使得系統的設計和管理變得更為復雜。這也使得在過去幾年中,流行著另一種新的存儲解決方案——NoSQL,它與傳統的關系型資料庫最大的差別在於,它不使用SQL作為查詢語言來查找數據,而採用key-value形式進行查找,提供了更高的查詢效率及吞吐,並且能夠更加方便地進行擴展,存儲海量數據,在數千個節點上進行分區,自動進行數據的復制和備份。在分布式系統中,消息作為應用間通信的一種方式,得到了十分廣泛的應用。消息可以被保存在隊列中,直到被接收者取出,由於消息發送者不需要同步等待消息接收者的響應,消息的非同步接收降低了系統集成的耦合度,提升了分布式系統協作的效率,使得系統能夠更快地響應用戶,提供更高的吞吐。
當系統處於峰值壓力時,分布式消息隊列還能夠作為緩沖,削峰填谷,緩解集群的壓力,避免整個系統被壓垮。垂直化的搜索引擎在分布式系統中是一個非常重要的角色,它既能夠滿足用戶對於全文檢索、模糊匹配的需求,解決資料庫like查詢效率低下的問題,又能夠解決分布式環境下,由於採用分庫分表,或者使用NoSQL資料庫,導致無法進行多表關聯或者進行復雜查詢的問題。
『玖』 Redis是什麼,用來做什麼
Redis是一個nosql資料庫,可以存儲key-value值。因為其底層實現中,數據讀寫是基於內存,速度非常快,所以常用於緩存;進而因其為獨立部署的中間件,常用於分布式緩存的實現方案。
常用場景有:緩存、秒殺控制、分布式鎖。
雖然其是基於內存讀寫,但底層也有持久化機制;同時具備集群模式;不用擔心其可用性。
關於Redis的使用,可以參考《Redis的使用方法、常見應用場景》