Redis簡介redis
Redis是REmote DIctionary Server(遠程字典服務器)縮寫。數據庫
以字典結構存儲數據,並容許其餘應用經過TCP協議讀寫字典中的內容。緩存
支持的鍵值數據類型有:字符串類型string、散列類型hash、列表類型list、集合類型set、有序集合類型zset。ruby
內存存儲與持久化服務器
Redis能夠爲每一個健設置生存時間(Time To Live,TTL),生存時間到期後會被自動刪除。能夠做爲緩存系統使用。網絡
在性能上Redis是單線程模式,而Memcached支持多線程,因此在多核服務器上後者性能更高一些。數據結構
Redis是使用C語言開發的。多線程
Redis多數據庫ide
一個Redis實例提供了多個用來存儲數據的字典,客戶端能夠指定將數據存儲在哪一個字典中。函數
每一個字典相似於一個獨立的數據庫。每一個字典對外以一個從0開始的遞增數字命名,默認支持16個,不支持自定義數據庫名字。
通常不一樣應用的數據應該使用不一樣的Redis實例存儲。
Redis不區分命令大小寫
Redis提供的全部命令都是原子操做(atomic operation)。
Redis對於鍵的命名並無強制要求,較好的實踐用「對象類型:對象ID:對象屬性」來命名一個鍵,如使用鍵 user:1:friends來存儲ID爲1的用戶的好友列表。
Redis各個數據類型都不支持數據類型的嵌套。
—————————————————————————————————————
Redis安裝
Redis約定版本號(即第一個小數點後的數字)爲偶數的版本是穩定版(如2.四、2.6),奇數版本是非穩定版(如2.五、2.7)。
下載安裝:
wget http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
Redis沒有其餘外部依賴。
Redis運行
啓動Redis:1.直接啓動(命令:redis-server);2.經過初始化腳本啓動;
中止Redis:redis-cli SHUTDOWN (kill命令效果與發送SHUTDOWN命令同樣)
Redis命令行客戶端
redis-cli (Redis Command Line Interface)是Redis自帶的基於命令行的Redis客戶端。
Redis配置
Redis提供了一個配置模板 redis.conf,位於源代碼目錄的根目錄下。
—————————————————————————————————————
Redis的數據結構
字符串類型
簡介:能夠存儲任何形式的字符串,一個字符串類型鍵容許存儲的數據的最大容量是512MB。
命令:SET key value / GET key
散列類型
簡介:散列類型適合存儲對象,使用對象類別和ID構成鍵名,使用字段表示對象的屬性,而字段值則存儲屬性值。
命令:HSET key field value / HGET key field ( HMSET key field value [fielld value ...] / HMGET key field [field ...])
列表類型
簡介:列表類型能夠存儲一個有序的字符串列表,經常使用的操做是向列表的兩端添加元素,或者得到列表的某一個片斷。列表類型內部是使用雙向鏈表實現的,向兩端添加刪除元素較快,但經過索引訪問元素較慢。
命令:LPUSH key value [value ...] / RPUSH key value [value ...] / LPOP key / RPOP key / LRANGE key start stop
集合類型
簡介:集合中每一個元素都是不一樣的,且沒有順序。經常使用操做是向集合中加入或刪除元素、判斷某個元素是否存在等,集合類型在Redis內部是使用值爲空的散列表實現的,因此這些操做較快。集合類型鍵之間還能夠進行並集、交集和差集運算。
命令:SADD key member [member ...] / SREM key member [member ...] / SDIFF key [key ...] / SINTER key [key ...] / SUNION key [key ...]
有序集合類型
簡介:在集合類型的基礎上有序集合類型爲集合中的每個元素都關聯了一個分數,按照這個分數對每一個元素進行排序。咱們進行得到分數最高(或最低)的前N個元素、得到指定分數範圍內的元素等於分數有關的操做。雖然集合中每一個元素都是不一樣的,可是他們的分數卻能夠相同。有序集合能夠調整某個元素的爲止,經過更改該元素的分數。
命令:ZADD key score member [score member ...] / ZSCORE key member / ZRANGE key start stop [WITHSCORES] / ZREVRANGE key start stop [WITHSCORES]
—————————————————————————————————————
Redis的事務:
Redis中的事務(transaction)是一組命令的集合。事務同命令同樣都是Redis的最小執行單元,一個事務中的命令要麼都執行,要麼都不執行。
事務的原理是先將屬於一個事務的命令發送給Redis,而後再讓Redis依次執行這些命令。
事務示例:
redis> MULTI
OK
redis> SADD "user:1:following" 2
QUEUED
redis> SADD "user:2:followers" 1
QUEUED
redis> EXEC
1) (integer) 1
2) (integer) 1
上面的代碼演示了事務使用方式。
首先MULTI命令告訴Redis,下面的命令屬於一個事務,先緩存不執行;
Redis回答OK;
發送兩個SADD命令,Redis沒有執行命令,而是放入等待隊列QUEUED;
要執行的命令發送完畢後,發送EXEC命令告訴Redis能夠執行了;
Redis將等待執行的命令按照發送順序執行,並依次返回執行結果。
故障處理:
若是在發送EXEC命令前客戶端斷線,則Redis會清空事務隊列,全部命令都不執行;但若是已經發送了EXEC命令後客戶端斷線,則Redis會執行全部命令的。
Redis的事務還能保證一個事務內的命令依次執行而不被其餘命令插入。
若是一個事務中的某個命令執行出錯,Redis會如何處理?
當在命令執行前出現錯誤,如語法錯誤,Redis會直接返回錯誤,全部命令都不執行;
當在命令執行中出現錯誤,如執行某個命令時運行時錯誤,因爲執行前沒法發現,Redis會接收並執行,全部命令都會執行。
Redis的事務沒有關係數據庫事務提供的回滾(rollback)功能。
WATCH命令
咱們已經知道在一個事務中只有當全部命令都依次執行完後才能獲得每一個結果的返回值,但是有些狀況下須要先得到一條命令的返回值,而後再根據這個值執行下一個命令。
上面的狀況在使用事務來實現時會產生競態條件。事務家族的另外一個成員WATCH,該命令能夠監控一個或多個鍵,一旦其中一個鍵被修改(或刪除),以後的事務就不會執行了。監控一直持續到EXEC命令(事務中的命令是在EXEC以後才執行的,因此MULTI命令後能夠修改WATCH監控的鍵值)。
因爲WATCH命令的做用只是當被監控的鍵值被修改後阻止以後一個事務的執行,而不能保證其餘客戶端不修改這一鍵值,因此咱們須要在EXEC執行失敗後從新執行整個函數。
生存時間
有時效的數據,好比限時優惠活動、緩存或驗證碼等,過了必定的時間就須要刪除這些數據。
Redis可使用EXPIRE命令設置一個鍵的生存時間,到時候後Redis會自動刪除它。默認不設置時間的爲永久存在。
命令:EXPIRE key seconds //上述命令標識key鍵在seconds秒後會被刪除,
實現訪問頻率的限制:例如要限制每一個用戶每分鐘最多能訪問100次。
思路:每一個用戶存儲「rate.limiting:用戶ip」字符串類型鍵,用戶每次訪問則遞增,第一次訪問時要設置該鍵的生存時間爲1分鐘。每次用戶訪問都讀取鍵值,判斷超過100則限制。該鍵每分鐘會自動刪除,用戶下一分鐘能夠從新計算限制值。
實現緩存:爲了提升網站的負載能力,經常須要將一些訪問頻率較高可是對CPU或IO資源消耗較大的操做的結果緩存起來,並但願讓這些緩存過一段時間自動過時。
能夠經過給鍵設置生存時間的方式來實現。每次訪問先查詢緩存,有則返回緩存值,沒有則從新計算並放緩存並同時設置緩存生存時間。
可是服務器的內存是有限的,Redis能使用的內存也是有限的。緩存鍵的生存時間設置的過長會致使Redis佔滿內存,設置太短會致使緩存命中率太低。實際開發中會發現很難爲緩存鍵設置合理的生存時間,爲此能夠限制Redis可以使用的最大內存,並讓Redis按照必定的規則淘汰不須要的緩存鍵,這種方式在只將Redis用做緩存系統時很是實用。
—————————————————————————————————————
Redis的排序
SORT命令:
SORT命令能夠對列表類型、集合類型和有序集合類型鍵進行排序,而且能夠完成與關係數據庫中的鏈接查詢相相似的任務。
除了能夠排列數字外,SORT命令還能夠經過ALPHA參數實現按照字典順序排列非數字元素。
SORT命令默認是按照從小到大的順序排列,若是想從大到小的順序排列,須要使用DESC參數。
SORT命令實現分頁:經過支持LIMIT參數來返回指定範圍的結果。用法和SQL語句同樣,LIMIT offset count,表示跳過前offset個元素並獲取以後的count個元素。
BY參數:
通常存儲數據時都以對象的ID爲標識,但更多的時候咱們但願根據ID對應的對象的某個屬性進行排序。
BY參數的語法爲「BY參考鍵」。參考鍵能夠是字符串類型的鍵或者是散列類型鍵的某個字段(表示爲鍵名->字段名)。
若是提供了BY參數,SORT命令將再也不依據元素自身的值進行排序,而是對每一個元素使用元素的值替換參考鍵中的第一個「*」並獲取其值,而後依據該值對元素排序。
例如:SORT tag:ruby:posts BY post:*->time DESC
GET參數:
GET參數不影響排序,它的做用是使SORT命令的返回結果再也不是元素自身的值,而是GET參數中指定的鍵值。
例如:SORT tag:ruby:posts BY post:*->time DESC GET post:*->title
STORE參數:
SORT命令會直接返回排序結果,若是但願保持排序結果,可使用STORE參數。STORE參數經常使用來結合EXPIRE命令緩存排序結果。示例僞代碼:
#判斷是否存在以前排序結果的緩存
$isCacheExists = EXISTS cache.sort
if $isCacheExists is 1
#若是存在則直接返回
return LRANGE cache.sort, 0, -1
else
#若是不存在,則使用SORT命令排序並將結果存入cache.sort鍵中做爲緩存
$sortResult = SORT some.list STORE cache.sort
#設置緩存的生存時間爲10分鐘
EXPIRE cache.sort, 600
#返回排序結果
return $sortResult
—————————————————————————————————————
消息通知
任務隊列:即傳遞任務的隊列,能夠藉助任務隊列實現通知的過程。
任務隊列的好處:鬆耦合,生產者和消費者無需知道彼此的實現細節;易於擴展消費者,能夠有多個並能夠分佈在不一樣的服務器中。
Redis實現任務隊列:使用Redis的列表類型,以及其LPUSH和RPOP命令實現隊列的概念。BRPOP和BLPOP還實現了沒有元素則阻塞機制。
優先級隊列:優先消費緊急的消息。
可經過使用BRPOP命令實現,BRPOP能夠同時接收多個鍵,格式如:BRPOP key [key ...]
意義是同時檢測多個鍵,若是全部鍵都沒有元素則阻塞,若是其中有一個鍵有元素則會從該鍵中彈出元素。若是多個鍵都有元素則按照從左到右的順序取第一個鍵中的一個元素。
如此一來將須要優先處理的消息的鍵放消費順序的前面,這樣無論後面有沒有元素,擠壓了多少,只要前面的有元素則會優先處理。
發佈/訂閱模式:分兩種角色,分別是發佈者和訂閱者。訂閱者能夠訂閱一個或若干個頻道(channel),而發佈者能夠向指定的頻道發送消息,全部訂閱此頻道的訂閱者都會收到此消息。
命令:PUBLISH channel message / SUBSCRIBE channel [channel ...]
按照規則訂閱:使用PSUBSCRIBE命令訂閱指定的規則。規則支持glob風格通配符格式。如:PSUBSCRIBE channel.?*
—————————————————————————————————————
Redis的管道
客戶端和Redis使用TCP協議鏈接。不管是客戶端向Redis發送命令仍是Redis向客戶端返回命令的執行結果,都須要通過網絡傳輸,這兩部分的總耗時稱爲往返時延。在執行多個命令時每條命令都須要等待上一條命令執行完才能執行,即便命令不須要上一條命令的執行結果。
Redis的底層通訊協議對管道(pipelining)提供了支持。經過管道能夠一次性發送多條命令並在執行完後一次性將結果返回,當一組命令中每條命令都不依賴於以前命令的執行結果時就能夠將這組命令一塊兒經過管道發出。管道經過減小客戶端與Redis的通訊次數來實現下降往返時延累計值得目的。
—————————————————————————————————————
優化Redis的存儲空間
Redis是一個基於內存的數據庫,全部的數據都存儲在內存中,因此優化存儲、減小內存空間佔用對成本控制來講很是重要。
1.精簡鍵名和鍵值;
2.內部編碼優化:Redis爲每種數據類型提供了兩種內部編碼方式,而且Redis會根據實際狀況自動調整。
數據類型 內部編碼方式 OBJECT ENCODING命令結果
字符串類型 REDIS_ENCODING_RAW raw
REDIS_ENCODING_INT int
散列類型 REDIS_ENCODING_HT hashtable
REDIS_ENCODING_ZIPLIST ziplist
列表類型 REDIS_ENCODING_LINKEDLIST linkedlist
REDIS_ENCODING_ZIPLIST ziplist
集合類型 REDIS_ENCODING_HT hashtable
REDIS_ENCODING_INTSET intset
有序集合類型 REDIS_ENCODING_SKIPLIST skiplist
REDIS_ENCODING_ZIPLIST ziplist
共享對象:Redis啓動後會預先創建10000個分別存儲從0到9999這些數字的redisObject類型變量做爲共享對象,若是要設置的字符串鍵值在這10000個數字內(如 SET key1 123)則能夠直接引用共享對象而不用再創建redisObject了。因而可知,使用字符串類型鍵存儲對象ID這樣小數字是很是節省存儲空間的,Redis只需存儲鍵名和一個對共享對象的引用便可。
REDIS_ENCODING_ZIPLIST編碼類型是一種緊湊的編碼格式,它犧牲了部分讀取性能以換取極高的空間利用率,適合在元素較少時使用。
—————————————————————————————————————
腳本
Redis在2.6版推出了腳本功能,容許開發者使用Lua語音編寫腳本傳到Redis中執行,腳本中能夠調用大部分的Redis命令。使用腳本的好處以下:
1.減小網絡開銷;多個命令能夠放到腳本中發送一個請求便可,減小網絡往返時延。
2.原子操做;整個腳本將做爲一個總體執行,中間不會被其餘命令插入。
3.複用;腳本會永久存儲在Redis中,其餘客戶端也能夠複用。
Lua是一個高效的輕量級腳本語言。Lua在葡萄牙語種是「月亮」的意思,它的徽標形似衛星,寓意着Lua是一個「衛星語音」,可以方便的嵌入到其餘語言中使用。
—————————————————————————————————————
持久化:經過持久化功能,Redis保證了即便在服務器重啓的狀況下也不會損失(或少許損失)數據。
RDB方式;
AOF方式(Append Only File);
—————————————————————————————————————
複製:
若是數據存儲在一臺服務器上,當硬盤出現故障時,也會致使數據丟失。
爲了不單點故障,Redis提供了複製功能能夠自動實現同步的功能,將數據庫複製多個副本以部署在不一樣的服務器上。
經過複製能夠實現讀寫分離以提升服務器的負載能力。
Redis數據庫分兩類:主數據庫、從數據庫;
主數據庫能夠進行讀寫操做,當發生寫操做時自動將數據同步給從數據庫;
從數據庫通常是隻讀的,並接收主數據庫同步過來的數據。
在Redis中使用複製功能很是簡單,只需在從數據庫的配置文件中加入「slaveof 主數據庫IP 主數據庫端口」便可,主數據庫無需進行任何配置。
除了使用配置文件設置slaveof參數,還能夠在運行時使用SLAVEOF命令修改。
Redis的複製原理:
當一個從數據庫啓動後,會向主數據庫發送SYNC命令,主數據庫接收到SYNC命令後會開始在後臺保存快照(即RDB持久化的過程),並將保存期間接收到的命令緩存起來。當快照完成後,Redis會將快照文件和全部緩存的命令發送給從數據庫。從數據庫收到後,會載入快照文件並執行收到的緩存的命令。當主從數據庫斷開重連後會從新執行上述操做,不支持斷點續傳。
從數據庫不只能夠接收主數據庫的同步數據,本身也能夠同時做爲主數據庫存在。
例如:A有B和C兩個從,B有D和E兩個從;當向B寫數據時只能同步到D和E,不能同步到A或C。
持久化操做很是耗時,爲了提升性能,能夠經過複製功能創建一個(或若干個)從數據庫,並在從數據庫中啓用持久化,同時在主數據庫禁用持久化。
當從數據庫崩潰時重啓後主數據庫會自動將數據同步過來,因此無需擔憂數據丟失。
當主數據庫崩潰時,須要在從數據庫中使用SLAVEOF NO ONE命令將從數據庫提高成主數據庫繼續服務,並在原來的主數據庫啓動後使用SLAVEOF命令將其設置成新的主數據庫的從數據庫,便可將數據同步回來。
—————————————————————————————————————
耗時命令日誌:
當一條命令執行時間超過限制時,Redis會將該命令的執行時間等信息加入耗時命令日誌(slow log)以供開發查看。
能夠經過配置文件的slowlog-log-slower-than參數設置這一限制,單位是微妙(1000000微秒=1秒),默認值是10000。
耗時命令日誌存儲在內存中,能夠經過配置文件的slowlog-max-len參數來限制記錄的條數。