Redis 集羣詳解 環境搭建 調用案例

http://www.jianshu.com/p/dbc62ed27f03

這是redis集羣介紹的上篇,主要是關於Redis集羣的搭建。後續將爲大家介紹Redis集羣的常用命令、Java操作Redis集羣、以及與Spring/Spring MVC的整合等知識。

Redis集羣搭建

要想搭建一個最簡單的Redis集羣,那麼至少需要6個節點:3個Master和3個Slave。爲什麼需要3個Master呢?如果你瞭解過Hadoop/Storm/Zookeeper這些的話,你就會明白一般分佈式要求基數個節點,這樣便於選舉(少數服從多數的原則)。


Redis集羣模型

這裏,我將採用一種“偷懶”的方式,在一個Linux虛擬機上搭建6個節點的Redis集羣。(因爲開啓6個Linux虛擬機,我的電腦完全扛不住)

實際上,思路很簡單,我將在一臺節點上開啓6個Redis實例,並且這6個Redis各自有自己的端口。這樣的話,相當於模擬出了6臺機器了。然後在以這6個實例組建Redis集羣就可以了。

第一步:爲這6個實例創建好各自存放的目錄


想一想,爲什麼要這樣做呢?

第二步:既然是要啓動6個Redis實例,自然需要準備各自的配置文件


拷貝redis.conf 6份



6個Redis實例的具體配置

具體來說,需要注意下:由於在一臺機器(192.168.99.121)上,因此每個實例應該有不同的端口;同時,每個實例顯然會有自己的存放數據的地方;開啓AOF模式;開啓集羣配置;開啓後臺模式;

第三步:實際上,Redis集羣的操作在後文你可以看到是通過Ruby腳本來完成的,因此我們需要安裝Ruby相關的RPM包,以及Redis和Ruby的接口包。


yum install ruby

yum install rubygems

gem install redis

第四步:讓Redis集羣工作起來!


啓動6個Redis實例

接下來,我們要通過Ruby腳本來創建集羣了。


redis-trib.rb是操作Redis集羣的腳本

[root@mydream121 bin]# ./redis-trib.rb create --replicas 1 192.168.99.121:8001 192.168.99.121:8002 192.168.99.121:8003 192.168.99.121:8004 192.168.99.121:8005 192.168.99.121:8006


create redis cluster

redis cluster info

首先,我們來看一下創建集羣命令中 --replicas 1,這個代表什麼意思呢?1其實代表的是一個比例,就是主節點數/從節點數的比例。那麼想一想,在創建集羣的時候,哪些節點是主節點呢?哪些節點是從節點呢?答案是將按照命令中IP:PORT的順序,先是3個主節點,然後是3個從節點。這一點可以通過上面的2張圖片印證。

其次,注意到圖中slot的概念。slot對於Redis集羣而言,就是一個存放數據的地方,就是一個槽。對於每一個Master而言,會存在一個slot的範圍,而Slave則沒有。在Redis集羣中,依然是Master可以讀、寫,而Slave只讀。數據的寫入,實際上是分佈的存儲在slot中,這和以前1.X的主從模式是不一樣的(主從模式下Master/Slave數據存儲是完全一致的),因爲Redis集羣中3臺Master的數據存儲並不一樣。這一點將在後續的實驗中得到驗證。

第五步:驗證Redis集羣搭建是否成功


cluster info/cluster nodes

搭建起來的Redis集羣


到這裏,Redis集羣的搭建就完畢了,See U~


接上一篇《玩轉Redis集羣(上)》,我們來繼續玩~

Redis集羣操作實踐

數據的分佈性



數據分佈性

從上面的操作,你可以看到,當存儲某一個數據的時候,會分配一個slot,而這個slot從屬於某一個Master,也就是說你需要明白,數據是分佈的存儲在Redis集羣當中的。

在線水平擴容

Redis Cluster有一個非常重要的特點就是可以在線的添加節點,實現不影響業務的水平擴容。在這裏,我將會在原來6個redis節點上,再添加2個redis節點。做法和以前一致,注意修改redis.conf,然後在啓動8007、8008這2個redis實例。


修改redis.conf配置



啓動新添加的2個redis實例



集羣狀態

其實,目前雖然啓動了新加的2個redis實例,但是它們是不屬於集羣的。下面,我們來讓它們加入集羣中。


add-node命令

./redis-trib.rb add-node 192.168.99.121:8007 192.168.99.121:8006

./redis-trib.rb add-node 新節點 集羣中已經存在的節點

在往集羣中添加節點A的時候,需要提供一個在集羣中已經存在的節點B的信息。因爲知道了B的信息,就知道了整個集羣的信息。爲什麼這麼說呢,來,我們看一個文件,你就知道了。


nodes-xxx.conf

