redis

Redis採用單線程來處理來自所有客戶端的併發請求,把任務封閉在一個線程中從而避免了線程安全問題;

Redis 是跑在單線程中的,所有的操作都是按照順序線性執行的,但是由於讀寫操作等待用戶輸入或輸出都是阻塞的,所以 I/O 操作在一般情況下往往不能直接返回,

這會導致某一文件的 I/O 阻塞導致整個進程無法對其它客戶提供服務,對此redis選擇了 I/O 多路複用模型來解決阻塞問題。

IO模型知識可以參考 https://blog.csdn.net/qq_32725403/article/details/100539974

下面舉一個例子,模擬一個tcp服務器處理30個客戶socket:
假設你是一個監考老師,讓30個學生解答一道競賽考題,然後負責驗收學生答卷,你有下面幾個選擇:

 

1. 第一種選擇:按順序逐個驗收,先驗收A,然後是B,之後是C、D。。。這中間如果有一個學生卡住,全班都會被耽誤。
這種模式就好比,你用循環挨個處理socket,根本不具有併發能力。
2. 第二種選擇:你創建30個分身,每個分身檢查一個學生的答案是否正確。 這種類似於爲每一個用戶創建一個進程或者線程處理連接。
3. 第三種選擇,你站在講臺上等,誰解答完誰舉手。這時C、D舉手,表示他們解答問題完畢,你下去依次檢查C、D的答案,然後繼續回到講臺上等。此時E、A又舉手,然後去處理E和A。。。
這種就是IO複用模型,Linux下的select、poll和epoll就是幹這個的。將用戶socket對應的fd註冊進epoll,然後epoll幫你監聽哪些socket上有消息到達,這樣就避免了大量的無用操作。此時的socket應該採用非阻塞模式。
這樣,整個過程只在調用select、poll、epoll這些調用的時候纔會阻塞,收發客戶消息是不會阻塞的,整個進程或者線程就被充分利用起來,這就是事件驅動,所謂的reactor模式。

 

針對上面的舉例在Redis中表現爲

 

有30個redis客戶端(考生)與redis服務器的網絡連接模塊(監考老師)保持TCP連接,客戶端會不定時的發送請求給服務器,當有一個redis客戶端發起請求,會觸發unix系統像epoll這樣的系統調用,Redis的I/O 多路複用模塊封裝了底層的epoll這樣的 I/O 多路複用函數,然後轉發到相應的事件處理器。文件事件處理器使用 I/O 多路複用模塊同時監聽多個 FD(文件描述符),當 acceptreadwrite 和 close 文件事件產生時,文件事件處理器就會回調 FD 綁定的事件處理器。雖然整個文件事件處理器是在單線程上運行的,但是通過 I/O 多路複用模塊的引入,實現了同時對多個 FD 讀寫的監控,提高了網絡通信模型的性能,同時也可以保證整個 Redis 服務實現的簡單。

 

1.Redis有多快?

 Redis採用的是基於內存的採用的是單進程單線程模型的 KV 數據庫,由C語言編寫,官方提供的數據是可以達到100000+的QPS

橫軸是連接數,縱軸是QPS。

2.Redis爲什麼這麼快?

1、完全基於內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中,類似於HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1);

2、數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的;

3、採用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因爲可能出現死鎖而導致的性能消耗;

4、使用多路I/O複用模型,非阻塞IO;採用多路 I/O 複用技術可以讓單個線程高效的處理多個連接請求(儘量減少網絡 IO 的時間消耗),且 Redis 在內存中操作數據的速度非常快,也就是說內存內的操作

不會成爲影響Redis性能的瓶頸,主要由以上幾點造就了 Redis 具有很高的吞吐量

5、使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因爲一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;

3.Redis爲什麼是單線程的?

因爲Redis是基於內存的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器內存的大小或者網絡帶寬。既然單線程容易實現,而且CPU不會成爲瓶頸,那就順理成章地採用單線程的方案了

由於在單線程模式的情況下已經很快了,就沒有必要在使用多線程了!但是,我們使用單線程的方式是無法發揮多核CPU 性能,不過我們可以通過在單機開多個Redis 實例來完善!

警告1:這裏我們一直在強調的單線程,只是在處理我們的網絡請求的時候只有一個線程來處理,一個正式的Redis Server運行的時候肯定是不止一個線程的,這裏需要大家明確的

注意一下!例如Redis進行持久化的時候會以子進程或者子線程的方式執行

4.Redis五種存儲類型及操作命令

    4.1 字符串   string    可存儲 字符串、整數、浮點數

  string 是 redis 最基本的類型,你可以理解成與 Memcached 一模一樣的類型,一個 key 對應一個 value。value其實不僅是String,也可以是數字。string 類型是二進制安全的。意思是 redis 的 string 可以包含任何數據。比如jpg圖片或者序列化的對象。string 類型是 Redis 最基本的數據類  型,string 類型的值最大能存儲 512MB。 

 

最基本的命令:          GET、SET、DEL        語法:GET key,SET key value   value如果有空格需要雙引號以示區分

整數遞增:                  INCR               語法:INCR key    默認值爲0,所以首先執行命令得到 1 ,不是整型提示錯誤

增加指定的整數:       INCRBY           語法:INCRBY key increment

整數遞減:                  DECR              語法:DECR key   默認值爲0,所以首先執行命令得到 -1,不是整型提示錯誤

減少指定的整數:       DECRBY          語法:DECRBY key increment

增加指定浮點數:      INCRBYFLOAT 語法:INCRBYFLOAT key increment  與INCR命令類似,只不過可以遞增一個雙精度浮點數

向尾部追加值:         APPEND           語法:APPEND key value   redis客戶端並不是輸出追加後的字符串,而是輸出字符串總長度

獲取字符串長度:     STRLEN            語法:STRLEN key  如果鍵不存在返回0,注意如果有中文時,一箇中文長度是3,redis是使用UTF-8編碼中文的

獲取多個鍵值:        MGET                語法:MGET key [key ...]  例如:MGET key1 key2    如果不在一個哈希槽會報錯

