Redis是一個開源的使用ANSI C語言編寫、遵照BSD協議、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。html
它一般被稱爲數據結構服務器,由於值(value)能夠是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。java
更多詳細數據請見官方bench-mark page(http://code.google.com/p/redis/wiki/Benchmarks)mysql
學習玩windows ,Linux都差很少.可是官方不推薦windows版的,建議閒麻煩再Linux上玩dockergit
安裝略redis
Redis 的配置文件位於 Redis 安裝目錄下,文件名爲 redis.conf。算法
你能夠經過 CONFIG 命令查看或設置配置項。sql
Redis CONFIG 命令格式以下:mongodb
redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
redis 127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"
使用 * 號獲取全部配置項:docker
redis 127.0.0.1:6379> CONFIG GET *
你能夠經過修改 redis.conf 文件或使用 CONFIG set 命令來修改配置。數據庫
在Linux下建議複製一份 redis.conf再配置.
而後使用複製的配置文件來啓動redis
redis-server /etc/redis.conf
3.2.100 有個134條
CONFIG SET 命令基本語法:
redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
redis 127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"
redis.conf 配置項說明以下:
\1. Redis默認不是以守護進程的方式運行,能夠經過該配置項修改,使用yes啓用守護進程
daemonize no
\2. 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,能夠經過pidfile指定
pidfile /var/run/redis.pid
\3. 指定Redis監聽端口,默認端口爲6379,做者在本身的一篇博文中解釋了爲何選用6379做爲默認端口,由於6379在手機按鍵上MERZ對應的號碼,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
\4. 綁定的主機地址
bind 127.0.0.1
\5.當 客戶端閒置多長時間後關閉鏈接,若是指定爲0,表示關閉該功能
timeout 300
\6. 指定日誌記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認爲verbose
loglevel verbose
\7. 日誌記錄方式,默認爲標準輸出,若是配置Redis爲守護進程方式運行,而這裏又配置爲日誌記錄方式爲標準輸出,則日誌將會發送給/dev/null
logfile stdout
\8. 設置數據庫的數量,默認數據庫爲0,可使用SELECT <dbid>
命令在鏈接上指定數據庫id
databases 16
\9. 指定在多長時間內,有多少次更新操做,就將數據同步到數據文件,能夠多個條件配合
save <seconds> <changes>
Redis默認配置文件中提供了三個條件:
save 900 1
save 300 10
save 60 10000
分別表示900秒(15分鐘)內有1個更改,300秒(5分鐘)內有10個更改以及60秒內有10000個更改。
\10. 指定存儲至本地數據庫時是否壓縮數據,默認爲yes,Redis採用LZF壓縮,若是爲了節省CPU時間,能夠關閉該選項,但會致使數據庫文件變的巨大
rdbcompression yes
\11. 指定本地數據庫文件名,默認值爲dump.rdb
dbfilename dump.rdb
\12. 指定本地數據庫存放目錄
dir ./
\13. 設置當本機爲slav服務時,設置master服務的IP地址及端口,在Redis啓動時,它會自動從master進行數據同步
slaveof <masterip> <masterport>
\14. 當master服務設置了密碼保護時,slav服務鏈接master的密碼
masterauth <master-password>
\15. 設置Redis鏈接密碼,若是配置了鏈接密碼,客戶端在鏈接Redis時須要經過AUTH <password>
命令提供密碼,默認關閉
requirepass foobared
\16. 設置同一時間最大客戶端鏈接數,默認無限制,Redis能夠同時打開的客戶端鏈接數爲Redis進程能夠打開的最大文件描述符數,若是設置 maxclients 0,表示不做限制。當客戶端鏈接數到達限制時,Redis會關閉新的鏈接並向客戶端返回max number of clients reached錯誤信息
maxclients 128
\17. 指定Redis最大內存限制,Redis在啓動時會把數據加載到內存中,達到最大內存後,Redis會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大內存設置,將沒法再進行寫入操做,但仍然能夠進行讀取操做。Redis新的vm機制,會把Key存放內存,Value會存放在swap區
maxmemory <bytes>
\18. 指定是否在每次更新操做後進行日誌記錄,Redis在默認狀況下是異步的把數據寫入磁盤,若是不開啓,可能會在斷電時致使一段時間內的數據丟失。由於 redis自己同步數據文件是按上面save條件來同步的,因此有的數據會在一段時間內只存在於內存中。默認爲no
appendonly no
\19. 指定更新日誌文件名,默認爲appendonly.aof
appendfilename appendonly.aof
\20. 指定更新日誌條件,共有3個可選值: no:表示等操做系統進行數據緩存同步到磁盤(快) always:表示每次更新操做後手動調用fsync()將數據寫到磁盤(慢,安全) everysec:表示每秒同步一次(折衷,默認值)
appendfsync everysec
\21. 指定是否啓用虛擬內存機制,默認值爲no,簡單的介紹一下,VM機制將數據分頁存放,由Redis將訪問量較少的頁即冷數據swap到磁盤上,訪問多的頁面由磁盤自動換出到內存中(在後面的文章我會仔細分析Redis的VM機制)
vm-enabled no
\22. 虛擬內存文件路徑,默認值爲/tmp/redis.swap,不可多個Redis實例共享
vm-swap-file /tmp/redis.swap
\23. 將全部大於vm-max-memory的數據存入虛擬內存,不管vm-max-memory設置多小,全部索引數據都是內存存儲的(Redis的索引數據 就是keys),也就是說,當vm-max-memory設置爲0的時候,實際上是全部value都存在於磁盤。默認值爲0
vm-max-memory 0
\24. Redis swap文件分紅了不少的page,一個對象能夠保存在多個page上面,但一個page上不能被多個對象共享,vm-page-size是要根據存儲的 數據大小來設定的,做者建議若是存儲不少小對象,page大小最好設置爲32或者64bytes;若是存儲很大大對象,則可使用更大的page,若是不 肯定,就使用默認值
vm-page-size 32
\25. 設置swap文件中的page數量,因爲頁表(一種表示頁面空閒或使用的bitmap)是在放在內存中的,,在磁盤上每8個pages將消耗1byte的內存。
vm-pages 134217728
\26. 設置訪問swap文件的線程數,最好不要超過機器的核數,若是設置爲0,那麼全部對swap文件的操做都是串行的,可能會形成比較長時間的延遲。默認值爲4
vm-max-threads 4
\27. 設置在向客戶端應答時,是否把較小的包合併爲一個包發送,默認爲開啓
glueoutputbuf yes
\28. 指定在超過必定的數量或者最大的元素超過某一臨界值時,採用一種特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
\29. 指定是否激活重置哈希,默認爲開啓(後面在介紹Redis的哈希算法時具體介紹)
activerehashing yes
\30. 指定包含其它的配置文件,能夠在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有本身的特定配置文件
include /path/to/local.conf
string是redis最基本的類型,你能夠理解成與Memcached如出一轍的類型,一個key對應一個value。
string類型是二進制安全的。意思是redis的string能夠包含任何數據。好比jpg圖片或者序列化的對象 。
string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。
redis 127.0.0.1:6379> SET name "redis.net.cn"OKredis 127.0.0.1:6379> GET name"redis.net.cn"
在以上實例中咱們使用了 Redis 的 SET 和 GET 命令。鍵爲 name,對應的值爲redis.net.cn。
下表列出了經常使用的 redis 字符串命令:
序號 | 命令及描述 |
---|---|
1 | [SET key value] 設置指定 key 的值 |
2 | GET key 獲取指定 key 的值。 |
3 | GETRANGE key start end 返回 key 中字符串值的子字符 |
4 | GETSET key value 將給定 key 的值設爲 value ,並返回 key 的舊值(old value)。 |
5 | GETBIT key offset 對 key 所儲存的字符串值,獲取指定偏移量上的位(bit)。 |
6 | [MGET key1 key2..] 獲取全部(一個或多個)給定 key 的值。 |
7 | SETBIT key offset value 對 key 所儲存的字符串值,設置或清除指定偏移量上的位(bit)。 |
8 | SETEX key seconds value 將值 value 關聯到 key ,並將 key 的過時時間設爲 seconds (以秒爲單位)。 |
9 | SETNX key value 只有在 key 不存在時設置 key 的值。 |
10 | SETRANGE key offset value 用 value 參數覆寫給定 key 所儲存的字符串值,從偏移量 offset 開始。 |
11 | STRLEN key 返回 key 所儲存的字符串值的長度。 |
12 | [MSET key value key value ...] 同時設置一個或多個 key-value 對。 |
13 | [MSETNX key value key value ...] 同時設置一個或多個 key-value 對,當且僅當全部給定 key 都不存在。 |
14 | PSETEX key milliseconds value 這個命令和 SETEX 命令類似,但它以毫秒爲單位設置 key 的生存時間,而不是像 SETEX 命令那樣,以秒爲單位。 |
15 | INCR key 將 key 中儲存的數字值增一。 |
16 | INCRBY key increment 將 key 所儲存的值加上給定的增量值(increment) 。 |
17 | INCRBYFLOAT key increment 將 key 所儲存的值加上給定的浮點增量值(increment) 。 |
18 | DECR key 將 key 中儲存的數字值減一。 |
19 | DECRBY key decrement key 所儲存的值減去給定的減量值(decrement) 。 |
20 | APPEND key value 若是 key 已經存在而且是一個字符串, APPEND 命令將 value 追加到 key 原來的值的末尾。 |
Redis hash 是一個鍵值對集合。
Redis hash是一個string類型的field和value的映射表,hash特別適合用於存儲對象。
redis 127.0.0.1:6379> HMSET user:1 username redis.net.cn password redis.net.cn points 200OKredis 127.0.0.1:6379> HGETALL user:1
1) "username"
2) "redis.net.cn"
3) "password"
4) "redis.net.cn
"5) "points"
6) "200"redis
127.0.0.1:6379>
下表列出了列表相關的基本命令:
序號 | 命令及描述 |
---|---|
1 | [BLPOP key1 key2 ] timeout 移出並獲取列表的第一個元素, 若是列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。 |
2 | [BRPOP key1 key2 ] timeout 移出並獲取列表的最後一個元素, 若是列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。 |
3 | BRPOPLPUSH source destination timeout 從列表中彈出一個值,將彈出的元素插入到另一個列表中並返回它; 若是列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。 |
4 | LINDEX key index 經過索引獲取列表中的元素 |
5 | LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者後插入元素 |
6 | LLEN key 獲取列表長度 |
7 | LPOP key 移出並獲取列表的第一個元素 |
8 | [LPUSH key value1 value2] 將一個或多個值插入到列表頭部 |
9 | LPUSHX key value 將一個或多個值插入到已存在的列表頭部 |
10 | LRANGE key start stop 獲取列表指定範圍內的元素 |
11 | LREM key count value 移除列表元素 |
12 | LSET key index value 經過索引設置列表元素的值 |
13 | LTRIM key start stop 對一個列表進行修剪(trim),就是說,讓列表只保留指定區間內的元素,不在指定區間以內的元素都將被刪除。 |
14 | RPOP key 移除並獲取列表最後一個元素 |
15 | RPOPLPUSH source destination 移除列表的最後一個元素,並將該元素添加到另外一個列表並返回 |
16 | [RPUSH key value1 value2] 在列表中添加一個或多個值 |
17 | RPUSHX key value 爲已存在的列表添加值 |
下表列出了 redis hash 基本的相關命令:
序號 | 命令及描述 |
---|---|
1 | [HDEL key field2 field2] 刪除一個或多個哈希表字段 |
2 | HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。 |
3 | HGET key field 獲取存儲在哈希表中指定字段的值/td> |
4 | HGETALL key 獲取在哈希表中指定 key 的全部字段和值 |
5 | HINCRBY key field increment 爲哈希表 key 中的指定字段的整數值加上增量 increment 。 |
6 | HINCRBYFLOAT key field increment 爲哈希表 key 中的指定字段的浮點數值加上增量 increment 。 |
7 | HKEYS key 獲取全部哈希表中的字段 |
8 | HLEN key 獲取哈希表中字段的數量 |
9 | [HMGET key field1 field2] 獲取全部給定字段的值 |
10 | [HMSET key field1 value1 field2 value2 ] 同時將多個 field-value (域-值)對設置到哈希表 key 中。 |
11 | HSET key field value 將哈希表 key 中的字段 field 的值設爲 value 。 |
12 | HSETNX key field value 只有在字段 field 不存在時,設置哈希表字段的值。 |
13 | HVALS key 獲取哈希表中全部值 |
14 | HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的鍵值對。 |
Redis 列表是簡單的字符串列表,按照插入順序排序。你能夠添加一個元素導列表的頭部(左邊)或者尾部(右邊)。
redis 127.0.0.1:6379> lpush redis.net.cn redis (integer) 1 redis 127.0.0.1:6379> lpush redis.net.cn mongodb (integer) 2 redis 127.0.0.1:6379> lpush redis.net.cn rabitmq (integer) 3 redis 127.0.0.1:6379> lrange redis.net.cn 0 10 1) "rabitmq" 2) "mongodb" 3) "redis"redis 127.0.0.1:6379>
Redis的Set是string類型的無序集合。
集合是經過哈希表實現的,因此添加,刪除,查找的複雜度都是O(1)。
添加一個string元素到,key對應的set集合中,成功返回1,若是元素以及在集合中返回0,key對應的set不存在返回錯誤。
sadd key member
redis 127.0.0.1:6379> sadd redis.net.cn redis (integer) 1 redis 127.0.0.1:6379> sadd redis.net.cn mongodb (integer) 1 redis 127.0.0.1:6379> sadd redis.net.cn rabitmq (integer) 1 redis 127.0.0.1:6379> sadd redis.net.cn rabitmq (integer) 0 redis 127.0.0.1:6379> smembers redis.net.cn 1) "rabitmq" 2) "mongodb" 3) "redis"
注意:以上實例中 rabitmq 添加了兩次,但根據集合內元素的惟一性,第二次插入的元素將被忽略。
下表列出了 Redis 集合基本命令:
序號 | 命令及描述 |
---|---|
1 | [SADD key member1 member2] 向集合添加一個或多個成員 |
2 | SCARD key 獲取集合的成員數 |
3 | [SDIFF key1 key2] 返回給定全部集合的差集 |
4 | [SDIFFSTORE destination key1 key2] 返回給定全部集合的差集並存儲在 destination 中 |
5 | [SINTER key1 key2] 返回給定全部集合的交集 |
6 | [SINTERSTORE destination key1 key2] 返回給定全部集合的交集並存儲在 destination 中 |
7 | SISMEMBER key member 判斷 member 元素是不是集合 key 的成員 |
8 | [SMEMBERS key]返回集合中的全部成員 |
9 | SMOVE source destination member 將 member 元素從 source 集合移動到 destination 集合 |
10 | SPOP key 移除並返回集合中的一個隨機元素 |
11 | [SRANDMEMBER key count] 返回集合中一個或多個隨機數 |
12 | [SREM key member1 member2] 移除集合中一個或多個成員 |
13 | [SUNION key1 key2] 返回全部給定集合的並集 |
14 | [SUNIONSTORE destination key1 key2] 全部給定集合的並集存儲在 destination 集合中 |
15 | SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素 |
Redis zset 和 set 同樣也是string類型元素的集合,且不容許重複的成員。
不一樣的是每一個元素都會關聯一個double類型的分數。redis正是經過分數來爲集合中的成員進行從小到大的排序。
zset的成員是惟一的,但分數(score)卻能夠重複。
添加元素到集合,元素在集合中存在則更新對應score
zadd key score member
redis 127.0.0.1:6379> zadd redis.net.cn 0 redis (integer) 1 redis 127.0.0.1:6379> zadd redis.net.cn 0 mongodb (integer) 1 redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq (integer) 1 redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq (integer) 0 redis 127.0.0.1:6379> ZRANGEBYSCORE redis.net.cn 0 1000 1) "redis" 2) "mongodb" 3) "rabitmq"
下表列出了 redis 有序集合的基本命令:
序號 | 命令及描述 |
---|---|
1 | [ZADD key score1 member1 score2 member2] 向有序集合添加一個或多個成員,或者更新已存在成員的分數 |
2 | ZCARD key 獲取有序集合的成員數 |
3 | ZCOUNT key min max 計算在有序集合中指定區間分數的成員數 |
4 | ZINCRBY key increment member 有序集合中對指定成員的分數加上增量 increment |
5 | [ZINTERSTORE destination numkeys key key ...] 計算給定的一個或多個有序集的交集並將結果集存儲在新的有序集合 key 中 |
6 | ZLEXCOUNT key min max 在有序集合中計算指定字典區間內成員數量 |
7 | [ZRANGE key start stop WITHSCORES] 經過索引區間返回有序集合成指定區間內的成員 |
8 | [ZRANGEBYLEX key min max LIMIT offset count] 經過字典區間返回有序集合的成員 |
9 | ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 經過分數返回有序集合指定區間內的成員 |
10 | ZRANK key member 返回有序集合中指定成員的索引 |
11 | [ZREM key member member ...] 移除有序集合中的一個或多個成員 |
12 | ZREMRANGEBYLEX key min max 移除有序集合中給定的字典區間的全部成員 |
13 | ZREMRANGEBYRANK key start stop 移除有序集合中給定的排名區間的全部成員 |
14 | ZREMRANGEBYSCORE key min max 移除有序集合中給定的分數區間的全部成員 |
15 | [ZREVRANGE key start stop WITHSCORES] 返回有序集中指定區間內的成員,經過索引,分數從高到底 |
16 | [ZREVRANGEBYSCORE key max min WITHSCORES] 返回有序集中指定分數區間內的成員,分數從高到低排序 |
17 | ZREVRANK key member 返回有序集合中指定成員的排名,有序集成員按分數值遞減(從大到小)排序 |
18 | ZSCORE key member 返回有序集中,成員的分數值 |
19 | [ZUNIONSTORE destination numkeys key key ...] 計算給定的一個或多個有序集的並集,並存儲在新的 key 中 |
20 | ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成員和元素分值) |
Redis 命令用於在 redis 服務上執行操做。
要在 redis 服務上執行命令須要一個 redis 客戶端。Redis 客戶端在咱們以前下載的的 redis 的安裝包中。
Redis 客戶端的基本語法爲:
$ redis-cli
如下實例講解了如何啓動 redis 客戶端:
啓動 redis 客戶端,打開終端並輸入命令 redis-cli。該命令會鏈接本地的 redis 服務。
$redis-cliredis 127.0.0.1:6379>redis 127.0.0.1:6379> PING PONG
在以上實例中咱們鏈接到本地的 redis 服務並執行 PING 命令,該命令用於檢測 redis 服務是否啓動。
若是須要在遠程 redis 服務上執行命令,一樣咱們使用的也是 redis-cli 命令。
$ redis-cli -h host -p port -a password
如下實例演示瞭如何鏈接到主機爲 127.0.0.1,端口爲 6379 ,密碼爲 mypass 的 redis 服務上。
$redis-cli -h 127.0.0.1 -p 6379 -a "mypass" redis 127.0.0.1:6379> redis 127.0.0.1:6379> PING PONG
下表給出了與 Redis 鍵相關的基本命令:
序號 | 命令及描述 |
---|---|
1 | DEL key 該命令用於在 key 存在是刪除 key。 |
2 | DUMP key 序列化給定 key ,並返回被序列化的值。 |
3 | EXISTS key 檢查給定 key 是否存在。 |
4 | EXPIRE key seconds 爲給定 key 設置過時時間。 |
5 | EXPIREAT key timestamp EXPIREAT 的做用和 EXPIRE 相似,都用於爲 key 設置過時時間。 不一樣在於 EXPIREAT 命令接受的時間參數是 UNIX 時間戳(unix timestamp)。 |
6 | PEXPIRE key milliseconds 設置 key 的過時時間億以毫秒計。 |
7 | PEXPIREAT key milliseconds-timestamp 設置 key 過時時間的時間戳(unix timestamp) 以毫秒計 |
8 | KEYS pattern 查找全部符合給定模式( pattern)的 key 。 |
9 | MOVE key db 將當前數據庫的 key 移動到給定的數據庫 db 當中。 |
10 | PERSIST key 移除 key 的過時時間,key 將持久保持。 |
11 | PTTL key 以毫秒爲單位返回 key 的剩餘的過時時間。 |
12 | TTL key 以秒爲單位,返回給定 key 的剩餘生存時間(TTL, time to live)。 |
13 | RANDOMKEY 從當前數據庫中隨機返回一個 key 。 |
14 | RENAME key newkey 修改 key 的名稱 |
15 | RENAMENX key newkey 僅當 newkey 不存在時,將 key 更名爲 newkey 。 |
16 | TYPE key 返回 key 所儲存的值的類型。 |
Redis 在 2.8.9 版本添加了 HyperLogLog 結構。
Redis HyperLogLog 是用來作基數統計的算法,HyperLogLog 的優勢是,在輸入元素的數量或者體積很是很是大時,計算基數所需的空間老是固定 的、而且是很小的。
在 Redis 裏面,每一個 HyperLogLog 鍵只須要花費 12 KB 內存,就能夠計算接近 2^64 個不一樣元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合造成鮮明對比。
可是,由於 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素自己,因此 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
好比數據集 {1, 3, 5, 7, 5, 7, 8}, 那麼這個數據集的基數集爲 {1, 3, 5 ,7, 8}, 基數(不重複元素)爲5。 基數估計就是在偏差可接受的範圍內,快速計算基數。
如下實例演示了 HyperLogLog 的工做過程:
redis 127.0.0.1:6379> PFADD w3ckey "redis" 1) (integer) 1 redis 127.0.0.1:6379> PFADD w3ckey "mongodb" 1) (integer) 1 redis 127.0.0.1:6379> PFADD w3ckey "mysql" 1) (integer) 1 redis 127.0.0.1:6379> PFCOUNT w3ckey (integer) 3
下表列出了 redis HyperLogLog 的基本命令:
序號 | 命令及描述 |
---|---|
1 | [PFADD key element element ...] 添加指定元素到 HyperLogLog 中。 |
2 | [PFCOUNT key key ...] 返回給定 HyperLogLog 的基數估算值。 |
3 | [PFMERGE destkey sourcekey sourcekey ...] 將多個 HyperLogLog 合併爲一個 HyperLogLog |
Redis 發佈訂閱(pub/sub)是一種消息通訊模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
Redis 客戶端能夠訂閱任意數量的頻道。
下圖展現了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:
當有新消息經過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:
如下實例演示了發佈訂閱是如何工做的。在咱們實例中咱們建立了訂閱頻道名爲 redisChat:
redis 127.0.0.1:6379> SUBSCRIBE redisChat Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1
如今,咱們先從新開啓個 redis 客戶端,而後在同一個頻道 redisChat 發佈兩次消息,訂閱者就能接收到消息。
redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique" (integer) 1 redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by w3cschool.cc" (integer) 1 # 訂閱者的客戶端會顯示以下消息 1) "message" 2) "redisChat" 3) "Redis is a great caching technique" 1) "message" 2) "redisChat" 3) "Learn redis by w3cschool.cc"
下表列出了 redis 發佈訂閱經常使用命令:
序號 | 命令及描述 |
---|---|
1 | [PSUBSCRIBE pattern [pattern ...]]訂閱一個或多個符合給定模式的頻道。 |
2 | [PUBSUB subcommand [argument [argument ...]]]查看訂閱與發佈系統狀態。 |
3 | [PUBLISH channel message]將信息發送到指定的頻道。 |
4 | [PUNSUBSCRIBE [pattern [pattern ...]]]退訂全部給定模式的頻道。 |
5 | [SUBSCRIBE channel [channel ...]]訂閱給定的一個或多個頻道的信息。 |
6 | [UNSUBSCRIBE [channel [channel ...]]]指退訂給定的頻道。 |
Redis 事務能夠一次執行多個命令, 而且帶有如下兩個重要的保證:
事務是一個單獨的隔離操做:事務中的全部命令都會序列化、按順序地執行。事務在執行的過程當中,不會被其餘客戶端發送來的命令請求所打斷。
事務是一個原子操做:事務中的命令要麼所有被執行,要麼所有都不執行。
一個事務從開始到執行會經歷如下三個階段:
開始事務。
命令入隊。
執行事務。
如下是一個事務的例子, 它先以 MULTI 開始一個事務, 而後將多個命令入隊到事務中, 最後由 EXEC 命令觸發事務, 一併執行事務中的全部命令:
redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days" QUEUED redis 127.0.0.1:6379> GET book-name QUEUED redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series" QUEUED redis 127.0.0.1:6379> SMEMBERS tag QUEUED redis 127.0.0.1:6379> EXEC 1) OK 2) "Mastering C++ in 21 days" 3) (integer) 3 4) 1) "Mastering Series" 2) "C++" 3) "Programming"
下表列出了 redis 事務的相關命令:
序號 | 命令及描述 |
---|---|
1 | DISCARD 取消事務,放棄執行事務塊內的全部命令。 |
2 | EXEC 執行全部事務塊內的命令。 |
3 | MULTI 標記一個事務塊的開始。 |
4 | UNWATCH 取消 WATCH 命令對全部 key 的監視。 |
5 | [WATCH key key ...] 監視一個(或多個) key ,若是在事務執行以前這個(或這些) key 被其餘命令所改動,那麼事務將被打斷。 |
Redis 腳本使用 Lua 解釋器來執行腳本。 Reids 2.6 版本經過內嵌支持 Lua 環境。執行腳本的經常使用命令爲 EVAL。
Eval 命令的基本語法以下:
redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
如下實例演示了 redis 腳本工做過程:
redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
下表列出了 redis 腳本經常使用命令:
序號 | 命令及描 |
---|---|
1 | EVAL script numkeys key [key ...] arg [arg ...] 執行 Lua 腳本。 |
2 | [EVALSHA sha1 numkeys key [key ...] arg [arg ...]] 執行 Lua 腳本。 |
3 | [SCRIPT EXISTS script script ...] 查看指定的腳本是否已經被保存在緩存當中。 |
4 | SCRIPT FLUSH 從腳本緩存中移除全部腳本。 |
5 | SCRIPT KILL 殺死當前正在運行的 Lua 腳本。 |
6 | SCRIPT LOAD script 將腳本 script 添加到腳本緩存中,但並不當即執行這個腳本。 |
Redis 鏈接命令主要是用於鏈接 redis 服務。
如下實例演示了客戶端如何經過密碼驗證鏈接到 redis 服務,並檢測服務是否在運行:
redis 127.0.0.1:6379> AUTH "password" OK redis 127.0.0.1:6379> PING PONG
下表列出了 redis 鏈接的基本命令:
序號 | 命令及描述 |
---|---|
1 | AUTH password 驗證密碼是否正確 |
2 | ECHO message 打印字符串 |
3 | PING 查看服務是否運行 |
4 | QUIT 關閉當前鏈接 |
5 | SELECT index 切換到指定的數據庫 |
Redis 服務器命令主要是用於管理 redis 服務。
如下實例演示瞭如何獲取 redis 服務器的統計信息:
redis 127.0.0.1:6379> INFO # Server redis_version:2.8.13 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:c2238b38b1edb0e2 redis_mode:standalone os:Linux 3.5.0-48-generic x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.7.2 process_id:3856 run_id:0e61abd297771de3fe812a3c21027732ac9f41fe tcp_port:6379 uptime_in_seconds:11554 uptime_in_days:0 hz:10 lru_clock:16651447 config_file: # Clients connected_clients:1 client-longest_output_list:0 client-biggest_input_buf:0 blocked_clients:0 # Memory used_memory:589016 used_memory_human:575.21K used_memory_rss:2461696 used_memory_peak:667312 used_memory_peak_human:651.67K used_memory_lua:33792 mem_fragmentation_ratio:4.18 mem_allocator:jemalloc-3.6.0 # Persistence loading:0 rdb_changes_since_last_save:3 rdb_bgsave_in_progress:0 rdb_last_save_time:1409158561 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok # Stats total_connections_received:24 total_commands_processed:294 instantaneous_ops_per_sec:0 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:41 keyspace_misses:82 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:264 # Replication role:master connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 # CPU used_cpu_sys:10.49 used_cpu_user:4.96 used_cpu_sys_children:0.00 used_cpu_user_children:0.01 # Keyspace db0:keys=94,expires=1,avg_ttl=41638810 db1:keys=1,expires=0,avg_ttl=0 db3:keys=1,expires=0,avg_ttl=0
下表列出了 redis 服務器的相關命令:
序號 | 命令及描述 |
---|---|
1 | BGREWRITEAOF 異步執行一個 AOF(AppendOnly File) 文件重寫操做 |
2 | BGSAVE 在後臺異步保存當前數據庫的數據到磁盤 |
3 | CLIENT KILL [ip:port] [ID client-id] 關閉客戶端鏈接 |
4 | CLIENT LIST 獲取鏈接到服務器的客戶端鏈接列表 |
5 | CLIENT GETNAME 獲取鏈接的名稱 |
6 | CLIENT PAUSE timeout 在指定時間內終止運行來自客戶端的命令 |
7 | CLIENT SETNAME connection-name 設置當前鏈接的名稱 |
8 | CLUSTER SLOTS 獲取集羣節點的映射數組 |
9 | COMMAND 獲取 Redis 命令詳情數組 |
10 | COMMAND COUNT 獲取 Redis 命令總數 |
11 | COMMAND GETKEYS 獲取給定命令的全部鍵 |
12 | TIME 返回當前服務器時間 |
13 | [COMMAND INFO command-name command-name ...] 獲取指定 Redis 命令描述的數組 |
14 | CONFIG GET parameter 獲取指定配置參數的值 |
15 | CONFIG REWRITE 對啓動 Redis 服務器時所指定的 redis.conf 配置文件進行改寫 |
16 | CONFIG SET parameter value 修改 redis 配置參數,無需重啓 |
17 | CONFIG RESETSTAT 重置 INFO 命令中的某些統計數據 |
18 | DBSIZE 返回當前數據庫的 key 的數量 |
19 | DEBUG OBJECT key 獲取 key 的調試信息 |
20 | DEBUG SEGFAULT 讓 Redis 服務崩潰 |
21 | FLUSHALL 刪除全部數據庫的全部key |
22 | FLUSHDB 刪除當前數據庫的全部key |
23 | [INFO section] 獲取 Redis 服務器的各類信息和統計數值 |
24 | LASTSAVE 返回最近一次 Redis 成功將數據保存到磁盤上的時間,以 UNIX 時間戳格式表示 |
25 | MONITOR 實時打印出 Redis 服務器接收到的命令,調試用 |
26 | ROLE 返回主從實例所屬的角色 |
27 | SAVE 異步保存數據到硬盤 |
28 | SHUTDOWN [NOSAVE] [SAVE] 異步保存數據到硬盤,並關閉服務器 |
29 | SLAVEOF host port 將當前服務器轉變爲指定服務器的從屬服務器(slave server) |
30 | [SLOWLOG subcommand argument] 管理 redis 的慢日誌 |
31 | SYNC 用於複製功能(replication)的內部命令 |
Redis SAVE 命令用於建立當前數據庫的備份。
redis Save 命令基本語法以下:
redis 127.0.0.1:6379> SAVE
redis 127.0.0.1:6379> SAVE OK
該命令將在 redis 安裝目錄中建立dump.rdb文件。
若是須要恢復數據,只需將備份文件 (dump.rdb) 移動到 redis 安裝目錄並啓動服務便可。獲取 redis 目錄可使用
CONFIG
命令,以下所示:
redis 127.0.0.1:6379> CONFIG GET dir 1) "dir" 2) "/usr/local/redis/bin"
以上命令 CONFIG GET dir 輸出的 redis 安裝目錄爲 /usr/local/redis/bin。
建立 redis 備份文件也可使用命令 BGSAVE,該命令在後臺執行。
127.0.0.1:6379> BGSAVE Background saving started
咱們能夠經過 redis 的配置文件設置密碼參數,這樣客戶端鏈接到 redis 服務就須要密碼驗證,這樣可讓你的 redis 服務更安全。
咱們能夠經過如下命令查看是否設置了密碼驗證:
127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) ""
默認狀況下 requirepass 參數是空的,這就意味着你無需經過密碼驗證就能夠鏈接到 redis 服務。
你能夠經過如下命令來修改該參數:
127.0.0.1:6379> CONFIG set requirepass "w3cschool.cc" OK 127.0.0.1:6379> CONFIG get requirepass 1) "requirepass" 2) "w3cschool.cc"
設置密碼後,客戶端鏈接 redis 服務就須要密碼驗證,不然沒法執行命令。
AUTH 命令基本語法格式以下:
127.0.0.1:6379> AUTH password
127.0.0.1:6379> AUTH "w3cschool.cc" OK 127.0.0.1:6379> SET mykey "Test value" OK 127.0.0.1:6379> GET mykey "Test value"
Redis 性能測試是經過同時執行多個命令實現的。
redis 性能測試的基本命令以下:
redis-benchmark [option] [option value]
如下實例同時執行 10000 個請求來檢測性能:
redis-benchmark -n 100000 PING_INLINE: 141043.72 requests per second PING_BULK: 142857.14 requests per second SET: 141442.72 requests per second GET: 145348.83 requests per second INCR: 137362.64 requests per second LPUSH: 145348.83 requests per second LPOP: 146198.83 requests per second SADD: 146198.83 requests per second SPOP: 149253.73 requests per second LPUSH (needed to benchmark LRANGE): 148588.42 requests per second LRANGE_100 (first 100 elements): 58411.21 requests per second LRANGE_300 (first 300 elements): 21195.42 requests per second LRANGE_500 (first 450 elements): 14539.11 requests per second LRANGE_600 (first 600 elements): 10504.20 requests per second MSET (10 keys): 93283.58 requests per second
redis 性能測試工具可選參數以下所示:
序號 | 選項 | 描述 | 默認值 |
---|---|---|---|
1 | -h | 指定服務器主機名 | 127.0.0.1 |
2 | -p | 指定服務器端口 | 6379 |
3 | -s | 指定服務器 socket | |
4 | -c | 指定併發鏈接數 | 50 |
5 | -n | 指定請求數 | 10000 |
6 | -d | 以字節的形式指定 SET/GET 值的數據大小 | 2 |
7 | -k | 1=keep alive 0=reconnect | 1 |
8 | -r | SET/GET/INCR 使用隨機 key, SADD 使用隨機值 | |
9 | -P | 經過管道傳輸 <numreq> 請求 |
1 |
10 | -q | 強制退出 redis。僅顯示 query/sec 值 | |
11 | --csv | 以 CSV 格式輸出 | |
12 | -l | 生成循環,永久執行測試 | |
13 | -t | 僅運行以逗號分隔的測試命令列表。 | |
14 | -I | Idle 模式。僅打開 N 個 idle 鏈接並等待。 |
如下實例咱們使用了多個參數來測試 redis 性能:
redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 100000 -q SET: 146198.83 requests per second LPUSH: 145560.41 requests per second
以上實例中主機爲 127.0.0.1,端口號爲 6379,執行的命令爲 set,lpush,請求數爲 10000,經過 -q 參數讓結果只顯示每秒執行的請求數。
Redis 經過監聽一個 TCP 端口或者 Unix socket 的方式來接收來自客戶端的鏈接,當一個鏈接創建後,Redis 內部會進行如下一些操做:
首先,客戶端 socket 會被設置爲非阻塞模式,由於 Redis 在網絡事件處理上採用的是非阻塞多路複用模型。
而後爲這個 socket 設置 TCP_NODELAY 屬性,禁用 Nagle 算法
而後建立一個可讀的文件事件用於監聽這個客戶端 socket 的數據發送
在 Redis2.4 中,最大鏈接數是被直接硬編碼在代碼裏面的,而在2.6版本中這個值變成可配置的。
maxclients 的默認值是 10000,你也能夠在 redis.conf 中對這個值進行修改。
config get maxclients 1) "maxclients" 2) "10000"
如下實例咱們在服務啓動時設置最大鏈接數爲 100000:
redis-server --maxclients 100000
S.N. | 命令 | 描述 |
---|---|---|
1 | CLIENT LIST | 返回鏈接到 redis 服務的客戶端列表 |
2 | CLIENT SETNAME | 設置當前鏈接的名稱 |
3 | CLIENT GETNAME | 獲取經過 CLIENT SETNAME 命令設置的服務名稱 |
4 | CLIENT PAUSE | 掛起客戶端鏈接,指定掛起的時間以毫秒計 |
5 | CLIENT KILL | 關閉客戶端鏈接 |
Redis是一種基於客戶端-服務端模型以及請求/響應協議的TCP服務。這意味着一般狀況下一個請求會遵循如下步驟:
客戶端向服務端發送一個查詢請求,並監聽Socket返回,一般是以阻塞模式,等待服務端響應。
服務端處理命令,並將結果返回給客戶端。
Redis 管道技術能夠在服務端未響應時,客戶端能夠繼續向服務端發送請求,並最終一次性讀取全部服務端的響應。
查看 redis 管道,只須要啓動 redis 實例並輸入如下命令:
$(echo -en "PING\r\n SET w3ckey redis\r\nGET w3ckey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379 +PONG +OK redis :1 :2 :3:2:3
以上實例中咱們經過使用 PING 命令查看redis服務是否可用, 以後咱們們設置了 w3ckey 的值爲 redis,而後咱們獲取 w3ckey 的值並使得 visitor 自增 3 次。
在返回的結果中咱們能夠看到這些命令一次性向 redis 服務提交,並最終一次性讀取全部服務端的響應
管道技術最顯著的優點是提升了 redis 服務的性能。
在下面的測試中,咱們將使用Redis的Ruby客戶端,支持管道技術特性,測試管道技術對速度的提高效果。
require 'rubygems' require 'redis' def bench(descr) start = Time.now yield puts "#{descr} #{Time.now-start} seconds" end def without_pipelining r = Redis.new 10000.times { r.ping } end def with_pipelining r = Redis.new r.pipelined { 10000.times { r.ping } } end bench("without pipelining") { without_pipelining } bench("with pipelining") { with_pipelining }
從處於局域網中的Mac OS X系統上執行上面這個簡單腳本的數據代表,開啓了管道操做後,往返時延已經被改善得至關低了。
without pipelining 1.185238 seconds with pipelining 0.250783 seconds
如你所見,開啓管道後,咱們的速度效率提高了5倍。
分區是分割數據到多個Redis實例的處理過程,所以每一個實例只保存key的一個子集。
經過利用多臺計算機內存的和值,容許咱們構造更大的數據庫。
經過多核和多臺計算機,容許咱們擴展計算能力;經過多臺計算機和網絡適配器,容許咱們擴展網絡帶寬。
redis的一些特性在分區方面表現的不是很好:
涉及多個key的操做一般是不被支持的。舉例來講,當兩個set映射到不一樣的redis實例上時,你就不能對這兩個set執行交集操做。
涉及多個key的redis事務不能使用。
當使用分區時,數據處理較爲複雜,好比你須要處理多個rdb/aof文件,而且從多個實例和主機備份持久化文件。
增長或刪除容量也比較複雜。redis集羣大多數支持在運行時增長、刪除節點的透明數據平衡的能力,可是相似於客戶端分區、代理等其餘系統則不支持這項特性。然而,一種叫作presharding的技術對此是有幫助的。
Redis 有兩種類型分區。 假設有4個Redis實例 R0,R1,R2,R3,和相似user:1,user:2這樣的表示用戶的多個key,對既定的key有多種不一樣方式來選擇這個key存放在哪一個實例中。也就是說,有不一樣的系統來映射某個key到某個Redis服務。
最簡單的分區方式是按範圍分區,就是映射必定範圍的對象到特定的Redis實例。
好比,ID從0到10000的用戶會保存到實例R0,ID從10001到 20000的用戶會保存到R1,以此類推。
這種方式是可行的,而且在實際中使用,不足就是要有一個區間範圍到實例的映射表。這個表要被管理,同時還須要各 種對象的映射表,一般對Redis來講並不是是好的方法。
另一種分區方法是hash分區。這對任何key都適用,也無需是object_name:這種形式,像下面描述的同樣簡單:
用一個hash函數將key轉換爲一個數字,好比使用crc32 hash函數。對key foobar執行crc32(foobar)會輸出相似93024922的整數。
對這個整數取模,將其轉化爲0-3之間的數字,就能夠將這個整數映射到4個Redis實例中的一個了。93024922 % 4 = 2,就是說key foobar應該被存到R2實例中。注意:取模操做是取除的餘數,一般在多種編程語言中用%操做符實現。
開始在 Java 中使用 Redis 前, 咱們須要確保已經安裝了 redis 服務及 Java redis 驅動,且你的機器上能正常使用 Java。 Java的安裝配置能夠參考咱們的 Java開發環境配置 接下來讓咱們安裝 Java redis 驅動:
首先你須要下載驅動包,下載 jedis.jar,確保下載最新驅動包。
在你的classpath中包含該驅動包。
import redis.clients.jedis.Jedis;
public class RedisJava {
public static void main(String[] args) {
//鏈接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//查看服務是否運行
System.out.println("Server is running: "+jedis.ping());
}
}
編譯以上 Java 程序,確保驅動包的路徑是正確的。
$javac RedisJava.java
$java RedisJava
Connection to server sucessfully
Server is running: PONG
Redis Java String Example
import redis.clients.jedis.Jedis;
public class RedisStringJava {
public static void main(String[] args) {
//鏈接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//設置 redis 字符串數據
jedis.set("w3ckey", "Redis tutorial");
// 獲取存儲的數據並輸出
System.out.println("Stored string in redis:: "+ jedis.get("w3ckey"));
}
}
編譯以上程序。
$javac RedisStringJava.java
$java RedisStringJava
Connection to server sucessfully
Stored string in redis:: Redis tutorial
import redis.clients.jedis.Jedis;
public class RedisListJava {
public static void main(String[] args) {
//鏈接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//存儲數據到列表中
jedis.lpush("tutorial-list", "Redis");
jedis.lpush("tutorial-list", "Mongodb");
jedis.lpush("tutorial-list", "Mysql");
// 獲取存儲的數據並輸出
List<String> list = jedis.lrange("tutorial-list", 0 ,5);
for(int i=0; i<list.size(); i++) {
System.out.println("Stored string in redis:: "+list.get(i));
}
}
}
編譯以上程序。
$javac RedisListJava.java
$java RedisListJava
Connection to server sucessfully
Stored string in redis:: Redis
Stored string in redis:: Mongodb
Stored string in redis:: Mysql
import redis.clients.jedis.Jedis;
public class RedisKeyJava {
public static void main(String[] args) {
//鏈接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
// 獲取數據並輸出
List<String> list = jedis.keys("*");
for(int i=0; i<list.size(); i++) {
System.out.println("List of stored keys:: "+list.get(i));
}
}
}
$javac RedisKeyJava.java
$java RedisKeyJava
Connection to server sucessfully
List of stored keys:: tutorial-name
List of stored keys:: tutorial-list