redis梳理

remote dictionary server遠程字典服務器

C語言開發的
TCP協議讀寫
數據都存儲在內存中,可達到10萬個鍵值讀寫每秒。
支持持久化。
還能夠限定數據佔用的最大內存空間,數據量達到空間限制後會按必定的規則自動淘汰不須要的鍵。
除了緩存,還能夠利用列表類型鍵實現隊列,並支持阻塞讀取。還有「發佈/訂閱」的消息模式,作分佈式鎖。
https://gist.github.com/348262 這是一個用redis實現的聊天室 git

單線程,對手Memcached支持多線程,但redis性能已經足夠優異。
redis的優點是支持字符串之外的其餘數據類型,還支持持久化。github

redis快的緣由

純內存操做
單線程操做,避免了頻繁的上下文切換
採用了非阻塞I/O多路複用機制
redis線程模型:
redis線程模型
redis-client在操做的時候,會產生具備不一樣事件類型的socket。在服務端,有一段I/0多路複用程序,將其置入隊列之中。而後,文件事件分派器,依次去隊列中取,轉發到不一樣的事件處理器中。redis

服務環境

輕量級,一個空redis實例內存只有1MB左右。 算法

第一個小數點後的數字是偶數的版本是穩定版
redis-benchmark 是redis性能測試工具
redis-check-aof 是AOF文件修復工具
redis-check-dump 是RDB文件檢查工具 數據庫

生產環境推薦使用腳本啓動redis,使得redis能隨系統自動運行。
將redis源代碼目錄utils裏的redis_init_script腳本,拷貝到/etc/init.d目錄中,重命名文件爲redis_6379。
新建/etc/redis目錄存放配置文件(6379.conf),新建/var/redis/6379文件夾存放redis持久化文件。 json

shutdown中止服務時,redis收到SHUTDOWN命令後會先斷開全部客戶端鏈接,而後根據配置執行持久化,最後完成退出。
使用kill也能夠正常中止redis服務。緩存

數據庫

0-15一個16個庫,默認使用第0號庫。
redis不支持自定義數據庫名,也不支持爲每一個庫設置不一樣的密碼。
數據庫之間也不是徹底隔離,FLUSHALL命令能夠清空一個redis實例中全部庫的數據。
因此這些數據庫更像是一種命名空間,不適合存儲不一樣應用程序的數據,能夠存儲不一樣環境如測試、生產環境的數據。服務器

鍵值支持的數據類型:

String
value能夠是String也能夠是數字。通常作一些複雜的計數功能的緩存,還能夠存儲json化的對象,甚至是圖片(二進制數據),最大容量是512MB(看具體版本)。
hash
注意不能嵌套其餘的數據類型(其餘的也是),字段值只能是字符串。
通常存放的是結構化的對象,使用 對象類型:對象id構成鍵名,使用字段表示對象屬性,字段值存放屬性值。比較方便的操做其中的某個字段。否則使用多個string類型存儲一個對象的不一樣屬性會很差管理。
也能夠存映射關係,如搭建博客網站時用散列類型存儲文章縮略名slug和id之間的映射關係。
在作單點登陸的時候,用這種數據結構存儲用戶信息,以cookieId做爲key,設置30分鐘爲緩存過時時間,能很好的模擬出相似session的效果。
list
列表類型能夠存儲一個有序(指的是插入順序)的字符串列表。
內部是雙向鏈表。獲取頭部或尾部的topn會比較快。插入數據的速度也不會受已有數據數量的影響。
能夠作簡單的消息隊列的功能。不一樣方向插入、彈出便可。
另外能夠用列表類型存儲id列表,利用分片獲取命令,作基於redis的分頁功能。
set
由於set堆放的是一堆不重複值的集合。內部是使用值爲空的散列表實現的。最方便的是能夠進行交集、並集、差集等運算。
能夠存儲標籤。能夠利用集合類型優點的場景。
sorted set
sorted set是使用散列表和跳躍表實現的。與普通集合相比,多了一個權重參數score,集合中的元素可以按score進行排列。能夠作排行榜應用,取TOP N操做。

redis-cli操做

大小寫不敏感
$ redis-cli PING 若是鏈接正常會受到PONG的回覆,用來測試客戶端與redis的鏈接是否正常(也能夠直接> PING)。
$ redis-cli -h 127.0.0.1 -p 6379 進入交互模式
> flushdb 清空當前數據庫。
> flushall 清空全部數據庫。
> select [index]選擇索引數據庫,index爲索引值名,如:select 1
> quit 退出客戶端鏈接。cookie

鍵值獲取

查看當前庫有哪些鍵KEYS (pattern)session

clipboard.png
支持*?[]\x(表示匹配字符x,如匹配問好,就 KEYS \?)
須要遍歷全部鍵,當數據量多時,不建議使用。

EXISTS (鍵名)判斷一個鍵是否存在,存在則返回1,不然0。
DEL (鍵名,多個鍵空格隔開)刪除鍵,返回值是刪除的個數。
能夠經過管道實現通配刪除:redis-cli KEYS "user:*" | xargs redis-cli DEL刪除全部以"user:"開頭的鍵。或者redis-cli DEL 'redis-cli KEYS "user:*"'

TYPE (鍵名)得到鍵值的數據類型。

STRLEN (鍵名)得到鍵值的長度(中文的話,計算的是utf-8編碼後的長度)。不存在,返回0。

鍵值設置

========string類型值
SET (鍵名) (值) 賦字符串類型值。項目中鍵的命名有個建議是對象類型:對象id:對象屬性
GET (鍵名) 當鍵不存在時會返回空。

MSET (鍵名) (值) 能夠設置多個鍵值。
MGET (鍵名) 當鍵不存在時會返回空。
clipboard.png

雖然沒有整數類型,但也提供了用於整數操做的命令,如INCR
clipboard.png
經常使用於統計文章訪問量等。

INCRBY (鍵名) (步長)遞增非1的狀況使用。若是要遞增浮點數,使用INCRBYFLOAT
一樣,INCR均可以換爲DECR實現遞減。

APPEND (鍵名) (帶雙引號的字符串)實現向鍵值末尾追加。若鍵不存在,則至關於在null裏追加。

========hash類型值

HSET 鍵名 字段名 字段值 用來給hash類型數據賦值即插入(返回1),也多是更新(返回0)。
HSETNX 鍵名 字段名 字段值與上面的區別是若是字段已經存在,不會執行返回0。
HGET 鍵名 字段名
HMSET 鍵名 (字段名1 字段值1) (字段名2 字段值2) (字段名3 字段值3)...
HMGET 鍵名 (字段名1) (字段名2) (字段名3) 同時獲取多個字段值
HGETALL 鍵名 獲取全部鍵值
HEXISTS 鍵名 字段名判斷一個字段是否存在,存在則返回1,不然(以及鍵不存在時)返回0。

HINCRBY 鍵名 字段名 步長使指定字段的字段值增長指定的整數。不存在的鍵會自動被創建。

HDEL 鍵名 字段名1 2 3能夠刪除一個或多個字段,返回刪除字段的個數。

HKEYS 鍵名HVALS 鍵名 分別獲取該鍵的全部字段名和全部字段值。
HLEN 鍵名 得到該鍵名的字段數。

========list類型值
LPUSH 鍵名 值1 值2... 從左側插入數據,RPUSH表示從右側插入。返回該鍵的元素數量。
LPOP 鍵名 從列表左側彈出一個元素。RPOP表示從右側彈出。
LLEN 鍵名 返回列表中元素的個數。不存在返回0。
LRANGE 鍵名 起始索引 結尾索引 從左往右,獲取列表分片,起始從0開始,並且包含兩端的元素。索引爲負值,如-1表示右邊的第一個元素。
LRANGE 鍵名 0 -1能夠獲取列表中全部元素,另外若」起始索引「位置比」結尾索引「位置靠後,會返回空列表;」結尾索引「大於實際索引範圍則會返回到列表最右邊的元素爲止。
LTRIM 鍵名 起始索引 結尾索引刪除指定索引範圍外的全部元素。