設置多個鍵值:        MSET                語法:MSET key value [key value ...]  例如:MSET key1 1 key2 "hello redis" 如果不在一個哈希槽會報錯

二進制指定位置值:GETBIT              語法:GETBIT key offset   例如:GETBIT key1 2 ,key1爲hello 返回 1,返回的值只有0或1,當key不存在或超出實際長度時爲0

設置二進制位置值:SETBIT              語法:SETBIT key offset value ,當前對象的value必須是二進制且set的數據也必須是二進制否則報錯。返回該位置的舊值

二進制是1的個數:  BITCOUNT       語法:BITCOUNT key [start end] ,start 、end爲開始和結束字節

位運算:                   BITOP              語法:BITOP operation destkey key [key ...]  ,operation支持AND、OR、XOR、NOT

偏移:                      BITPOS             語法:BITPOS key bit [start] [end]

    4.2 列表 list

列表類型存儲了一個有序的字符串雙向鏈表。常用的操作是向兩端插入新的元素。時間複雜度爲 O(1)。結構爲一個鏈表。記錄頭和尾的地址。看到這裏,Redis 數據類型的列表類型一個重大的作用呼之欲出,那就是隊列。新來的請求插入到尾部,新處理過的從頭部刪除。另外,比如微博的新鮮事。比如日誌。列表類型就是一個下標從 0 開始的數組。由於是鏈表存儲,那麼越靠近頭和尾的元素操作越快,越靠近中間則越慢。

 

添加左邊元素:           LPUSH                   語法:LPUSH key value [value ...]  ,將元素推入列表的左端  返回添加後的列表元素的總個數

添加右邊元素:           RPUSH                   語法:RPUSH key value [value ...]  ,將元素推入列表的右端  返回添加後的列表元素的總個數

移除左邊第一個元素:LPOP                      語法:LPOP key  ,從列表左端彈出元素 返回被移除的元素值

移除右邊第一個元素:RPOP                      語法:RPOP key ,從列表右端彈出元素 返回被移除的元素值 

列表元素個數:           LLEN                       語法:LLEN key, 不存在時返回0,redis是直接讀取現成的值,並不是統計個數

獲取列表片段:           LRANGE                  語法:LRANGE key start stop,如果start比stop靠後時返回空列表,0 -1 返回整個列表正數時:start 開始索引值,stop結束索引值(索引從0開始)負數時:例如 lrange num -2 -1,-2表示最右邊第二個,-1表示最右邊第一個,

刪除指定值:               LREM                      語法:LREM key count value,返回被刪除的個數 count>0,從左邊開始刪除前count個值爲value的元素count<0,從右邊開始刪除前|count|個值爲value的元素 count=0,刪除所有值爲value的元素

索引元素值:               LINDEX                    語法:LINDEX key index ,返回索引的元素值,-1表示從最右邊的第一位

設置元素值:               LSET                         語法:LSET key index value

保留列表片段:           LTRIM                       語法:LTRIM key start stop,start、top 參考lrange命令

一個列表轉移另一個列表:RPOPLPUSH      語法:RPOPLPUSH source desctination ,從source列表轉移到desctination列表,該命令分兩步看,首先source列表RPOP右移除,再desctination列表LPUSH

 

    4.3 集合 set

集合類型是爲了方便對多個集合進行操作和運算。集合中每個元素不同且沒有順序的概念,每個元素都是且只能是一個字符串。常用操作是對集合插入、刪除、判斷等操作。時間複雜度尾 O(1)。可以進行交集、並集、差集運算。例如文章 1 的有 3 個標籤,是一個 Redis 數據類型集合類型存儲。文章 2 有 3 個標籤,有一個 Redis 數據類型集合類型存儲。文章是 1 是 mysql,文章 2 是講 redis。那麼交集是不是就交出了一個數據庫?(假設數據庫這個tag在兩篇文字都有)。集合類型在 redis 中的存儲是一個值爲空的散列表(哈希表)。

 

添加元素:            SADD               語法:SADD key member [member ...] ,向一個集合添加一個或多個元素,因爲集合的唯一性,所以添加相同值時會被忽略。 返回成功添加元素的數量。

刪除元素:            SREM               語法:SREM key member [member ...] 刪除集合中一個或多個元素,返回成功刪除的個數。

獲取全部元素:     SMEMBERS     語法:SMEMBERS key ,返回集合全部元素

值是否存在:        SISMEMBER    語法:SISMEMBER key member ,如果存在返回1,不存在返回0

差運算:                SDIFF              語法:SDIFF key [key ...] ,例如:集合A和集合B,差集表示A-B,在A裏有的元素B裏沒有,返回差集合;多個集合(A-B)-C

交運算:                SINTER           語法:SINTER key [key ...],返回交集集合,每個集合都有的元素

並運算:                SUNION   語法:SUNION key [key ...],返回並集集合,所有集合的元素

集合元素個數:     SCARD           語法:SCARD key ,返回集合元素個數

集合運算後存儲結果                    語法:SDIFFSTROE destination key [key ...] ,差運算並存儲到destination新集合中

                   SINTERSTROE destination key [key ...],交運算並存儲到destination新集合中

                                                                SUNIONSTROE destination key [key ...],並運算並存儲到destination新集合中

隨機獲取元素:SRANDMEMGER 語法:SRANDMEMBER key [count],根據count不同有不同結果,count大於元素總數時返回全部元素count>0 ,返回集合中count不重複的元素count<0,返回集合中count的絕對值個元素,但元素可能會重複

彈出元素:SPOP                          語法:SPOP key [count] ,因爲集合是無序的,所以spop會隨機彈出一個元素

    4.4 散列 hash

Redis 是以字典(關聯數組)的形式存儲的,一個 key 對應一個 value。在字符串類型中,value 只能是一個字符串。那麼在散列類型,也叫哈希類型中,value 對應的也是一個字典(關聯數組)。那麼就可以理解,Redis 的哈希類型/散列類型中,key 對應的 value 是一個二維數組。但是字段的值只可以是字符串。也就是說只能是二維數組,不能有更多的維度。  每個hash可以存儲2的32次方 -1個鍵值對(40多億)

設置單個:                HSET                      語法:HSET key field value,不存在時返回1,存在時返回0,沒有更新和插入之分

設置多個:               HMSET                    語法:HMSET key field value [field value ...]

讀取單個:               HGET                      語法:HGET key field,不存在是返回nil

讀取多個:               HMGET                    語法:HMGET key field [field ...]

讀取全部:               HGETALL                 語法:HGETALL key,返回時字段和字段值的列表

判斷字段是否存在:HEXISTS                   語法:HEXISTS key field,存在返回1 ,不存在返回0

字段不存在時賦值:HSETNX                   語法:HSETNX key field value,與hset命令不同,hsetnx是鍵不存在時設置值

增加數字:              HINCRBY                  語法:HINCRBY key field increment ,返回增加後的數,不是整數時會提示錯誤

刪除字段:              HDEL                        語法:HDEL key field [field ...] ,返回被刪除字段的個數

只獲取字段名:       HKEYS                      語法:HKEYS key ,返回鍵的所有字段名

只獲取字段值:       HVALS                     語法:HVALS key  ,返回鍵的所有字段值

字段數量:              HLEN                       語法:HLEN key ,返回字段總數

    4.5 有序集合 zset

集合類型是無序的,每個元素是唯一的。那麼有序集合就是有序的,每個元素是唯一的。有序集合類型和集合類型的差別是,有序集合爲每個元素配備了一個屬性:分數。有序集合就是根據分數來排序的。有序集合是使用散列表和跳躍表實現的。所以和列表相比,操作中間元素的速度也很快。時間複雜度尾 O(log(N))。Redis 數據類型中的有序集合類型比 Redis 數據類型中的列表類型更加耗費資源。

啥是跳躍表?  詳細的咱們可以看這個博客  https://www.cnblogs.com/acfox/p/3688607.html  你就記住他是爲了減少尋址次數就好。就是爲了快!

 

添加集合元素:        ZADD                       語法:ZADD key [NX|XX] [CH] [INCR] score member [score member ...],不存在添加,存在更新。

獲取元素分數:        ZSCORE                    語法:ZSCORE key member ,返回元素成員的score 分數

元素小到大:            ZRANGE                   語法:ZRANGE key start top [WITHSCORES] ,參考LRANGE ,加上withscores 返回帶元素,即元素,分數當分數一樣時,按元素排序

元素大到小:           ZREVRANGE              語法:ZREVRANGE key start [WITHSCORES] ,與zrange區別在於zrevrange是從大到小排序

