天天看點

Redis

  下面是官方的bench-mark資料:

  測試完成了50個并發執行100000個請求。

  設定和擷取的值是一個256位元組字元串。

  Linux box是運作Linux 2.6,這是X3320 Xeon 2.5 ghz。

  文本執行使用loopback接口(127.0.0.1)。

  結果:每秒約110000套,每秒約81000得到。

  redis目前提供四種資料類型:string,list,set及zset(sorted set)。

  string(字元串)

  string是最簡單的類型,你可以了解成與Memcached一模一樣的類型,一個key對應一個value,其上支援的操作與Memcached的操作類似。但它的功能更豐富。

  typedef char *sds;

  struct sdshdr {

  long len;

  long free;

  char buf[];

  };

  list(雙向連結清單)

  list是一個連結清單結構,主要功能是push、pop、擷取一個範圍的所有值等等。操作中key了解為連結清單的名字。

  對list的定義和實作在源檔案adlist.h/adlist.c,相關的資料結構定義如下:

  typedef struct listIter {

  listNode *next;

  int direction;

  } listIter;

  // list資料結構

  typedef struct list {

  listNode *head;

  listNode *tail;

  void *(*dup)(void *ptr);

  void (*free)(void *ptr);

  int (*match)(void *ptr, void *key);

  unsigned int len;

  listIter iter;

  } list;

  dict(hash表)

  set是集合,和我們數學中的集合概念相似,對集合的操作有添加删除元素,有對多個集合求交并差等操作。操作中key了解為集合的名字。

  在源檔案dict.h/dict.c中實作了hashtable的操作,資料結構的定義如下:

  // dict中的元素項

  typedef struct dictEntry {

  void *key;

  void *val;

  struct dictEntry *next;

  } dictEntry;

  // dict相關配置函數

  typedef struct dictType {

  unsigned int (*hashFunction)(const void *key);

  void *(*keyDup)(void *privdata, const void *key);

  void *(*valDup)(void *privdata, const void *obj);

  int (*keyCompare)(void *privdata, const void *key1, const void *key2);

  void (*keyDestructor)(void *privdata, void *key);

  void (*valDestructor)(void *privdata, void *obj);

  } dictType;

  // dict定義

  typedef struct dict {

  dictEntry **table;

  dictType *type;

  unsigned long size;

  unsigned long sizemask;

  unsigned long used;

  void *privdata;

  } dict;

  // dict疊代器

  typedef struct dictIterator {

  dict *ht;

  int index;

  dictEntry *entry, *nextEntry;

  } dictIterator;

  zset(排序set)

  zset是set的一個更新版本,他在set的基礎上增加了一個順序屬性,這一屬性在添加修改元素的時候可以指定,每次指定後,zset會自動重新按新的值調整順序。可以了解了有兩列的mysql表,一列存value,一列存順序。操作中key了解為zset的名字。

  typedef struct zskiplistNode {

  struct zskiplistNode **forward;

  struct zskiplistNode *backward;

  double score;

  robj *obj;

  } zskiplistNode;

  typedef struct zskiplist {

  struct zskiplistNode *header, *tail;

  unsigned long length;

  int level;

  } zskiplist;

  typedef struct zset {

  dict *dict;

  zskiplist *zsl;

  } zset;

  zset利用dict維護key -> value的映射關系,用zsl(zskiplist)儲存value的有序關系。zsl實際是叉數

  當接收到SAVE指令的時候,Redis就會dump資料到一個檔案裡面。

  值得一說的是它的獨家功能:存儲清單和集合,這是它與mc之流相比更有競争力的地方。

  不介紹mc裡面已經有的東東,隻列出特殊的:

  TYPE key — 用來擷取某key的類型

  KEYS pattern — 比對所有符合模式的key,比如KEYS * 就列出所有的key了,當然,複雜度O(n)

  RANDOMKEY - 傳回随機的一個key

  清單操作,精華

  RPUSH key string — 将某個值加入到一個key清單頭部

  LPUSH key string — 将某個值加入到一個key清單末尾

  LLEN key — 清單長度

  LTRIM key start end — 隻保留清單中某個範圍的值

  LINDEX key index — 擷取清單中特定索引号的值,要注意是O(n)複雜度

  LSET key index value — 設定清單中某個位置的值

  LPOP key

  集合操作

  SADD key member — 增加元素

  SREM key member — 删除元素

  SCARD key — 傳回集合大小

  SISMEMBER key member — 判斷某個值是否在集合中

  SINTER key1 key2 ... keyN — 擷取多個集合的交集元素

  SMEMBERS key — 列出集合的所有元素

  還有Multiple DB的指令,可以更換db,資料可以隔離開,預設是存放在DB 0。

  便于下次讀取檔案進行加載;增量請求檔案則是把記憶體中的資料序列化為操作請求,用于讀取檔案進行replay得到資料,序列化的操作包括SET、RPUSH、SADD、ZADD。

  appendonly yes/no ,appendonly配置,指出是否在每次更新操作後進行日志記錄,如果不開啟,可能會在斷電時導緻一段時間内的資料丢失。因為redis本身同步資料檔案是按上面的save條件來同步的,是以有的資料會在一段時間内隻存在于記憶體中。

  擷取源碼、解壓、進入源碼目錄

  使用wget工具等下載下傳:

  wget (百度不讓用連結)

  tar xzf redis-1.2.6.tar.gz

  cd redis-1.2.6。

  編譯生成可執行檔案

  由于makefile檔案已經寫好,我們隻需要直接在源碼目錄執行make指令進行編譯即可:

  make

  redis-server:Redis伺服器的daemon啟動程式

  redis-cli:Redis指令行操作工具。當然,你也可以用telnet根據其純文字協定來操作

  redis-stat:Redis狀态檢測工具,可以檢測Redis目前狀态參數及延遲狀況。

  建立Redis目錄(非必須)

  執行以下指令建立相關目錄并拷貝相關檔案至目錄中:

  sudo -s

  mkdir -p /usr/local/redis/bin

  mkdir -p /usr/local/redis/etc

  mkdir -p /usr/local/redis/var

  cp redis-server redis-cli redis-benchmark redis-stat /usr/local/redis/bin/

  cp redis.conf /usr/local/redis/etc/

  配置參數

  daemonize:是否以背景daemon方式運作

  pidfile:pid檔案位置

  port:監聽的端口号

  timeout:請求逾時時間

  loglevel:log資訊級别

  logfile:log檔案位置

  databases:開啟資料庫的數量

  rdbcompression:是否使用壓縮

  dbfilename:資料快照檔案名(隻是檔案名,不包括目錄)

  dir:資料快照的儲存目錄(這個是目錄)

  appendonly:是否開啟appendonlylog,開啟的話每次寫操作會記一條log,這會提高資料抗風險能力,但影響效率。

  appendfsync:appendonlylog如何同步到磁盤(三個選項,分别是每次寫都強制調用fsync、每秒啟用一次fsync、不調用fsync等待系統自己同步)

  下面是一個略做修改後的配置檔案内容:

  daemonize yes

  pidfile /usr/local/redis/var/redis.pid

  port 6379

  timeout 300

  loglevel debug

  logfile /usr/local/redis/var/redis.log

  databases 16

  save 900 1

  save 300 10

  save 60 10000

  rdbcompression yes

  dbfilename dump.rdb

  dir /usr/local/redis/var/

  appendonly no

  appendfsync always

  glueoutputbuf yes

  shareobjects no

  shareobjectspoolsize 1024

  将上面内容寫為redis.conf并儲存到/usr/local/redis/etc/目錄下

  然後在指令行執行:

  /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

  即可在背景啟動redis服務,這時你通過

  即可連接配接到你的redis服務

<dl></dl>

<dt>參考資料</dt>

<dd></dd>

<dt>擴充閱讀:</dt>

1

<a href="http://redis.io/" target="_blank">http://redis.io/</a>

<dt>開放分類:</dt>