LREM 鍵名 個數 值 當」個數「>0時,會刪除從左邊數前"個數"個值爲"值"的元素; 當」個數「=0時,會刪除全部值爲"值"的元素;當」個數「<0時,會刪除從右邊數前"個數"的絕對值個值爲"值"的元素。返回實際刪除的元素個數。

LINDEX 鍵名 索引 獲取指定索引(從0開始,負數表示從右邊開始計算最右是-1)的元素值。
LSET 鍵名 索引 值 設置指定索引的元素值。
LINSERT 鍵名 BEFORE|AFTER pivot value 從左到右找到值爲pivot的元素,而後根據第二個參數BEFORE|AFTER將value插入到該值的前或後面。返回最後列表的元素的個數。

RPOPLPUSH source destination 從源列表RPOP一個元素,而後LPUSH到目標列表。返回這個元素的值。至關於一個隊列操做。源和目標列表能夠是同一個列表。

========set類型值
SADD 鍵名 元素1 元素2...增添一個或多個元素,鍵不存在自動建立。返回成功加入元素的個數。
SREM 鍵名 元素1 元素2...刪除一個或多個元素,返回刪除成功的個數。
SPOP 鍵名 從集合中隨機彈出一個元素。

SMEMBERS 鍵名返回集合中全部元素。
SRANDMEMBER 鍵名隨機從集合中獲取一個元素。後面也能夠加數字表示返回該數字個元素,分正、負、以及大於集合數的狀況。
ps:這種「隨機」對每個元素並非平等的。首先是隨機選一個桶,而後在桶裏隨機選元素。沒有哈希衝突的元素被選中的概率要大於有哈希衝突的。

SCARD 鍵名 獲取集合中元素個數。
SISMEMBER 鍵名 元素 判斷元素是否在集合中。存在返回1,不存在或鍵不存在時返回0。

SDIFF 鍵1 鍵2 鍵3...多集合的差集運算。使用SDIFFSTORE 鍵0 鍵1 鍵2 ...將結果集存儲在鍵0中。
SINTER 鍵1 鍵2 鍵3...多集合的交集運算。SINTERSTORE、SUNIONSTORE相似。
SUNION 鍵1 鍵2 鍵3...多集合的並集運算。

========sorted set類型值
ZADD 鍵名 score1 元素1 score2 元素2 ...增長元素,返回新增元素個數(不包括重複覆蓋的)。
ZSCORE 鍵名 元素 獲取元素的score。
ZRANGE 鍵名 start stop 返回按score從小到大排序後在指定索引區間裏(包含兩端) 的元素。加上WITHSCORES也會返回元素的score。另外從大到小,使用ZREVRANGE

ZRANGEBYSCORE 鍵名 minScore maxScore 返回指定score範圍裏的元素。也可帶WITHSCORES,以及LIMIT offset count,還能夠指定不包含端點值,還可使用-inf、+inf表示負無窮、正無窮。一樣也有ZREVRANGEBYSCORE,先maxScore再minScore。

ZINCRBY 鍵名 increment 元素 增長某個元素的score,返回最後該元素的分數。元素不存在時,會初始化爲0再加。

ZCARD、ZCOUNT、ZREM、ZREMRANGEBYRANK、ZREMRANGEBYSCORE、ZRANK以及一些集合運算命令

排序

redis提供了對列表、集合、有序集合(忽略score)類型鍵的排序命令SORT
能夠對數字排序,還有指定ALPHA參數實現字典排序。
DESC實現倒序。
LIMIT offset count實現返回值的指定範圍(跳過前offset個元素,獲取count個元素)。

BY參數後面加參考鍵(字符串類型或hash類型鍵的某個字段鍵名->字段名),命令將對「每一個元素的值替換參考鍵中第一個(能夠是鍵名帶,能夠是字段名帶*)並獲取其值後的值」排序。
若獲得的值相同,則會再比較元素自己的值再排序。
當參考鍵不帶*時(常量鍵名,與元素值無關),或改參考鍵不存在時,命令不會執行排序操做。

配置

CONFIG SET ...命令能夠在不重啓服務的狀況下動態修改redis配置,如日誌級別loglevel,是否開啓持久化等,但也不支持全部的配置項。
CONFIG GET ...命令查看當前配置狀況。

事務

redis先將屬於一個事務的命令發送給服務器,而後再依次執行這些命令。
MULTI命令告知服務器接下來的命令都屬於同一個事物,後面的命令都會被加入等待執行的事務隊列中。EXEC命令告知服務器將執行事務隊列中的全部命令,並保證不會被其餘命令插入,當事務裏全部命令都執行完後,返回每一個命令的返回值。

可是1

redis事務沒有回滾功能。若出現執行出錯的狀況只有本身手動恢復數據。

可是2

若出現某條命令須要先獲取上一條命令返回值才能繼續執行的狀況時,因爲redis事務中每一個命令的返回值都是最後一塊兒返回的,這種狀況不能「將上一條命令」與該命令都加入到事務中,而是獲取「上一條命令」返回值後再使用事務,並採用相似「鎖」的監控機制,在執行事務前防止獲取的返回值被改變形成髒讀。
WATCH命令能夠監控一個或多個鍵,一旦其中有一個被改動,以後的事務便不會執行。監控一直持續到EXEC命令。 也能夠用UNWATCH取消監控
若exec執行失敗,再從新執行整個函數。

生存時間

EXPIRE設置鍵的生存時間(Time To Live,TTL),單位秒,必須是整數。PEXPIRE單位是毫秒。
TTL獲取該鍵還有多久時間被刪除,返回-1表示該鍵已不存在,或沒有爲該鍵設置生存時間。PTTL以毫秒爲單位返回剩餘時間。
PERSIST取消生存時間設置。使用SET、GETSET命令爲鍵賦值時也會清除生存時間設置。其餘如HSET、ZREM、LPUSH只對鍵值操做的命令不影響鍵的生存時間。

WATCH監控一個設置了生存時間的鍵,該鍵到期天然死亡後,WATCH並不會被認爲該鍵被改變。

問題1

到期後的鍵都會自動被刪除嗎?
不必定,redis採用的是 按期刪除+惰性刪除策略。    
按期刪除:redis默認每隔100ms檢查是否有過時的key,有過時key則刪除。但redis不是每一個100ms將全部的key檢查一次,而是 隨機抽取進行檢查(若是每隔100ms,所有key進行檢查,redis可能會卡死),所以,若是隻採用按期刪除策略,會致使不少key到時間沒有刪除。還須要 惰性刪除機制,即在你獲取某個key的時候,redis同時也會檢查一下,這個key若是設置了過時時間那麼是否過時了?若是過時了此時就會刪除該鍵。 

問題2

每一個鍵設置多長時間的生存時間?
設置得太長,在內存有限的狀況下可能會致使內存佔滿。
設置過短,可能致使緩存命中率低致使大量內存閒置。
實際開發過程當中會比較難爲緩存設置合理的生存時間,通常是經過限制redis最大內存使用量,並讓redis按照必定的規則淘汰不須要的緩存鍵,這樣來利用redis緩存系統。

配置文件redis.conf中maxmemory參數來限制redis最大可用內存(單位字節)。
maxmemory-policy指定超出內存後的刪除規則,直到redis佔用內存小於限制內存。有如下幾種刪除策略:

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
# 
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations

1)volatile-lru:即便用LRU算法刪除鍵。當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,移除最近最少使用的key。這種狀況通常是把redis既當緩存,又作持久化存儲的時候才用。不推薦。
2)allkeys-lru:也是使用LRU算法刪除鍵。當內存不足以容納新寫入數據時,在鍵空間中,直接移除最近最少使用的key。推薦使用。
3)volatile-random:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,隨機移除某個key。依然不推薦。4)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。應該也沒人用吧,你不刪最少使用Key,去隨機刪。5)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,有更早過時時間的key優先移除。不推薦。6)noeviction:當內存不足以容納新寫入數據時,新寫入操做會報錯。(默認的)ps:若是沒有設置 expire 的key, 不知足先決條件(prerequisites); 那麼 volatile-lru, volatile-random 和 volatile-ttl 策略的行爲, 和 noeviction(不刪除) 基本上一致。

相關文章
相關標籤/搜索