指定分數範圍元素:ZRANGEBYSCORE     語法:ZRANGEBYSCORE key min max [WITHSCORE] [LIMIT offest count]

                                      返回從小到大的在min和max之間的元素,( 符號表示不包含,例如:80-100,(80 100,

                                         withscore返回帶分數

                                         limit offest count 向左偏移offest個元素,並獲取前count個元素

指定分數範圍元素:ZREVRANGESCORE   語法:ZREVRANGEBYSCORE key max  min [WITHSCORE] [LIMIT offest count]與zrangebyscore類似,只不過該命令是從大到小排序的。

增加分數:              ZINCRBY                    語法:ZINCRBY key increment member ,注意是增加分數,返回增加後的分數;如果成員不存在,則添加一個爲0的成員。

Redis一共有幾種數據類型?五種嗎?不止!其實除了我們面試常說的string、list、hash、set、zset這五種基本類型以外它還包括 Bitmaps,Hyperloglogs,GEO。

    4.6 Bitmaps

   

bitmaps不是一個真實的數據結構。而是String類型上的一組面向bit操作的集合。由於strings是二進制安全的blob,並且它們的最大長度是512m,所以bitmaps能最大設置2^32個不同的bit。

Bitmaps的最大優點就是存儲信息時可以節省大量的空間。例如在一個系統中,不同的用戶被一個增長的用戶ID表示。40億(2^32=4*1024*1024*1024≈40億)用戶只需要512M內存就能記住某種信息,例如用戶是否登錄過。

bit操作被分爲兩組:

1.恆定時間的單個bit操作,例如把某個bit設置爲0或者1。或者獲取某bit的值。

2.對一組bit的操作。例如給定範圍內bit統計(例如人口統計)。

 

二進制指定位置值:GETBIT              語法:GETBIT key offset   例如:GETBIT key1 2 ,key1爲hello 返回 1,返回的值只有0或1,當key不存在或超出實際長度時爲0

設置二進制位置值:SETBIT              語法:SETBIT key offset value ,當前對象的value必須是二進制且set的數據也必須是二進制否則報錯。返回該位置的舊值 SETBIT命令第一個參數是位編號,第二個參數是這個位的值,只能是0或者1。如果bit地址超過當前string長度,會自動增大string。

二進制是1的個數:   BITCOUNT       語法:BITCOUNT key [start end] ,start 、end爲開始和結束字節  統計位的值爲1的數量。

位運算:                   BITOP               語法:BITOP operation destkey key [key ...]  ,operation支持AND、OR、XOR、NOT

偏移:                       BITPOS             語法:BITPOS key bit [start] [end]  尋址第一個爲0或者1的bit的位置(尋址第一個爲1的bit的位置:bitpos dupcheck 1; 尋址第一個爲0的bit的位置:bitpos dupcheck 0).

bitmaps一般的使用場景:

各種實時分析.

存儲與對象ID關聯的節省空間並且高性能的布爾信息.

例如,想象一下你想知道訪問你的網站的用戶的最長連續時間。你開始計算從0開始的天數,就是你的網站公開的那天,每次用戶訪問網站時通過SETBIT命令設置bit爲1,可以簡單的用當前時間減去初始時間併除以3600*24(結果就是你的網站公開的第幾天)當做這個bit的位置。

這種方法對於每個用戶,都有存儲每天的訪問信息的一個很小的string字符串。通過BITCOUN就能輕易統計某個用戶連續訪問網站的天數。另外通過調用BITPOS命令,或者客戶端獲取並分析這個bitmap,就能計算出最長停留時間。
 

    4.7 HyperLogLogs

 

HyperLogLog是用於計算唯一事物的概率數據結構(從技術上講,這被稱爲估計集合的基數)。如果統計唯一項,項目越多,需要的內存就越多。因爲需要記住過去已經看過的項,從而避免多次統計這些項。

然而,有一組算法可以交換內存以獲得精確度:在redis的實現中,您使用標準錯誤小於1%的估計度量結束。這個算法的神奇在於不再需要與需要統計的項相對應的內存,取而代之,使用的內存一直恆定不變。最壞的情況下只需要12k,就可以計算接近2^64個不同元素的基數。或者如果您的HyperLogLog(我們從現在開始簡稱它爲HLL)已經看到的元素非常少,則需要的內存要要少得多。

在redis中HLL是一個不同的數據結構,它被編碼成Redis字符串。因此可以通過調用GET命令序列化一個HLL,也可以通過調用SET命令將其反序列化到redis服務器。

HLL的API類似使用SETS數據結構做相同的任務,SETS結構中,通過SADD命令把每一個觀察的元素添加到一個SET集合,用SCARD命令檢查SET集合中元素的數量,集合裏的元素都是唯一的,已經存在的元素不會被重複添加。

而使用HLL時並不是真正添加項到HLL中(這一點和SETS結構差異很大),因爲HLL的數據結構只包含一個不包含實際元素的狀態,API是一樣的:

PFADD 命令用於添加一個新元素到統計中。

PFCOUNT 命令用於獲取到目前爲止通過PFADD命令添加的唯一元素個數近似值。

PFMERGE 命令執行多個HLL之間的聯合操作。

127.0.0.1:6380> PFADD hll a b c d d c

(integer) 1

127.0.0.1:6380> PFCOUNT hll

(integer) 4

127.0.0.1:6380> PFADD hll e

 (integer) 1

127.0.0.1:6380> PFCOUNT hll

(integer) 5

PFMERGE命令說明:

PFMERGE destkey sourcekey [sourcekey ...]

Merge N different HyperLogLogs into a single one.

用法(把hll1和hll2合併到hlls中):

1

2

3

4

5

6

7

127.0.0.1:6380> PFADD hll1 1 2 3

(integer) 1 

27.0.0.1:6380> PFADD hll2 3 4 5

(integer) 1 

27.0.0.1:6380> PFMERGE hlls hll1 hll2

OK

127.0.0.1:6380> PFCOUNT hlls

HLL數據結構的一個使用場景就是計算用戶每天在搜索框中執行的唯一查詢,即搜索頁面UV統計。而Bitmaps則用於判斷某個用戶是否訪問過搜索頁面。這是它們用法的不同。 

ps:這個PFMERGE有個限制:所有操作對象必須在同一服務器。

 

 

    4.8 GEO

Redis的GEO特性在 Redis3.2版本中推出,這個功能可以將用戶給定的地理位置(經度和緯度)信息儲存起來,並對這些信息進行操作。GEO相關命令只有6個:

 

 

GEOADD:GEOADD key longitude latitude member [longitude latitude member …],將指定的地理空間位置(緯度、經度、名稱)添加到指定的key中。例如:GEOADD city 113.501389 22.405556 shenzhen;

經緯度具體的限制,由EPSG:900913/EPSG:3785/OSGEO:41001規定如下:

有效的經度從-180度到180度。

有效的緯度從-85.05112878度到85.05112878度。

當座標位置超出上述指定範圍時,該命令將會返回一個錯誤。

 

GEOHASH:GEOHASH key member [member …],返回一個或多個位置元素的標準Geohash值,它可以在http://geohash.org/使用。查詢例子:http://geohash.org/sqdtr74hyu0.(可以通過谷歌瞭解Geohash原理,或者戳Geohash基本原理:https://www.cnblogs.com/tgzhu/p/6204173.html)。

 

GEOPOS:GEOPOS key member [member …],從key裏返回所有給定位置元素的位置(經度和緯度)。

 

GEODIST:GEODIST key member1 member2 [unit],返回兩個給定位置之間的距離。GEODIST命令在計算距離時會假設地球爲完美的球形。在極限情況下,這一假設最大會造成0.5%的誤差。

指定單位的參數unit必須是以下單位的其中一個:

m 表示單位爲米(默認)。

km 表示單位爲千米。

mi 表示單位爲英里。

ft 表示單位爲英尺。

 

GEORADIUS:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count],以給定的經緯度爲中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素。這個命令可以查詢某城市的周邊城市羣。  

 

GEORADIUSBYMEMBER:GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count],這個命令和GEORADIUS命令一樣,都可以找出位於指定範圍內的元素,但是GEORADIUSBYMEMBER的中心點是由給定的位置元素決定的,而不是像 GEORADIUS那樣,使用輸入的經度和緯度來決定中心點。  

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"

(integer) 2

  

redis> GEOHASH Sicily Palermo Catania

1"sqc8b49rny0"

2"sqdtr74hyu0"

  

redis> GEOPOS Sicily Palermo Catania NonExisting

11"13.361389338970184"

   2"38.115556395496299"

21"15.087267458438873"

   2"37.50266842333162"

3) (nil)

  

redis> GEODIST Sicily Palermo Catania

"166274.15156960039"

  

redis> GEORADIUS Sicily 15 37 100 km

1"Catania"

redis> GEORADIUS Sicily 15 37 200 km

1"Palermo"

2"Catania"

  

redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km

1"Agrigento"

2"Palermo"

5.通用命令

TTL命令

expire key seconds  設置鍵過期時間 Redis 支持對  添加 過期時間,當超過過期時間後,會 自動刪除鍵

127.0.0.1:6379> set hello world

OK

127.0.0.1:6379> expire hello 10

(integer) 0

ttl 命令會返回鍵的 剩餘過期時間,它有 3 種返回值:

 

  • 大於等於 0 的整數:表示鍵 剩餘 的 過期時間
  • 返回 -1: 沒設置 過期時間
  • 返回 -2: 不存在。

 

可以通過 ttl 命令觀察  hello 的 剩餘過期時間

# 還剩7秒

127.0.0.1:6379> ttl hello(integer)

(integer) 7

