Redis備案
http://www.runoob.com/redis/redis-conf.html
redis是一個key-value存儲系統, 數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的, 為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。
數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹復制。從盤可以有意無意的對數據進行寫操作。由于完全實現了發布/訂閱機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道并接收主服務器完整的消息發布記錄。
安裝:
Mac
brew install redis
redis-server /usr/local/etc/redis.conf
redis-cli
Linux
http://redis.io/download
$ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
$ tar xzf redis-2.8.17.tar.gz
$ cd redis-2.8.17
$ make
$ cd src
$ ./redis-server
$ ./redis-server redis.conf
$ cd src
$ ./redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
連接:
Redis 連接命令
下表列出了 redis 連接的基本命令:
序號 | 命令 | 描述
--- | --- | ————-
1 | AUTH password | 驗證密碼是否正確
2 | ECHO message | 打印字符串
3 | PING | 查看服務是否運行
4 | QUIT | 關閉當前連接
5 | SELECT | index |切換到指定的數據庫
栗子:
Redis Select 命令用于切換到指定的數據庫,數據庫索引號 index 用數字值指定,以 0 作為起始索引值。
SET db_number 0 # 默認使用 0 號數據庫
SELECT 1 # 使用 1 號數據庫
[1]> GET db_number
[1]> SET db_number 1
[1]> GET db_number
[1]> SELECT 3 # 再切換到 3 號數據庫
[3]> # 提示符從 [1] 改變成了 [3]
服務器
http://www.runoob.com/redis/redis-server.html
INFO 獲取 Redis 服務器的各種信息和統計數值
Save 命令執行一個同步保存操作,將當前 Redis 實例的所有數據快照(snapshot)以 RDB 文件的形式保存到硬盤。 該命令將在 redis 安裝目錄中創建dump.rdb文件。
如果需要恢復數據,只需將備份文件 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可
Flushdb 命令用于清空當前數據庫中的所有 key。
FLUSHALL 刪除所有數據庫的所有key
DBSIZE 返回當前數據庫的 key 的數量
CONFIG RESETSTAT 重置 INFO 命令中的某些統計數據
CONFIG SET parameter value 修改 redis 配置參數,無需重啟
CONFIG GET parameter 獲取指定配置參數的值
TIME 返回當前服務器時間
CLIENT KILL [ip:port] [ID client-id]
Client List 命令用于返回所有連接到服務器的客戶端信息和統計數據。
Client Getname 命令用于返回 CLIENT SETNAME 命令為連接設置的名字。 因為新創建的連接默認是沒有名字的, 對于沒有名字的連接, CLIENT GETNAME 返回空白回復。
CLIENT SETNAME hello-world-connection
BGSAVE 命令執行之后立即返回 OK ,然后 Redis fork 出一個新子進程,原來的 Redis 進程(父進程)繼續處理客戶端請求,而子進程則負責將數據保存到磁盤,然后退出。
安全
CONFIG get requirepass
CONFIG set requirepass "runoob"
CONFIG get requirepass
requirepass是一個 HASH類型
登錄驗證密碼:
AUTH "runoob"
性能測試
http://www.runoob.com/redis/redis-benchmarks.html
redis-benchmark
Redis 分區
分區是分割數據到多個Redis實例的處理過程,因此每個實例只保存key的一個子集。
分區的優勢
- 通過利用多臺計算機內存的和值,允許我們構造更大的數據庫。
- 通過多核和多臺計算機,允許我們擴展計算能力;通過多臺計算機和網絡適配器,允許我們擴展網絡帶寬。
配置:
CONFIG GET CONFIG_SETTING_NAME
CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
CONFIG GET loglevel
CONFIG SET loglevel "notice"
CONFIG GET dir 輸出的 redis 安裝目錄
config get maxclients 最大連接數 maxclients 的默認值是 10000
redis-server --maxclients 100000 也可以啟動時設定, 也可以啟動后config get maxclients 100000
CONFIG GET *
說明:
參數說明
redis.conf 配置項說明如下:
http://www.runoob.com/redis/redis-conf.html
參數說明
redis.conf 配置項說明如下:
-
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
5.當 客戶端閑置多長時間后關閉連接,如果指定為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支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
http://www.runoob.com/redis/redis-data-types.html
String
string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。
string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。
SET name "runoob"
GET name
Hash(哈希)
Redis hash 是一個鍵值(key=>value)對集合。
Redis hash是一個string類型的field和value的映射表,hash特別適合用于存儲對象。
HMSET myhash field1 "Hello" field2 "World"
HGET myhash field1
HGET myhash field2
每個 hash 可以存儲 232 -1 鍵值對(40多億)。
List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。
lpush runoob redis
lrange runoob 0 10
列表最多可存儲 232 - 1 元素 (4294967295, 每個列表可存儲40多億)。
Set(集合)
Redis的Set是string類型的無序集合。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
添加一個 string 元素到 key 對應的 set 集合中,成功返回1,如果元素已經在集合中返回 0,如果 key 對應的 set 不存在則返回錯誤。 返回 1, 0
sadd key member
smembers runoob
集合中最大的成員數為 232 - 1(4294967295, 每個集合可存儲40多億個成員)。
zset(sorted set:有序集合)
edis zset 和 set 一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
zset的成員是唯一的,但分數(score)卻可以重復。
zadd runoob 0 redis
zadd runoob 0 rabitmq
ZRANGEBYSCORE runoob 0 1000
命令
登錄
本地:
$redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING
PONG
遠程
$ redis-cli -h host -p port -a password
鍵(key)
http://www.runoob.com/redis/redis-keys.html
Redis 鍵命令用于管理 redis 的鍵。
DEL key
EXISTS key 命令用于檢查給定 key 是否存在。 返回 1, 0
EXPIRE key seconds為給定 key 設置過期時間。
RENAME key newkey 修改 key 的名稱
TYPE key 返回 key 所儲存的值的類型。
KEYS w3c*
字符串(String)
http://www.runoob.com/redis/redis-strings.html
哈希(Hash)
http://www.runoob.com/redis/redis-hashes.html
HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
HGETALL runoobkey
下表列出了 redis hash 基本的相關命令:
序號 | 命令 | 描述 |
---|---|---|
1 | HDEL key field1 [field2] | 刪除一個或多個哈希表字段 |
2 | HEXISTS key field | 查看哈希表 key 中,指定的字段是否存在。 |
3 | HGET key field | 獲取存儲在哈希表中指定字段的值。 |
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] | 迭代哈希表中的鍵值對。 |
更多命令請參考:https://redis.io/commands
列表(List)
http://www.runoob.com/redis/redis-lists.html
集合(Set)
Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這就意味著集合中不能出現重復的數據。
Redis 中集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是 O(1)。
Redis 集合命令
下表列出了 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] | 迭代集合中的元素 |
有序集合(sorted set)
http://www.runoob.com/redis/redis-sorted-sets.html
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重復。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)
事務
http://www.runoob.com/redis/redis-transactions.html
Redis 事務可以一次執行多個命令, 并且帶有以下兩個重要的保證:
批量操作在發送 EXEC 命令前被放入隊列緩存。
收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行。
在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
這樣保證多進程共享變量
一個事務從開始到執行會經歷以下三個階段:
開始事務。 multi
命令入隊。
執行事務。 exec
注意:
單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行并不是原子性的。
事務可以理解為一個打包的批量執行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成后續的指令不做。
Redis 發布訂閱
Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。 消息推送 而非拉取, 這個可以用于召回的peer數據的推送, peer的新狀態 推送給每個關聯用戶,
Redis 客戶端可以訂閱任意數量的頻道。
http://www.runoob.com/redis/redis-pub-sub.html
SUBSCRIBE redisChat
SUBSCRIBE channel [channel ...] 命令用于訂閱給定的一個或多個頻道的信息
PUBLISH redisChat "Redis is a great caching technique"
PUBLISH redisChat "Learn redis by runoob.com"
UNSUBSCRIBE channel [channel ...] 命令用于退訂給定的一個或多個頻道的信息。
redis 管道技術
管道技術最顯著的優勢是提高了 redis 服務的性能。
redis每執行一條指令都是連接 斷開
Redis是一種基于客戶端-服務端模型以及請求/響應協議的TCP服務。這意味著通常情況下一個請求會遵循以下步驟:
客戶端向服務端發送一個查詢請求,并監聽Socket返回,通常是以阻塞模式,等待服務端響應。
服務端處理命令,并將結果返回給客戶端。
實例:
$(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379
+PONG
+OK
redis
:1
:2
:3
以上實例中我們通過使用 PING 命令查看redis服務是否可用, 之后我們設置了 runoobkey 的值為 redis,然后我們獲取 runoobkey 的值并使得 visitor 自增 3 次。
在返回的結果中我們可以看到這些命令一次性向 redis 服務提交,并最終一次性讀取所有服務端的響應
redis使用
java
jedis.jar
import redis.clients.jedis.Jedis;
public class RedisJava {
public static void main(String[] args) {
//連接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
//查看服務是否運行
System.out.println("服務正在運行: "+jedis.ping());
//設置 redis 字符串數據
jedis.set("runoobkey", "www.runoob.com");
// 獲取存儲的數據并輸出
System.out.println("redis 存儲的字符串為: "+ jedis.get("runoobkey"));
//存儲數據到列表中
jedis.lpush("site-list", "Runoob");
jedis.lpush("site-list", "Google");
jedis.lpush("site-list", "Taobao");
// 獲取存儲的數據并輸出
List<String> list = jedis.lrange("site-list", 0 ,2);
for(int i=0; i<list.size(); i++) {
System.out.println("列表項為: "+list.get(i));
// 獲取數據并輸出
Set<String> keys = jedis.keys("*");
Iterator<String> it=keys.iterator() ;
while(it.hasNext()){
String key = it.next();
System.out.println(key);
}
}
}
python
http://www.cnblogs.com/melonjiang/p/5342383.html
redis-py
連接:
import redis
r = redis.Redis(host='192.168.0.110', port=6379,db=0)
r.set('name', 'roob') #添加
print (r.get('name')) #獲取
連接池:
redis-py使用connection pool來管理對一個redis server的所有連接,避免每次建立、釋放連接的開銷。默認,每個Redis實例都會維護一個自己的連接池??梢灾苯咏⒁粋€連接池,然后作為參數Redis,這樣就可以實現多個Redis實例共享一個連接池。
import redis
pool = redis.ConnectionPool(host='192.168.0.110', port=6379)
r = redis.Redis(connection_pool=pool)
r.set('name', 'zhangsan') #添加
print (r.get('name')) #獲取
操作:
http://www.cnblogs.com/melonjiang/p/5342505.html
http://www.lxweimin.com/p/2639549bedc8
管道:
redis-py默認在執行每次請求都會創建(連接池申請連接)和斷開(歸還連接池)一次連接操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,并且默認情況下一次pipline 是原子性操作。
import redis
pool = redis.ConnectionPool(host='192.168.0.110', port=6379)
r = redis.Redis(connection_pool=pool)
pipe = r.pipeline(transaction=True)
r.set('name', 'zhangsan')
r.set('name', 'lisi')
pipe.execute()
發布和訂閱
首先定義一個RedisHelper類,連接Redis,定義頻道為monitor,定義發布(publish)及訂閱(subscribe)方法。
import redis
class RedisHelper(object):
def __init__(self):
self.__conn = redis.Redis(host='192.168.0.110',port=6379)#連接Redis
self.channel = 'monitor' #定義名稱
def publish(self,msg):#定義發布方法
self.__conn.publish(self.channel,msg)
return True
def subscribe(self):#定義訂閱方法
pub = self.__conn.pubsub()
pub.subscribe(self.channel)
pub.parse_response()
return pub
發布者
from RedisHelper import RedisHelper
obj = RedisHelper()
obj.publish('hello')#發布
訂閱者
from RedisHelper import RedisHelper
obj = RedisHelper()
redis_sub = obj.subscribe()#調用訂閱方法
while True:
msg= redis_sub.parse_response()
print (msg)