數據類型 | 能夠存儲的值 | 操做 |
---|---|---|
String | 字符串、整數或浮點型 | 對整個字符串或者字符串的 對整數和浮點數執行自增或自減操做 |
List | 列表 | 從兩端壓入或者彈出元素 對單個或者多個元素進行修剪、只保留一個範圍內的元素 |
Set | 無序集合 | 添加、獲取、移除單個元素 檢查一個元素是否存在於集合中 計算交集、並集、差集 從集合裏面隨機獲取元素 |
HASH | 包含鍵值對的無序散列表 | 添加、獲取、移除單個鍵值對 獲取全部鍵值對 檢查某個鍵是否存在 |
ZSET | 有序集合 | 添加、獲取、刪除元素 根據分值範圍或者成員來獲取元素、計算一個鍵的排名 |
struct sdshdr{ //記錄buf數組中已使用字節的數量 int len; //記錄buf數組中未使用的數量 int free; //字節數組,用於保存字符串 char buf[]; }
127.0.0.1:6379> set hello world OK 127.0.0.1:6379> get hello "world" 127.0.0.1:6379> del hello (integer) 1 127.0.0.1:6379> get hello (nil) 127.0.0.1:6379>
String是最經常使用的一種數據類型,普通的key/value存儲均可以歸爲此類,value其實不只是String,也能夠是數字:好比想知道何時封鎖一個IP地址(訪問超過幾回)。INCRBY命令讓這些變得很容易,經過原子遞增保持計數。redis
typedef struct listNode{ //前置節點 struct listNode *prev; //後置節點 struct listNode *next; //節點的值 struct value; }
> lpush list-key item (integer) 1 > lpush list-key item2 (integer) 2 > rpush list-key item3 (integer) 3 > rpush list-key item (integer) 4 > lrange list-key 0 -1 1) "item2" 2) "item" 3) "item3" 4) "item" > lindex list-key 2 "item3" > lpop list-key "item2" > lrange list-key 0 -1 1) "item" 2) "item3" 3) "item"
Redis list的應用場景很是多,也是Redis最重要的數據結構之一。
咱們能夠輕鬆地實現最新消息排行等功能。
Lists的另外一個應用就是消息隊列,能夠利用Lists的PUSH操做,將任務存在Lists中,而後工做線程再用POP操做將任務取出進行執行。數據庫
dictht是一個散列表結構,使用拉鍊法保存哈希衝突的dictEntry。數組
typedef struct dictht{ //哈希表數組 dictEntry **table; //哈希表大小 unsigned long size; //哈希表大小掩碼,用於計算索引值 unsigned long sizemask; //該哈希表已有節點的數量 unsigned long used; } typedef struct dictEntry{ //鍵 void *key; //值 union{ void *val; uint64_tu64; int64_ts64; } struct dictEntry *next; }
Redis的字典dict中包含兩個哈希表dictht,這是爲了方便進行rehash操做。在擴容時,將其中一個dictht上的鍵值對rehash到另外一個dictht上面,完成以後釋放空間並交換兩個dictht的角色。服務器
typedef struct dict { dictType *type; void *privdata; dictht ht[2]; long rehashidx; /* rehashing not in progress if rehashidx == -1 */ unsigned long iterators; /* number of iterators currently running */ } dict;
rehash操做並非一次性完成、而是採用漸進式方式,目的是爲了不一次性執行過多的rehash操做給服務器帶來負擔。數據結構
漸進式rehash經過記錄dict的rehashidx完成,它從0開始,而後沒執行一次rehash例如在一次 rehash 中,要把 dict[0] rehash 到 dict[1],這一次會把 dict[0] 上 table[rehashidx] 的鍵值對 rehash 到 dict[1] 上,dict[0] 的 table[rehashidx] 指向 null,並令 rehashidx++。性能
在 rehash 期間,每次對字典執行添加、刪除、查找或者更新操做時,都會執行一次漸進式 rehash。ui
採用漸進式rehash會致使字典中的數據分散在兩個dictht中,所以對字典的操做也會在兩個哈希表上進行。
例如查找時,先從ht[0]查找,沒有再查找ht[1],添加時直接添加到ht[1]中。spa
> hset hash-key sub-key1 value1 (integer) 1 > hset hash-key sub-key2 value2 (integer) 1 > hset hash-key sub-key1 value1 (integer) 0 > hgetall hash-key 1) "sub-key1" 2) "value1" 3) "sub-key2" 4) "value2" > hdel hash-key sub-key2 (integer) 1 > hdel hash-key sub-key2 (integer) 0 > hget hash-key sub-key1 "value1" > hgetall hash-key 1) "sub-key1" 2) "value1"
> sadd set-key item (integer) 1 > sadd set-key item2 (integer) 1 > sadd set-key item3 (integer) 1 > sadd set-key item (integer) 0 > smembers set-key 1) "item2" 2) "item" 3) "item3" > sismember set-key item4 (integer) 0 > sismember set-key item (integer) 1 > srem set-key item (integer) 1 > srem set-key item (integer) 0 > smembers set-key 1) "item2" 2) "item3"
Redis爲集合提供了求交集、並集、差集等操做,故能夠用來求共同好友等操做。操作系統
typedef struct zskiplistNode{ //後退指針 struct zskiplistNode *backward; //分值 double score; //成員對象 robj *obj; //層 struct zskiplistLever{ //前進指針 struct zskiplistNode *forward; //跨度 unsigned int span; }lever[]; } typedef struct zskiplist{ //表頭節點跟表尾結點 struct zskiplistNode *header, *tail; //表中節點的數量 unsigned long length; //表中層數最大的節點的層數 int lever; }
跳躍表,基於多指針有序鏈實現,能夠看做多個有序鏈表。.net
在查找時,先從上層指針開始查找,找到對應的區間以後再到下一層查找。下圖演示了查找22的過程。
與紅黑樹等平衡樹相比,跳躍表具備如下優勢:
> zadd zset-key 728 member1 (integer) 1 > zadd zset-key 982 member0 (integer) 1 > zadd zset-key 982 member0 (integer) 0 > zrange zset-key 0 -1 1) "member1" 2) "member0" > zrange zset-key 0 -1 withscores 1) "member1" 2) "728" 3) "member0" 4) "982" > zrangebyscore zset-key 0 800 withscores 1) "member1" 2) "728" > zrem zset-key member1 (integer) 1 > zrem zset-key member1 (integer) 0 > zrange zset-key 0 -1 withscores 1) "member0" 2) "982"
以某個條件爲權重,好比按頂的次數排序
ZREVRANGE命令能夠用來按照得分來獲取前100名的用戶,ZRANK能夠用來獲取用戶排名,很是直接並且操做容易。
Redis sorted set的使用場景與set相似,區別是set不是自動有序的,而sorted set能夠經過用戶額外提供一個優先級(score)的參數來爲成員排序,而且是插入有序的,即自動排序。
Redis能夠爲每一個鍵設置過時時間,當鍵過時時,會自動刪除該鍵。
經過EXPIRE命令或者PEXPIRE命令,客戶端能夠以秒或者秒精度爲數據庫中的某個鍵設置生存時間(Time To Live,TTL),在通過執行的秒數或者毫秒書以後,服務器就會自動刪除生存時間爲0的鍵。
對於散列表這種容器,只能爲整個鍵設置過時時間(整個散列鍵),而不能爲鍵裏面的單個元素設置過時時間。
Redis是內存數據庫,爲了不數據意外丟失,須要將內存中的數據持久化到磁盤中。
在指定的時間間隔內將內存中的數據集快照寫入磁盤,恢復時是將快照文件直接讀到內存裏。
Redis會單首創建(fork)一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,再用這個臨時文件替代上次持久化完成的文件。整個過程當中,主進程不進行任何IO操做,這就確保了極高的性能。若是須要進行大規模數據的恢復,且對於數據的完整性不是特別敏感,那麼RDB方式要比AOF方式更加的高效。RDB的缺點是最後一次持久化的數據可能丟失。
以日誌的形式來記錄每一個寫操做,將redis執行過的全部寫指令記錄下來(讀操做不記錄),只需追加文件不能夠改寫文件,redis啓動之初會讀取該文件重構數據,換言之,redis重啓的話就是根據日誌文件的內容從前到後執行一次以完成數據的恢復工做。
將命令添加到AOF文件的末尾。
使用AOF持久化須要設置同步選項,從而確保命令何時會同步到磁盤文件上。這是由於對文件寫入並不會立馬將內容同步到磁盤上,而是先存儲到緩衝區,案後由操做系統決定何時同步到磁盤。有一喜好同步選項:
選項 | 同步頻率 |
---|---|
always | 每一個寫命令都同步 |
everysec | 每秒同步一次 |
no | 讓操做系統來決定什麼時候同步 |
Redis事務指一次執行多個命令,本質是一組命令的集合,一個事物中的全部命令都會被序列化,按順序地串行執行而不是被其餘命令插入,不準加塞。一個隊列中,一次性、順序性、排他性的執行一系列命令。
Redis事務執行的一些狀況:
Redis的複製也就是咱們所說的主從複製,主機數據更新後根據配置和策略,自動同步到備機的master/slaver機制,master已寫爲主,slaver已讀爲主。
Sentinel是Redis高可用的解決方案,由一個或多個Sentinel實例組成的Sentinel系統能夠監視多個主服務器,以及這些主服務器屬下的全部從服務器,並在被監視的主服務器進行下線時自動將屬下的某個從服務器升級爲新的主服務器,而後由新的主服務器代替已下線的主服務器繼續處理命令請求。
Redis提供的Sentinel(哨兵)機制,經過Sentinel模式啓動Redis後,自動監控master/slaver的運行狀態,基本原理:心跳機制和投票裁決。
Redis設計與實現
Redis 講解系列之 Redis的持久化
Redis 講解系列之 Redis的事務
Redis 講解系列之 Redis的複製(一)
Redis 講解系列之 Redis的複製(二)