如果一個鍵是過期的那它到了過期事件之後是不是馬上就從內存中被刪除呢??如果不是,那過期之後到底什麼時候被刪除呢?這個問題是不是很熟悉?是不是一臉黑線的想起了某次面試。。

過期鍵的刪除策略:

其實有三種不同的刪除策略:

1.立即刪除。在設置鍵的過期時間是創建一個回調事件,當過期時間到達時,由事件處理器自動執行鍵的刪除操作。  這個對cpu是最不友好的。因爲刪除操作會佔用cpu時間,而且它不管你忙不忙。

2.惰性刪除。鍵過期了就過期了,不管。每次從dict中按鍵取值時看到它過期了就刪除它然後返回nil,如果沒有就返回鍵值。 這個對內存是不友好的,因爲過期數據在下次訪問前仍一直存在於內存中。

3.定時刪除。每個一段時間,對expires字典進行檢查,刪除裏面的過期值。  上面倆都不好使,就剩這一個了,這個也是比較折中的一個刪除策略了。

有沒有更好的解決辦法呢?

redis中對於過期的數據選擇的是惰性刪除和定時刪除配合使用 這樣 浪費的內存不會浪費太長時間,cpu也不會每次響應過期操作。

 

type key  鍵的數據結構類型

127.0.0.1:6379> set a b

OK

127.0.0.1:6379> type a

string

性能查看:這個命令不是cli命令因此需要命令行執行。

redis-benchmark -h 192.168.189.131 -p 7001 -q -d 10000  #SET/GET 100 bytes 檢測host爲127.0.0.1 端口爲6379的redis服務器性能
redis-benchmark -h 127.0.0.1 -p 6379 -c 5000 -n 100000  5000個併發連接,100000個請求,檢測host爲127.0.0.1 端口爲6379的redis服務器性能 

如果不給參數的話,即:redis-benchmark 那麼默認的會以50個客戶端進行性能測試。

6.數據結構

    6.1 上圖: 

對於每種 數據結構,實際上都有自己底層的 內部編碼 實現,而且是 多種實現。這樣 Redis 會在合適的 場景 選擇合適的 內部編碼3.0之後list鍵已經不直接用ziplist和linkedlist作爲底層實現了,取而代之的是quicklist   A doubly linked list of ziplists)  

想看詳細的  看這個 https://blog.csdn.net/men_wen/article/details/70229375

可以看到,每種 數據結構 都有 兩種以上 的 內部編碼實現。例如 list 數據結構 包含了 linkedlist 和 ziplist 兩種 內部編碼。同時有些 內部編碼,例如 ziplist,可以作爲 多種外部數據結構 的內部實現,可以通過 object encoding 命令查詢 內部編碼

127.0.0.1:6379> object encoding hello

"embstr"

127.0.0.1:6379> object encoding mylist

"quicklist"

 

 6.2 這裏有必要說一下這個ziplist和inset: 這種數據結構 被稱爲 短結構

   6.2.1 ziplist:

在列表、散列和有序集合的長度較短或體積較小的時候,Redis可以選擇使用一種名爲壓縮列表(ziplist)的緊湊存儲方式來存儲這些結構。壓縮列表是列表、散列有序集合的三種不同類型的對象的非結構化表示。壓縮列表會以序列化的方式存儲數據。因此讀取和存入需要編碼和解碼。

爲什麼說ziplist可以節省內存呢?

拿列表爲例:在典型的雙向鏈表裏面,鏈表包含的每個值都會由一個node節點表示,每個節點都會帶有指向鏈表中前一個節點和後一個節點的指針,以及一個當前節點包含的字符串值的指針。每個節點包含的字符串值都會分爲3部分進行存儲:第一部分存儲的是字符串的長度,第二部分存儲的是字符串值中剩餘可用的字節數量,而最後一部分存儲的則是以空字符串結尾的字符串本身。

例如一個較長的雙向鏈表的一部分的三個元素分別爲 one  two  ten 他們在鏈表裏的存儲方式:

圖中展示的三個3字符長的字符串,每個都需要空間來存儲3個指針、兩個整數(一個字符串長度,一個剩餘可用空間大小)、字符串本身以及一個額外的字節。在32位平臺上,每存儲這樣的3字節長的字符串,就需要付出21字節的額外開銷,而這還只是保守的估計值,實際的額外開銷還會更多一些。

壓縮列表是由節點組成的序列(sequence),每個節點都有兩長度值和一個字符串組成。第一個長度值紀錄的是前一個節點的長度,這個長度值將被用於對壓縮列表進行從後向前的遍歷,第二個長度值紀錄了當前節點的長度,而位於節點最後的則是被存儲的字符串值。這樣使用壓縮列表存儲每個節點只會有兩個字節的額外開銷。通過避免存儲額外的指針和元數據來達到節省內存的目的。 這個東西理論上可以將內存壓縮至原數據結構的1/20.

ziplist數據結構:

  • zlbytes: ziplist的長度(單位: 字節),是一個32位無符號整數
  • zltail: ziplist最後一個節點的偏移量,反向遍歷ziplist或者pop尾部節點的時候有用。
  • zllen: ziplist的節點(entry)個數
  • entry: 節點
  • zlend: 值爲0xFF,用於標記ziplist的結尾

ziplist元素結構:  這玩意極其複雜  想看細緻的 可以去簡書研究https://www.jianshu.com/p/afaf78aaf615  這裏你就記住它是將其存儲爲有長度信息描述的內存空間連續的線性結構就行了,但是這有個必須面對的問題就是刪改數據造成的內存重分配,所以衍生除了quicklist。詳見上面數據結構6.1部分。

爲了確保壓縮列表只會在有需要降低內存佔用的情況下使用,Redis引入了 配置選項,這些選項決定了列表、散列和有序集和會在什麼情況下使用壓縮列表表示。

list-max-ziplist-entries 512
list-max-ziplist-value 64

 

 

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

 

hash-max-zipmap-entries 512
hash-max-zipmap-value 64

 

entries選項說明在被編碼爲壓縮列表的情況下,允許包含的最大元素數量;

value選項說明這個壓縮列表最大體積是多少字節。當這些選項設置的限制條件中的任意一個被突破的時候,Redis就會將相應的列表、散列、有序集和從壓縮列表編碼轉換爲其他結構,而內存佔用也會因此而增加。

 

