Redis 緩存

使用場景#

  • Redis 通常用作web應用的內存緩存,和Django,Ruby-on-Rails,Node.js以及Flask框架結合
  • Redis在存儲新的數據的過程中可以清除陳舊的數據。
  • Redis使用Less Recently Used(LRU)策略,可以為每個健設置過期時間
  • Redis 存儲指標數據用於量化網站的使用情況和用戶行為數據
  • Redis可用作不同系統之間的通訊層,通過訂閱推送消息模型

數據模型#

  • 字符串 簡單動態字符串,Redis底層使用的一種簡單動態字符串的抽象類型。
<code>struct sdshdr {
in length: # 記錄buf中已使用字節的數量
int free; # 記錄bug數組中未使用的字節的數量
char buf[]; # 字節數組保存字符串
}/<code>

優點:

  • 可以O(1)獲取存儲的鍵值的長度
  • 杜絕緩衝區溢出
  • 減少修改字符串帶來的內存重分配次數【【【【【【【
  • 列表 列表的底層實現就是一個鏈表,鏈表的每個節點保存一個鍵值。
<code>typedef struct listNode {
struct listNode *prev; #前置節點
struct listNode *next; #後置節點
void *value; #節點的值
} listNode

typedef struct list {
listNode *head; #頭節點
listNode *tail; #尾節點
unsigned long len; #節點數量
void *(*dup)(void *ptr); #節點複製函數
void (*free)(void *ptr); #節點釋放函數
int (*match)(void *ptr, void *key) #節點值對比函數
}/<code>

示例:

<code>127.0.0.1:6379> RPUSH integers 0 1 2 3 4 5 6
(integer) 7
127.0.0.1:6379> LLEN integers
(integer) 7
127.0.0.1:6379> LRANGE integers 0 10
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
7) "6"/<code>
  • 字典 Redis的字典使用哈希表作為底層實現,一個哈希表裡可以有多個哈希表節點,每個哈希表節點就保存了字典中的 一個鍵值對。
<code>typedef struct dictht {
dictEntry **table; #哈希表數組
unsigned long size; #哈希表大小
unsigned long sizemask; #哈希表大小掩碼
unsigned long used; #該哈希表已有節點的數量
}dictht

typedef struct dictEntry {
void *key;
union {
void *val;
uint64_tu64;
int64_ts64;
} v;
struct dictEntry next;
}dictEntry

typedef struct dict {
dictType * type; # 類型特定函數
void *privatedata; # 私有數據
dictht ht[2]; # 哈希表
int rehashidx; #rehash 索引
}/<code>


Redis 緩存


當有一個新的鍵值對添加到字典中時,字典會對鍵進行哈希,得到哈希值後在和掩碼進行與運算得到最終的哈希值 當有兩個以上的鍵被分配到同一個哈希表數組的同一個索引上時,此時會產生鍵衝突。一般解決衝突有兩種方法, 一種是Rehash,一種是鏈地址法。

  • 鏈地址法: 每個哈希表都有一個next指針,多個哈希表節點可以用next指針構成一個單向鏈表,被分配到同一個 索引上的多個節點可以用這個單向鏈表連接起來
  • Rehash: 隨著哈希表中鍵值對增多和減少,為了使負載因子維持在一個合理的範圍,需要對哈希表進行Rehash - 擴展,申請ht[1]的大小為大於ht[0].used*2的第一個2的次方的數,收縮,ht[1]為ht[0].used的第一個2的N次方的數。 - 執行rehash將ht[0]中的數值映射到ht[1]上 - 將ht[1]設置為ht[0],ht[1]新建一個空白哈希表
  • 跳躍表 跳躍表是一種有序數據結構,它通過在每個節點中維持多個指向其他節點的指針,從而達到快速訪問節點的目.Redis使用跳躍表來實現有序集合鍵,和集群節點中的內部數據結構. redis使用的是zskiplist結構

zskiplist包含以下屬性: header: 指向跳躍表的表頭節點 tail: 指向跳躍表的表尾節點 level: 記錄目前跳躍表內,層數最大的那個節點的層數 length: 記錄跳躍表的長度即跳躍表目前包含的節點的數量

<code>typedef struct zskiplistNode {

struct zskiplistLevel {
struct zskiplistNode *forward;
unsigned int span;
} level[];

struct zskiplistNode *backward;
double score;
robj *obj

} zskiplistNode

typedef struct zskiplist{
structz skiplistNode *header, *tail;

unsigned long length;

int level;

} zskiplist;/<code>

常用命令#

在設計Redis存儲結構的時候,主要要考慮鍵和數據結構兩方面 如果使用SET或者GETSET命令去更新鍵值, 鍵值的過期時間會被清除

<code>127.0.0.1:6379> EXPIRE tea/1/box1/bag/8 300
(integer) 1
127.0.0.1:6379> TTL tea/1/box1/bag/8
(integer) 260
127.0.0.1:6379> SET tea/1/box1/bag/8 brew
OK
127.0.0.1:6379> TTL tea/1/box1/bag/8
(integer) -1/<code>


分享到:


相關文章: