redis安裝及配置
安裝
wget http://download.redis.io/releases/redis-3.0.7.tar.gz tar zxvf redis-3.0.7.tar.gz cd redis-3.0.7/ make make install
安裝後,在/usr/local/bin下面有如下文件:
redis-server 服務器 redis-cli 命令行客戶端 redis-benchmark 性能測試工具 redis-check-aof AOF文件修復工具 redis-check-dump RDB文件檢查工具
啓動
不指定配置文件啓動,在控制檯執行:redis-server
指定配置文件啓動,需要加上參數:redis-server /etc/myredis.conf
指定端口啓動:redis-server –port 6379
以salve方式啓動:redis-server –port 6380 –slaveof 127.0.0.1 6379
可以使用redis自帶的redis-cli作爲客戶端連接服務器
配置
Redis默認不是以守護進程的方式運行,可以通過該配置項修改,使用yes啓用守護進程
daemonize no
當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定
pidfile /var/run/redis.pid
指定Redis監聽端口,默認端口爲6379,作者在自己的一篇博文中解釋了爲什麼選用6379作爲默認端口,因爲6379在手機按鍵上MERZ對應的號碼,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
綁定的主機地址
bind 127.0.0.1
當客戶端閒置多長時間後關閉連接,如果指定爲0,表示關閉該功能
timeout 300
指定日誌記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認爲verbose
loglevel verbose
日誌記錄方式,默認爲標準輸出,如果配置Redis爲守護進程方式運行,而這裏又配置爲日誌記錄方式爲標準輸出,則日誌將會發送給/dev/null
logfile stdout
設置數據庫的數量,默認數據庫爲0,可以使用SELECT <dbid>命令在連接上指定數據庫id
databases 16
指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合
save <seconds> <changes>
Redis默認配置文件中提供了三個條件:
save 900 1
save 300 10
save 60 10000
分別表示900秒(15分鐘)內有1個更改,300秒(5分鐘)內有10個更改以及60秒內有10000個更改。
指定存儲至本地數據庫時是否壓縮數據,默認爲yes,Redis採用LZF壓縮,如果爲了節省CPU時間,可以關閉該選項,但會導致數據庫文件變的巨大
rdbcompression yes
指定本地數據庫文件名,默認值爲dump.rdb
dbfilename dump.rdb
指定本地數據庫存放目錄
dir ./
設置當本機爲slav服務時,設置master服務的IP地址及端口,在Redis啓動時,它會自動從master進行數據同步
slaveof <masterip> <masterport>
當master服務設置了密碼保護時,slav服務連接master的密碼
masterauth <master-password>
設置Redis連接密碼,如果配置了連接密碼,客戶端在連接Redis時需要通過AUTH <password>命令提供密碼,默認關閉
requirepass foobared
設置同一時間最大客戶端連接數,默認無限制,Redis可以同時打開的客戶端連接數爲Redis進程可以打開的最大文件描述符數,如果設置 maxclients 0,表示不作限制。當客戶端連接數到達限制時,Redis會關閉新的連接並向客戶端返回max number of clients reached錯誤信息
maxclients 128
指定Redis最大內存限制,Redis在啓動時會把數據加載到內存中,達到最大內存後,Redis會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大內存設置,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis新的vm機制,會把Key存放內存,Value會存放在swap區
maxmemory <bytes>
指定是否在每次更新操作後進行日誌記錄,Redis在默認情況下是異步的把數據寫入磁盤,如果不開啓,可能會在斷電時導致一段時間內的數據丟失。因爲 redis本身同步數據文件是按上面save條件來同步的,所以有的數據會在一段時間內只存在於內存中。默認爲no
appendonly no
指定更新日誌文件名,默認爲appendonly.aof
appendfilename appendonly.aof
指定更新日誌條件,共有3個可選值: no:表示等操作系統進行數據緩存同步到磁盤(快) always:表示每次更新操作後手動調用fsync()將數據寫到磁盤(慢,安全) everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
指定是否啓用虛擬內存機制,默認值爲no,簡單的介紹一下,VM機制將數據分頁存放,由Redis將訪問量較少的頁即冷數據swap到磁盤上,訪問多的頁面由磁盤自動換出到內存中(在後面的文章我會仔細分析Redis的VM機制)
vm-enabled no
虛擬內存文件路徑,默認值爲/tmp/redis.swap,不可多個Redis實例共享
vm-swap-file /tmp/redis.swap
將所有大於vm-max-memory的數據存入虛擬內存,無論vm-max-memory設置多小,所有索引數據都是內存存儲的(Redis的索引數據 就是keys),也就是說,當vm-max-memory設置爲0的時候,其實是所有value都存在於磁盤。默認值爲0
vm-max-memory 0
Redis swap文件分成了很多的page,一個對象可以保存在多個page上面,但一個page上不能被多個對象共享,vm-page-size是要根據存儲的 數據大小來設定的,作者建議如果存儲很多小對象,page大小最好設置爲32或者64bytes;如果存儲很大大對象,則可以使用更大的page,如果不 確定,就使用默認值
vm-page-size 32
設置swap文件中的page數量,由於頁表(一種表示頁面空閒或使用的bitmap)是在放在內存中的,,在磁盤上每8個pages將消耗1byte的內存。
vm-pages 134217728
設置訪問swap文件的線程數,最好不要超過機器的核數,如果設置爲0,那麼所有對swap文件的操作都是串行的,可能會造成比較長時間的延遲。默認值爲4
vm-max-threads 4
設置在向客戶端應答時,是否把較小的包合併爲一個包發送,默認爲開啓
glueoutputbuf yes
指定在超過一定的數量或者最大的元素超過某一臨界值時,採用一種特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
指定是否激活重置哈希,默認爲開啓(後面在介紹Redis的哈希算法時具體介紹)
activerehashing yes
指定包含其它的配置文件,可以在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有自己的特定配置文件
include /path/to/local.conf
redis數據庫管理工具
命令行管理工具
redis_cli是redis自帶的命令行工具。
用法示例:
root@debian8:redis-3.0.7# redis-cli127.0.0.1:6379> keys * (empty list or set)127.0.0.1:6379>
圖形管理工具
redis desktop
基本操作
這裏字符串類型爲例描述redis的基本操作命令,其它數據類型參考文檔。
SET
如果key不存在,該命令可以完成添加操作;如果key存在,該命令實現更新操作;
SET key value
GET
獲取某個key所對應的值,格式如下:
GET key
DEL
刪除操作,格式如下:
DEL key
KEYS
獲取符合規律的鍵名列表,格式如下:
KEYS pattern
pattern支持glob風格通配符格式,具體如下:
? 匹配一個字符 * 匹配任意個(包括0個)字符[] 匹配括號間的任一字符,可以使用"-"符號表示一個 範圍,如a[b-d]可以匹配"ab","ac"和"ad" \x 匹配字符x,用於轉義符號。
EXISTS
用於判斷一個鍵是否存在,格式:
EXISTS key
EXPIRE
設置key的超時時間TTL(Time To Live),生存時間到期後鍵會自動被刪除,格式:
EXPIRE key seconds
數據模型
Redis是REmote DIctionary Server(遠程字典服務器)的縮寫, 它以字典結構存儲數據,並允許其他應用通過TCP協議讀寫字典中的內容。 同大多數腳本語言中的字典一樣,Redis字典中的鍵值除了可以是字符串,還可以是其他數據類型。 到目前爲止 Redis 支持的鍵值數據類型如下:
字符串類型
字符串是redis最基礎的數據類型,它能存儲任何形式的字符串,包括二進制數據。 一個字符串類型鍵允許存儲的數據的最大容量是512M。 常用命令如下:
SET
賦值操作
SET key value
示例:
SET a 5 ==> OK
GET
取值操作
GET key
示例:
GET a ==> "5"
INCR
遞增操作,鍵不存在時創建並賦0,否則+1
INCR key
示例:
INCR a ==> 6
DECR
遞減操作
DECR key
示例:
DECR a ==> 5
INCRBY
與incr一樣,不過可以指定增加的數值
INCRBY key num
示例:
INCRBY a 10 ==> 15
APPEND
追加,返回追加後字符串長度
APPEND key value
示例:
APPEND a 6 ==> 156
STRLEN
獲取字符串長度
STRLEN key
示例:
STRLEN a ==> 3
MSET
同時設置多個鍵值
MSET key value[key2 value2 ...]
示例:
MSET key1 1 key2 2 ==> OK
MGET
同時獲取多個鍵值
MGET key1 key2 =>1) "1"2) "2"
其它string命令參考官方手冊 : http://redis.io/commands#string
散列類型
散列類型(hash)的鍵值也是一種字典結構,其存儲了字段(field)和字段值的映射, 但字段值只能是字符串,不支持其他數據類型,也就是散列類型不能嵌套其他的數據類型。
除了散列類型,Redis 的其他數據類型同樣不支持數據類型嵌套。比如集合類型的每個元素都只能是字符串,不能是另一個集合或散列表等。
散列類型適合存儲對象:使用對象類別和 ID 構成鍵名,使用字段表示對象的屬性, 而字段值則存儲屬性值。
常用命令如下:
HSET
設置或修改字段值
HSET key field value
HGET
獲取字段值
HGET key field
HMSET
同時設置多個字段
HMSET key field value [field value ...]
HMGET
同時獲取多個字段值
HMGET key field [field ...]
HGETALL
獲取鍵中所有字段和值
HGETALL key
HEXISTS
判斷字段是否存在,存在返回1,否則返回0(如果鍵不存在也返回0)
HEXISTS key field
其它hashs命令參考官方手冊 : http://redis.io/commands#hash
列表類型
列表類型(list)可以存儲一個有序的字符串列表,常用的操作是向列表兩端添加元素,或者獲得列表的某一個片段。
列表類型內部是使用雙向鏈表(double linked list)實現的,所以向列表兩端添加元素的時間複雜度爲O(1),獲取越接近兩端的元素速度就越快。 這意味着即使是一個有幾千萬個元素的列表,獲取頭部或尾部的10條記錄也是極快的(和從只有20個元素的列表中獲取頭部或尾部的10條記錄的速度是一樣的)。
這種特性使列表類型能非常快速地完成關係數據庫難以應付的場景: 如社交網站的新鮮事,我們關心的只是最新的內容,使用列表類型存儲, 即使新鮮事的總數達到幾千萬個,獲取其中最新的100條數據也是極快的。 同樣因爲在兩端插入記錄的時間複雜度是O(1),列表類型也適合用來記錄日誌,可以保證加入新日誌的速度不會受到已有日誌數量的影響。
常用命令如下:
LPUSH
向列表的左邊增加元素,返回增加元素後列表的長度
LPUSH key value[ value..]
RPUSH
向列表的右邊增加元素
RPUSH key value[ value..]
LPOP
從列表左邊移除一個元素,並返回該元素值
LPOP key
RPOP
從列表的右側移除一個元素,並返回該元素值
RPOP key
LLEN
返回列表元素個數,鍵不存在時返回0
LLEN key
LRANGE
獲取列表片段,start和stop支持負數,-1表示右數第一個
LRANGE key start stop
LREM
刪除列表中指定的值,返回刪除的元素個數
LREM key count value
LINDEX
獲取指定索引元素值
LINDEX key index
LSET
設置指定索引的元素值
LSET key index value
LTRIM
只保留列表指定片段,刪除其他元素
LTRIM key start end
其它命令參考官方手冊 : http://redis.io/commands#list
集合類型
集合中的每個元素都不同,且沒有順序。
常用命令如下:
SADD
增加一個或多個元素
SADD key member[ member..]
SREM
移除一個或多個元素
SREM key member[ member..]
SMEMBERS
獲取集合中所有的元素
SMEMBERS key
SISMEMBER
判斷元素是否存在集合中
SISMEMBER key member
SCARD
獲取集合的元素個數
SCARD key
SRANDMEMBER
返回1個或count個隨機元素
SRANDMEMBER key[ count]
SDIFF
集合差運算
SDIFF key[ key..]
SINTER
集合交集運算
SINTER key[ key..]
SUNION
集合並集運算
SUNION key[ key..]
其它sets命令參考官方手冊 : http://redis.io/commands#set
有序集合類型
在集合類型的基礎上有序集合類型爲每個元素都關聯了一個分數,這使我們可以使用集合類型的操作之外,還能做與分數有關的操作。
常用命令如下:
ZADD
增加一個帶分數的元素,如果已存在,則替換分數
ZADD key score member[ score member..]
ZSCORE
獲得元素分數
ZSCORE key member
ZRANGE
獲得排名在某個範圍內的元素,返回按score升序排序的元素
ZRANGE key start end[ WITHSCORES]
ZREVRANGE
與zrange使用一致,返回按score降序的元素
ZREVRANGE key start end[ WITHSCORES]
ZRANGEBYSCORE
獲得指定分數範圍內的元素
ZRANGEBYSCORE key min max WITHSCORES
ZREVRANGEBYSCORE
獲得指定分數範圍內的元素,降序排序
ZREVRANGEBYSCORE key max min WITHSCORES
ZINCREBY
增加某個元素的分數
ZINCREBY key increment member
ZCARD
獲取集合中元素個數
ZCARD key
ZCOUNT
獲得指定分數範圍內的元素個數
ZCOUNT KEY min max
ZREM
刪除一個或多個元素
ZREM key member[ member..]
ZRANK
獲取分數從小到大排序的位置
ZRANK key member
其它sorted_set命令參考官方手冊 : http://redis.io/commands#sorted_set
redis事務
Redis 事務可以一次執行多個命令,並且帶有以下兩個重要的保證:
事務是一個單獨的隔離操作:
事務中的所有命令都會序列化、按順序地執行。 事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。
事務是一個原子操作:
事務中的命令要麼全部被執行,要麼全部都不執行。
一個事務從開始到執行會經歷以下三個階段:
開始事務(multi)
命令入隊
執行事務(exec)
示例如下:
127.0.0.1:6379> MULTIOK127.0.0.1:6379> set var 1QUEUED127.0.0.1:6379> get varQUEUED127.0.0.1:6379> exec1) OK2) "1" 127.0.0.1:6379>
redis客戶端開發庫
c客戶端
Redis官方推薦的C客戶端是hiredis, github地址: https://github.com/redis/hiredis
同步API
redisConnect
連接redis數據庫(同步方式)
redisContext *redisConnect(const char *ip, int port);
用法示例:
redisContext *c = redisConnect("127.0.0.1", 6379);if (c == NULL || c->err) { if (c) { printf("Error: %s\n", c->errstr); // handle error } else { printf("Can't allocate redis context\n"); } }
redisCommand
給redis發送命令
void *redisCommand(redisContext *c, const char *format, ...);
用法示例:
reply = redisCommand(context, "SET foo bar");reply = redisCommand(context, "SET foo %s", value);reply = redisCommand(context, "SET foo %b", value, (size_t)valuelen);reply = redisCommand(context, "SET key:%s %s", myid, value);
freeReplyObject
釋放redis資源
void freeReplyObject(void *reply);
其它api參考hiredis.h
異步API
redisAsyncConnect
連接redis數據庫(異步方式)
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
示例代碼:
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);if (c->err) { printf("Error: %s\n", c->errstr); // handle error }
redisAsyncSetConnectCallback
redis連接回調函數
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
示例代碼:
void connectCallback(const redisAsyncContext *c, int status) { if (status != REDIS_OK) { printf("Error: %s\n", c->errstr); return; } printf("Connected...\n"); } redisAsyncSetConnectCallback(c,connectCallback);
redisAsyncSetDisconnectCallback
redis斷開連接的回調函數
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
示例代碼:
void disconnectCallback(const redisAsyncContext *c, int status) { if (status != REDIS_OK) { printf("Error: %s\n", c->errstr); return; } printf("Disconnected...\n"); } redisAsyncSetDisconnectCallback(c,disconnectCallback);
redisAsyncCommand
以異步方式給redis發送命令。
int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
示例代碼:
void getCallback(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; if (reply == NULL) return; printf("argv[%s]: %s\n", (char*)privdata, reply->str); /* Disconnect after receiving the reply to GET */ redisAsyncDisconnect(c); } redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");
redisAsyncDisconnect
斷開異步連接
void redisAsyncDisconnect(redisAsyncContext *ac);
其它api參考async.h
python客戶端
Redis官方推薦的Python客戶端是redis-py, github地址: https://github.com/andymccurdy/redis-py
安裝方式:
pip install redis
或者
easy_install redis
使用方法
1. 導入redis
import redis
2. 連接到redis
r = redis.StrictRedis() # 默認 127.0.0.1:6379
也可以顯式指定需要連接的地址:
r = redis.StrictRedis(host='127.0.0.1',port=6379,db=0)
3.操作redis
以SET和GET命令爲例:
r.set('var','1') print r.get('var')
異步方式redis客戶端請參考asyncio_redis: http://asyncio-redis.readthedocs.org/en/latest/
redis作爲消息隊列
工作隊列模式
redis的隊列實際在代碼邏輯中不需要由我們自己實現, 因此一個所謂的 RedisMQ 對象實際是一個 redis key以及對其操作的一些封裝。
可以通過list的lpush和rpop來模擬實現。
127.0.0.1:6379> LPUSH q1 1 (integer) 1 127.0.0.1:6379> LPUSH q1 2 (integer) 2 127.0.0.1:6379> LPUSH q1 3 (integer) 3 127.0.0.1:6379> RPOP q1"1" 127.0.0.1:6379> RPOP q1"2" 127.0.0.1:6379> RPOP q1"3" 127.0.0.1:6379>
如果是優先級隊列可以用zset來實現。
訂閱發佈模式
實現思想很簡單,Publisher調用redis的publish方法往特定的channel發送消息,Subscriber在初始化的時候要subscribe到該channel,一旦有消息就會立即接收。
訂閱消息(redis-cli終端1):
發佈消息(redis-cli終端2):
其它命令參考: http://redis.io/commands#pubsub
更多關於pubsub的描述詳見: http://redis.io/topics/pubsub
Redis作爲消息隊列與RabbitMQ的性能對比:
http://zqdevres.qiniucdn.com/data/20110714104018/index.html
腳本支持
Redis提供了通過eval命令來執行Lua 5.1腳本。
下面通過幾個小例子來講述如何在Redis服務端執行Lua腳本。
redis-cli中直接執行lua腳本
bash調用redis-cli執行
如果lua腳本內容比較長,可以將lua腳本寫入文件, 然後通過redis-cli執行:
與mysql交互
mysql2redis
https://github.com/dawnbreaks/mysql2redis