判斷一個結構是否被表示爲壓縮列表的方法:

debug object  key    encoding即爲其結構 

 6.2.2 集合的整數集合編碼inset:

跟列表、散列和有序結合一樣,體積較小的集合也有自己的緊湊表示:如果整數包含的所有成員都可以被解釋爲十進制整數,而這些數字又處於平臺的有符號整數範圍內,並且集合成員的數量又足夠少的話,

那麼Redis就會以有序整數數組的方式存儲集合,而這種存儲方式又被稱爲整數集合(inset)

以有序集合的方式存儲集合不僅可以降低內存消耗,還可以提升所有標準集合操作的執行速度。那麼一個集合要符合什麼條件才能被存儲爲整數集合呢?配置選項:

set-max-inset-entries 512

只要集合存儲的整數數量沒有超過配置設定的大小,Redis就會使用整數集合表示以減小數據的體積。

7.Redis持久化。Redis咋保證數據安全?如果出現故障數據最多損失多少?

7.1持久化方式及配置

Redis是可以完全基於內存存儲的,但是這樣有一個問題就是數據的持久化問題和容災問題。爲此Redis提供了複製和持久化選項。Redis提供了兩種不同的持久化方法來將數據存儲到硬盤裏面。使得數據在Redis重啓之後仍然存在。

一種方法叫做快照(snapshotting)它可以將存在於某一時刻的所有數據都寫入到硬盤裏面。另一種方法叫做只追加文件(append-only file AOF),他會在執行寫命令時,將被執行的寫命令複製到硬盤裏面。這兩種持久化方法

既可以同時使用又可以單獨使用。

將內存中的數據存儲到硬盤的一個主要原因是爲了在之後重用數據,或者是爲了防止系統故障而將數據備份到一個遠程位置。另外,存儲在redis中的數據有可能是長時間計算得出的,或者有程序在使用redis存儲的數據進行計算,

所以用戶希望這些數據存儲起來以便之後使用,這樣就不必重新計算了。

 

 

#快照持久化選項

save 60 1000             觸發同步保存操作的條件。 這個可以配置多個:save 3600 10 300 100  60 10000     這個東西redis是這麼判斷的:當前時間距離上次快照備份已經超過了60秒,且在這期間內發生了大於1000次寫操作。那麼執行bgsave。

stop-writes-on-bgsave-error no    #執行快照持久化時是否繼續執行寫命令

rdbcompression yes                       #是否壓縮快照文件

dbfilename dump.rdb                    #持久化文件名

快照持久化是Redis內存中的數據在某一個時間點進行備份,在創建快照之後,用戶可以對快照進行備份,需要注意的是:快照是某個時間點執行的,並不是每次更新都會創建快照。系統發生崩潰時,只能保存上次快照的數據,

因此快照持久化適用於數據不經常修改或者丟失部分數據影響不大的場景。

 

快照面臨的大數據問題:

當Redis存儲的數據量只有幾個GB的時候,使用快照來保存數據是沒有問題的。Redis會創建子進程並將數據保存到硬盤裏面。生成快照所用的時間可能比你讀這段話的時間還要短。但隨着Redis佔用的內存越來越多,BGSAVE在創建子進程的

好費時間也會越來越多。這會導致系統停頓,也可能引發系統大量的使用虛擬內存,從而導致redis的性能降低至無法使用的程度。

執行BGSAVE而導致的停頓時間長短取決於redis所在的系統:

真實硬件、VMWare、KVM虛擬機中Redis進程中每佔用1G的內存,創建該進程所需的時間就要增加10-20毫秒;

Xen虛擬機(雲供應商很多用這種虛擬機) 則需要200-400毫秒;也就是說如果有20G數據  那麼快照將使Redis停頓4-6秒!!!

爲了防止redis因爲創建子進程而出現停頓,我們可以考慮關閉自動保存,轉而通過手動發送BGSAVE或者SAVE來進行持久化。手動發送BGSAVE一樣會造成卡頓,但好處是我們能自己決定允許卡頓的時間,比如用戶影響最小的月黑風高的夜晚。

另一方面SAVE會一直阻塞Redis知道快照生成完畢,但是因爲他不用創建子進程,所以不會因爲創建進程而造成的卡頓;並且因爲沒有子進程搶奪資源它創建快照的速度也會更快。

 

#AOF持久化選項

配置參數:

appendonly no                               #是否使用AOF持久化

appendfsync everysec                    #可選參數: always(每個寫操作都要同步到硬盤)   everysec(每秒同步一次)  no(讓操作系統決定應該何時進行同步)

no-appendfsync-on-rewrite no      #對AOF文件壓縮時是否執行寫操作

auto-aof-rewrite-percentage 100  #多久執行一次AOF壓縮

auto-aof-rewrite-min-size 64mb   #新寫入多大內存數據出發一次AOF壓縮

 

dir ./                                                持久化文件存放目錄

AOF 的運作方式是不斷地將命令追加到文件的末尾, 所以隨着寫入命令的不斷增加, AOF 文件的體積也會變得越來越大。

可以通過設置auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 選項來自動執行BGREWRITEAOF。

AOF 文件有序地保存了對數據庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式保存, 因此 AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕鬆。而且這種操作將數據丟失窗口時間可以降低至一秒以內。

AOF面臨的硬盤性能問題:

頻繁的AOF操作能將發生系統崩潰時出現的數據丟失減到最小。但這也意味着對硬盤進行大量的寫入操作,所以redis的處理命令的速度會受到硬盤性能的限制:轉盤式硬盤在這種同步頻率下每秒只能處理200個寫命令,而固態硬盤每秒大概也只能處理幾萬個名利。

固態硬盤能幾萬已經接近10萬的標準了是不是很開心?警告:使用固態硬盤的用戶應謹慎使用appendsync always 選項,因爲這個選項一次只寫一個命令會造成寫入放大,這種不斷寫入會讓你的硬盤壽命從原來的幾年降低爲幾個月。

AOF面臨的文件提及問題:

快照存的是數據而AOF剛纔我們說了它存儲的是一行一行的Redis 協議的格式寫入腳本,隨着redis的不斷運行,AOF文件的體積也會不斷的增長,在極端情況下,aof文件甚至能寫滿硬盤可用空間。還有一個問題就是存儲了這麼多東西是爲了還原redis數據用的,AOF文件體積

這麼大,還原操作的執行時間就可能非常長!

爲了解決AOF體積問題,用戶可以向redis發送 BGREWRITEAOF 命令,這個命令會通過一處AOF文件中的冗餘命令來重寫AOF文件以壓縮體積。BGREWRITEAOF  和 BGSAVE 命令創建快照原理類似:創建子進程,然後重寫。所以他也存在卡頓問題。所以壓縮不宜頻繁。

 

兩種持久化方案講完了,最後提醒一下,備份是爲了容災,所以持久化的服務器最好不要和redis服務器爲同一臺,別把雞蛋全放一個籃子裏...

 

8.主從複製

複製可以讓其他服務器擁有一個不斷地更新的數據副本,從而使得擁有數據副本的服務器可以用於處理客戶端發送的讀請求。關係型數據庫通常會使用一個主服務器向多個從服務器發送更新,並使用從服務器來處理所有讀請求。redis也採用了同樣的方法來實現自己的複製特性,並將其用作一種拓展性能的手段。

可以通過設置額外的redis從服務器來保存數據集的副本。在接收到主服務器發送的數據初始副本之後,客戶端每次向主服務器進行寫入時,從服務器都會實時的得到更新。在部署好從服務器後,客戶端就可以向任意一個從服務器發送讀請求了。

 8.1如何配置從服務器

1.redis.conf 中配置:slaveof host port 即可使其成爲 從服務器

2.正在運行的redis服務可以發送 SLAVEOF NO ONE 即可讓服務器終止複製操作 或發送 SLAVEOF host port 來讓服務器開始複製一個新的主服務器。

 配置一下或者發個命令就成從服務器了嗎?這期間經歷了啥?

從服務器在連接一個主服務器的時候,主服務器會創建一個快照文件並將其發送至從服務器,但這只是中從複製執行過程中的異步,具體操作是這樣的:

 

步驟

主服務器操作

從服務器操作

步驟

主服務器操作

從服務器操作

1 (等待命令進入) 連接(或者重連接)主服務器,發送sync命令
2 開始執行BGSAVE,並使用緩衝區紀錄BGSAVE之後執行的所有寫命令 根據配置選項來決定是否繼續使用現有的數據(如果有的話)來處理客戶端的命令請求,還是向發送請求的客戶端返回錯誤
3 BGSAVE執行完畢,向從服務器發送快照文件,並在發送期間繼續使用緩衝區紀錄被執行的寫命令 丟棄所有的舊數據(如果有的話),開始載入主服務器發來的快照文件
4 快照文件發送完畢,開始向從服務器發送存儲在緩衝區的寫命令 完成對快照文件的解釋操作,像往常一樣開始接受命令請求
5 緩存區存儲的寫命令發送完畢;從現在開始,每執行一個寫命令,就向從服務器發送相同的寫命令 執行主服務器發送來的所有存儲在緩衝區裏面的寫命令;並從現在開始,接受並執行主服務器傳來的每個寫命令

從服務器在進行同步時,會清空自己的所有數據

Redis不支持主主複製。相互設置成主服務器的兩個實例會持續佔用處理器資源嘗試與對方進行通信,根據客戶端連接的服務器不同客戶端可能會取到不一致的數據,或者完全得不到數據。

複製操作的bgsave會影響主服務器的寫性能原因前面說過了,所以實現上我們習慣以樹狀結構來分擔主服務器的複製壓力:

原:

樹狀結構:

 

9.redis事務

MULTI、EXEC、DISCARD和WATCH、UNWATCH命令是Redis事務功能的基礎。Redis事務允許在一次單獨的步驟中執行一組命令,並且可以保證如下兩個重要事項:

Redis會將一個事務中的所有命令序列化,然後按順序執行。Redis不可能在一個Redis事務的執行過程中插入執行另一個客戶端發出的請求。這樣便能保證Redis將這些命令作爲一個單獨的隔離操作執行。 

在一個Redis事務中,Redis要麼執行其中的所有命令,要麼什麼都不執行。因此,Redis事務能夠保證原子性。EXEC命令會觸發執行事務中的所有命令。

 

PS:在事務運行期間,雖然Redis命令可能會執行失敗,但是Redis仍然會執行事務中餘下的其他命令,而不會執行回滾操作。

1.redis足夠快,所以發生需要回滾的概率很低。

2.鍵值數據庫造成錯誤更多的是程序bug,而這種問題一般不會出現在生產上 比如改錯鍵 增錯步長等。

 

 

9.1、相關命令

1. MULTI

用於標記事務塊的開始。Redis會將後續的命令逐個放入隊列中,然後才能使用EXEC命令原子化地執行這個命令序列。

這個命令的運行格式如下所示:

MULTI

這個命令的返回值是一個簡單的字符串,總是OK。

2. EXEC

在一個事務中執行所有先前放入隊列的命令,然後恢復正常的連接狀態。

當使用WATCH命令時,只有當受監控的鍵沒有被修改時,EXEC命令纔會執行事務中的命令,這種方式利用了檢查再設置(CAS)的機制。

這個命令的運行格式如下所示:

EXEC

這個命令的返回值是一個數組,其中的每個元素分別是原子化事務中的每個命令的返回值。 當使用WATCH命令時,如果事務執行中止,那麼EXEC命令就會返回一個Null值。

3. DISCARD

清除所有先前在一個事務中放入隊列的命令,然後恢復正常的連接狀態。

如果使用了WATCH命令,那麼DISCARD命令就會將當前連接監控的所有鍵取消監控。

這個命令的運行格式如下所示:

DISCARD

這個命令的返回值是一個簡單的字符串,總是OK。

4. WATCH

當某個事務需要按條件執行時,就要使用這個命令將給定的鍵設置爲受監控的。

這個命令的運行格式如下所示:

WATCH key [key ...]

