Redis 一个key-value存储系统 简介
簡介 redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)和zset(有序集合)。這些數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。
性能
下面是官方的bench-mark數據:
The test was done with 50 simultaneous clients performing 100000 requests.
The value SET and GET is a 256 bytes string.
The Linux box is running Linux 2.6, it’s Xeon X3320 2.5Ghz.
Text executed using the loopback interface (127.0.0.1).
Results: about 110000 SETs per second, about 81000 GETs per second
數據結構
redis目前提供四種數據類型:string,list,set及zset(sorted set)。
sds(字符串)
string是最簡單的類型,你可以理解成與Memcached一模一個的類型,一個key對應一個value,其上支持的操作與Memcached的操作類似。但它的功能更豐富。
redis采用結構sdshdr和sds封裝了字符串,字符串相關的操作實現在源文件sds.h/sds.c中。sdshdr
數據結構定義如下:
typedef char *sds;
struct sdshdr {
long len;
long free;
char buf[];
};
list(雙向鏈表)
list是一個鏈表結構,主要功能是push、pop、獲取一個范圍的所有值等等。操作中key理解為鏈表的名字。
對list的定義和實現在源文件adlist.h/adlist.c,相關的數據結構定義如下:
// list迭代器
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;
dict中table為dictEntry指針的數組,數組中每個成員為hash值相同元素的單向鏈表。set是在dict的基礎上實現的,指定了key的比較函數為dictEncObjKeyCompare,若key相等則不再插入。
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實際是叉數
不穩定的多叉樹,每條鏈上的元素從根節點到葉子節點保持升序排序。
存儲結構以及存儲格式
redis使用了兩種文件格式:全量數據和增量請求。全量數據格式是把內存中的數據寫入磁盤,
便于下次讀取文件進行加載;增量請求文件則是把內存中的數據序列化為操作請求,用于讀取文件進行replay得到數據,序列化的操作包括SET、RPUSH、SADD、ZADD。
redis的存儲分為內存存儲、磁盤存儲和log文件三部分,配置文件中有三個參數對其進行配置。
save seconds updates,save配置,指出在多長時間內,有多少次更新操作,就將數據同步到數據文件。這個可以多個條件配合,比如默認配置文件中的設置,就設置了三個條件。
appendonly yes/no ,appendonly配置,指出是否在每次更新操作后進行日志記錄,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為redis本身同步數據文件是按上面的save條件來同步的,所以有的數據會在一段時間內只存在于內存中。
appendfsync no/always/everysec ,appendfsync配置,no表示等操作系統進行數據緩存同步到磁盤,always表示每次更新操作后手動調用fsync()將數據寫到磁盤,everysec表示每秒同步一次。
常用命令
就DB來說,Redis成績已經很驚人了,且不說memcachedb和tokyocabinet之流,就說原版的memcached,速度似乎也只能達到這個級別。Redis根本是使用內存存儲,持久化的關鍵是這三條指令:SAVE BGSAVE LASTSAVE …
當接收到SAVE指令的時候,Redis就會dump數據到一個文件里面。
值得一說的是它的獨家功能:存儲列表和集合,這是它與mc之流相比更有競爭力的地方。
不介紹mc里面已經有的東東,只列出特殊的:
TYPE key — 用來獲取某key的類型
KEYS pattern — 匹配所有符合模式的key,太淫蕩了,比如KEYS * 就列出所有的key了,當然,復雜度O(n)
RANDOMKEY - 返回隨機的一個key
RENAME oldkey newkey — key也可以改名
列表操作,精華
RPUSH key string — 將某個值加入到一個key列表頭部
LPUSH key string — 將某個值加入到一個key列表末尾
LLEN key — 列表長度
LRANGE key start end — 返回列表中某個范圍的值,相當于mysql里面的分頁查詢那樣
LTRIM key start end — 只保留列表中某個范圍的值
LINDEX key index — 獲取列表中特定索引號的值,要注意是O(n)復雜度
LSET key index value — 設置列表中某個位置的值
LPOP key
RPOP key — 和上面的LPOP一樣,就是類似棧或隊列的那種取頭取尾指令,可以當成消息隊列來使用了
集合操作
SADD key member — 增加元素
SREM key member — 刪除元素
SCARD key — 返回集合大小
SISMEMBER key member — 判斷某個值是否在集合中
SINTER key1 key2 ... keyN — 獲取多個集合的交集元素
SMEMBERS key — 列出集合的所有元素
還有Multiple DB的命令,可以更換db,數據可以隔離開,默認是存放在DB 0
安裝Redi
獲取源碼、解壓、進入源碼目錄
使用wget工具等下載:
wget (百度不讓用鏈接)
tar xzf redis-1.2.6.tar.gz
cd redis-1.2.6
編譯生成可執行文件
由于makefile文件已經寫好,我們只需要直接在源碼目錄執行make命令進行編譯即可:
make
make命令執行完成后,會在當前目錄下生成本個可執行文件,分別是redis-server、redis-cli、redis-benchmark、redis-stat,它們的作用如下:
redis-server:Redis服務器的daemon啟動程序
redis-cli:Redis命令行操作工具。當然,你也可以用telnet根據其純文本協議來操作
redis-benchmark:Redis性能測試工具,測試Redis在你的系統及你的配置下的讀寫性能
redis-stat:Redis狀態檢測工具,可以檢測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/
配置參數
在我們成功安裝Redis后,我們直接執行redis-server即可運行Redis,此時它是按照默認配置來運行的(默認配置甚至不是后臺運行)。我們希望Redis按我們的要求運行,則我們需要修改配置文件,Redis的配置文件就是我們上面第二個cp操作的redis.conf文件,目前它被我們拷貝到了/usr/local/redis/etc/目錄下。修改它就可以配置我們的server了。如何修改?下面是redis.conf的主要配置參數的意義:
daemonize:是否以后臺daemon方式運行
pidfile:pid文件位置
port:監聽的端口號
timeout:請求超時時間
loglevel:log信息級別
logfile:log文件位置
databases:開啟數據庫的數量
save * *:保存快照的頻率,第一個*表示多長時間,第三個*表示執行多少次寫操作。在一定時間內執行一定數量的寫操作時,自動保存快照。可設置多個條件。
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服務,這時你通過
telnet 127.0.0.1 6379
即可連接到你的redis服務
總結
以上是生活随笔為你收集整理的Redis 一个key-value存储系统 简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对处于初始起火阶段一般火灾事故,在组织人
- 下一篇: 去日本一定要10万流水吗