要知道集羣中的每一個節點都有這麼一個文件,存儲着集羣中每一個節點的信息:節點的角色、節點的ID、連接狀態、slot範圍、IP/PORT信息等。仔細觀察圖中,你可以發現,新加入的8007節點,實際上被默認爲master節點,並且沒有slot分配!這說明,新加入的節點現在還不可以存儲數據,因此我們要爲新節點分配slot槽。

[root@mydream121 bin]# ./redis-trib.rb reshard 192.168.99.121:8001

要知道slot都分配在master上,因此其實我們要做的就是從集羣的masters上進行重新分配。上面的命令需要指定一個master節點進行reshard分片。


slot重新分配

圖中要爲新加入的節點8007分配500個slot,而且分配的方式是"all",all是什麼意思呢?all代表從已經存在的所有的master上均勻的分配一部分slot給8007。當然你可以通過"done"來指定某一個master進行分配。注意分配給8007是通過節點ID來指定的。


分配後的集羣信息

按照上面的操作,我將8008節點也加入集羣中,我的想法是讓8008成爲8007的從節點。既然是從節點,就不需要分配slot槽。注意到add-node方式加入的節點,默認就是master節點,因此這裏我們得利用replicate指定主節點。

[root@mydream121 bin]# ./redis-trib.rb add-node 192.168.99.121:8008 192.168.99.121:8001



爲從節點指定主節點

那麼到現在,我們就在線完成了對Redis集羣的水平擴容。那麼如何刪除節點呢?刪除節點時,數據怎麼辦呢?對於從節點,刪除就刪除了,並不要緊,關鍵是主節點,因爲主節點上有slot。因此,在刪除主節點前,我們要對主節點的slot進行重新分配,完成數據的遷移。這裏我就不再演示了,直接給出命令。

刪除主節點:先reshard + 後del-node

刪除從節點:直接del-node


Redis實現Session共享

Redis可以被用於Session共享,不過現在CAS實現單點登錄更容易些。(CAS以後爲大家介紹)


redis集羣存儲session信息

不論是Nginx掛了,還是其中的Tomcat掛掉,都不會丟失Session信息。在實現上,有現成的插件,比如:https://github.com/jcoleman/tomcat-redis-session-manager 


Java操作Redis

在單機Redis環境:Jedis

這個沒什麼好說的,就是給定IP/PORT實例化Jedis操作即可。

Jedis jedis = new Jedis("192.168.99.121", 8001);

在多臺Redis環境:ShardedJedis+ShardedJedisPool


ShardedJedis方式

這是一種切片的方式來操作redis,通過hash而均勻的分配到pool裏的redis機器中。

在Redis集羣環境:JedisCluster


JedisCluster

與Spring整合

我們直接來看配置文件吧!


redis集羣與Spring整合

同上文Java操作Redis集羣的代碼對比下,其實XML就是代碼的映射。只不過通過spring的方式,幫助我們配置生成了一個bean:redisCluster。我們可以通過注入的方式得到redisCluster,然後我們想幹啥就可以幹啥,就這麼簡單~


Redis高級特性介紹及實例分析

http://www.jianshu.com/p/af7043e6c8f9

本文將爲大家介紹Redis的一些高級特性以及結合一個具體的實際案例來對Redis進行設計分析。

Redis基礎類型回顧

String

Redis中最基本,也是最簡單的數據類型。注意,VALUE既可以是簡單的String,也可以是複雜的String,如JSON,在實際中常常利用fastjson將對象序列化後存儲到Redis中。另外注意mget批量獲取可以提高效率。

Hash

Hash結構適用於存儲對象,相較於String,存儲佔用更少的內存。Hash結構可以使你像在數據庫中Update一個屬性一樣只修改某一項屬性值,而且還可以快速定位數據。比如,如果我們把表User中的數據可以這樣放置到Redis中:Hash存儲,KEY:User,Field:USERID,VALUE:user序列化後的string。

List

既可以當做棧、又可以當做隊列。實際上,可以利用List的先進先出或者先進後出的特性維護一段列表,比如排行榜、實時列表等,甚至還可以簡單的當做消息隊列來使用。

Set

Set是String類型的不重複無序集合。Set的特點在於,它提供了集合的一些運算,比如交集、並集、差集等。這些運算特性,非常方便的解決實際場景中的一些問題,如共同關注、共同粉絲等。

ZSet

ZSet就是SortedSet。實際中,很多排序場景都可以考慮ZSet來做。


Redis發展過程中的三種模式:主從、哨兵、集羣

Redis的發展可以從版本的變化看出來,從1.X的主從模式,到2.X的哨兵模式,再到今天3.X的集羣模式,可以說這些都是Redis保證數據可靠性、高可用的思路。下面我們來簡單實踐下。環境說明:這裏準備了4臺Centos Linux,裝有redis的3.0版本。


主從模式

Redis早期用於保證數據可靠性的一種簡單方式。具體來說,Master可用於寫、讀,而Slave一般只用於讀。


其實在配置上相當簡單,只需要在Slave節點配置下Master的IP、PORT、密碼即可。


192.168.99.122/123 redis.conf

Master info



master info

Slave info



slave info

一個Master可以擁有多個Slave

主從複製不會阻塞住Master,在同步數據時Master可以繼續處理client端請求

哨兵模式


對於主從複製模式而言,有個明顯的缺點:一旦主節點掛了,那麼redis服務將不可用。在2.X中,爲了確保可高用,所以發展出來哨兵模式。顧名思義,就是哨兵站崗,去監聽master心跳,如果master掛了,那麼將從slave中選舉出一個master來,從而實現了故障自動切換。

實質上,在Master-Slave模式基礎上,只需要在啓動一個哨兵服務進行監聽就可以,這個哨兵服務可以部署在Master/Slave上,也可以部署到其他機器上。當然,在實際中爲了避免哨兵節點的單點性,也會配置多個哨兵服務。

哨兵節點192.168.99.124  sentinel.conf:

sentinel monitor mymaster 192.168.99.121 6379 1

sentinel down-after-milliseconds mymaster 5000

sentinel parallel-syncs mymaster 2

我們需要告訴哨兵服務:

監控的主節點的IP,PORT

如果master掛了,那麼選舉的時候,slave達到多少票就可以成爲主節點

監控主節點的心跳頻率

主節點下有多少slave


集羣模式

Redis集羣模式是目前應用非常廣泛的,Redis集羣模式的出現,也使得以前的一些Redis技術,比如分片、都不在適用了,同時數據的高可靠、數據分佈性、服務的高可用性進一步加強。關於Redis集羣將在下一篇博客中詳細介紹。


Redis的簡單事務

目前來看,Redis對事務的支持是比較簡單的,在實際應用中,我們基本上是不會使用的。看一個實例,你就會明白。通過multi開啓事務,通過exec來提交事務。可以看到,redis的事務目前是不支持一起成功,一起失敗這種基本要求的,即便在事務中有錯誤,亦不會回退,和MySQL的事務功能相距甚遠吧。


redis事務

Redis持久化機制

Redis是一個支持持久化的內存數據庫,也就是說Redis需要經常將內存中的數據同步到硬盤來保證持久化,有2種方式實現。

RDB

RDB方式,也稱作快照snapshotting,將內存中的數據以快照的方式寫入到二進制文件dump.rdb中,這種方式也是redis的默認方式。可以在redis.conf中設置保存的策略。一句話:redis在N秒內如果超過M個KEY發生修改則自動做快照保存。


save機制

AOF


aof文件內容

AOF,即Append-Only File。要知道RDB的方式,是在一定的時間間隔做一次,如果redis意外down掉,這將意味着會丟失最後一次快照後的所有修改數據,這在生產環境將不太可能接受。AOF比RDB有着更好的持久化方式,通過AOF,redis會將每一個收到的寫命令都通過write函數追加到命令中,當redis重新啓動時,會重新執行文件中保存的寫命令來重建數據內容。

redis.conf:


aof策略

在實際應用中,爲了確保數據高可靠性,應該使用always策略。


發佈與訂閱消息

概念上比較簡單,如果你訂閱了頻道,那麼這個頻道上發佈的消息,你都會知道。實際中應用較多的是消息中間件(ActiveMQ,RocketMQ)的訂閱發佈模式(在以後的消息中間件專題再爲大家介紹)。


發佈



訂閱



Redis案例設計分析


我們先來看一個京東上進行商品搜索的圖.

假設一個類似的場景,有幾百萬,甚至幾千萬的商品數據,考慮下如何快速實現搜索查詢呢?當然,我們不可能直接查詢MySQL,應該需要在MySQL上加一層,可以考慮加一層Redis。


將MySQL中的數據加載至Redis中,給定條件,直接遍歷Hash數據進行查詢。如果就這樣簡單的設計的話,對於京東這樣的大流量平臺,每天有非常多的人進行商品搜索,而且每個人搜索的條件還不一樣,根本無法快速響應。


如上圖所示,我們可以這樣設計:

我們事先建立好一系列的SET,實際上這些Set都是各種分類的ProductID集合

用戶的搜索條件,實際上就是各種SET進行交、並、補的運算而已

要知道SET進行運算後的結果,就是ProductID集合,此時範圍已經有所縮小,比起直接遍歷全部商品數據要小不少

上這裏也可以看出,Redis雖然用起來簡單,但是要綜合運用,並根據業務場景進行設計,還是挺有意思的。到這裏就結束了,我們下期Redis集羣再見!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章