這個命令的返回值是一個簡單的字符串,總是OK。

對於每個鍵來說,時間複雜度總是O(1)。

5. UNWATCH

清除所有先前爲一個事務監控的鍵。

如果你調用了EXEC或DISCARD命令,那麼就不需要手動調用UNWATCH命令。

這個命令的運行格式如下所示:

UNWATCH

這個命令的返回值是一個簡單的字符串,總是OK。

時間複雜度總是O(1)。

demo:

 摺疊源碼

expand source?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

redis 127.0.0.1:6379> MULTI

OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"

QUEUED

redis 127.0.0.1:6379> GET book-name

QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"

QUEUED

redis 127.0.0.1:6379> SMEMBERS tag

QUEUED

redis 127.0.0.1:6379> EXEC

1) OK

2) "Mastering C++ in 21 days"

3) (integer) 3

4)

1) "Mastering Series"

2) "C++"

3) "Programming"

 

8.redis環境搭建及參數配置

  8.1單機版搭建步驟


linux版的可以到https://redis.io/或者是http://www.redis.cn/ 下載需要版本的源代碼。

因爲是源代碼且底層是c開發的,所以需要c的編譯環境。

如果make命令能夠使用,則證明已經有了c環境了。沒有c環境則可以使用yum install gcc-c++

wget http://103.78.124.156:83/2Q2WB244B2029332D80C415CBEE56A6C1AE4974EDC31_unknown_CD91975374E1DFF333B4DC4BBF173C7966F8F0F3_1/download.redis.io/releases/redis-5.0.4.tar.gz

進入解壓目錄    make install

cp /usr/local/redisinstall/redis-5.0.4/redis.conf  ./redis.conf

改 bind  bind 0.0.0.0
改 守護線程   daemonize yes
改公網可訪問  protected-mode no

開放防火牆6379端口

起服務
redis-server   redis.conf

遠程測試
telnet ip  6379

ok!

 

8.2 集羣環境搭建:

安裝位置:/usr/local/redis/redis-cluster

1、Linux下redis 安裝:
redis 官網鏈接:https://redis.io
1.1.首先進入自己的文件目錄,下載一個安裝包,解壓縮,進入redis解壓目錄,執行make指令

  1. wget http://download.redis.io/releases/redis-4.0.2.tar.gz
  2. tar xzf redis-4.0.2.tar.gz
  3. cd redis-4.0.2
  4. make


1.2. 編譯完成後,cd到src 目錄下,安裝
cd src
make install

 

如果make命令能夠使用,則證明已經有了c環境了。沒有c環境則可以使用yum install gcc-c++

2、組建集羣:
2.1.拷貝六份項目 至 /usr/local/redis/redis-cluster  分別命名 redis01 redis02
redis03 redis04 redis05   redis06

拷貝腳本:
cp -r redis-4.0.2 ./redis01
cp -r redis-4.0.2 ./redis02
cp -r redis-4.0.2 ./redis03
cp -r redis-4.0.2 ./redis04
cp -r redis-4.0.2 ./redis05
cp -r redis-4.0.2 ./redis06
誤創建刪除腳本:
rm -rf redis06
2.2./usr/local/redis/redis-cluster下創建conf文件夾  用於存放六個服務器配置文件;
創建腳本:
mkdir conf
cd /usr/local/redis/redis-cluster/conf
cp ../redis-4.0.2/redis.conf  redis01.conf
cp ../redis-4.0.2/redis.conf  redis02.conf
cp ../redis-4.0.2/redis.conf  redis03.conf
cp ../redis-4.0.2/redis.conf  redis04.conf
cp ../redis-4.0.2/redis.conf  redis05.conf
cp ../redis-4.0.2/redis.conf  redis06.conf

修改每個conf配置文件:
修改端口號  分別爲7001 7002 7003 7004 7005 7006
改 bind  bind 0.0.0.0
改 守護線程   daemonize yes
改公網可訪問  protected-mode no
允許集羣:cluster-enable yes

2.3防火牆放行:
vi /etc/sysconfig/iptables
加入如下腳本:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7001 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7002 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7003 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7004 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7005 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7006 -j ACCEPT

ps:如果跨服務器需要開通開啓集羣總線端口:  所有端口+10000
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17001 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17002 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17003 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17004 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17005 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 17006 -j ACCEPT
然後重啓一下防火牆
service iptables restart

2.4編寫啓停腳本:
批量啓動:
startall.sh

##!/bin/bash
clusterpath="/usr/local/redis/redis-cluster/"
cd $clusterpath
redis_arr=(01 02 03 04 05 06)
for num in ${redis_arr[@]}
do
    echo "start ${num}nth redis server..."
    cd redis${num}/
    redis-server ../conf/redis${num}.conf
    cd ..

done

批量終止:
stopall.sh

#!/bin/bash
pid_name="redis"
echo "殺死的進程名稱:" $pid_name

pid=$(ps -ef|grep $pid_name|grep -v grep|awk '{print $2}')

echo "pid列表:" $pid

for item in $pid
do
echo  "殺死進程pid=" $item
kill -9  $item
done

showall.sh

ps aux | grep redis

給他們賦權可執行: 
賦權腳本:
chmod +x startall.sh
chmod +x stopall.sh
chmod +x showall.sh

啓動所有服務:
./startall.sh
檢查是否成功:

./showall.sh

 

2.5安裝ruby 環境
yum install ruby

裝好以後測試一下
ruby -v
ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-linux]
ok 已經變成1.8.7 了

2.6安裝rubygems
yum install rubygems
gem 查看是否安裝成功

2.7安裝redis集羣需要的包
gem install redis -v 3.3.3  
2.8.創建集羣
ruby redis01/src/redis-trib.rb create --replicas 1 192.168.189.131:7001 192.168.189.131:7002 192.168.189.131:7003 192.168.189.131:7004 192.168.189.131:7005  192.168.189.131:7006

輸入yes

2.9測試連接: telnet 192.168.189.131 7002

已連入集羣的服務器如果想重新搭建集羣:
1.清空所有實例數據
2.刪除實例跟目錄下node.conf文件 
重新執行2.8即可

 

 

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