Redis學習筆記

Redis 是完全開源免費的,遵守BSD協議,是一個高性能的key-value數據庫。

Redis 與其他 key - value 緩存產品有以下三個特點:

1)Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。

2)Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。

3)Redis支持數據的備份,即master-slave模式的數據備份。

Redis 優勢

1)性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。

2)豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作。

3)原子 – Redis的所有操作都是原子性的,同時Redis還支持對幾個操作全並後的原子性執行。

4)豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。

Redis與其他key-value存儲有什麼不同?

Redis有著更為複雜的數據結構並且提供對他們的原子性操作,這是一個不同於其他數據庫的進化路徑。Redis的數據類型都是基於基本數據結構的同時對程序員透明,無需進行額外的抽象。

Redis運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡內存,因為數據量不能大於硬件內存。在內存數據庫方面的另一個優點是,相比在磁盤上相同的複雜的數據結構,在內存中操作起來非常簡單,這樣Redis可以做很多內部複雜性很強的事情。同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因為他們並不需要進行隨機訪問。

Window 下安裝

下載地址:https://github.com/MSOpenTech/redis/releases。

Redis 支持 32 位和 64 位。這個需要根據你係統平臺的實際情況選擇,這裡我們下載 Redis-x64-xxx.zip壓縮包到 C 盤,解壓後,將文件夾重新命名為 redis。

服務啟動:打開cmd窗口,cd命令到redis安裝目錄,運行redis-server.exe redis.windows.conf

參數說明

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 命令在連接上指定數據庫id

databases 16

9. 指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合

save

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

14. 當master服務設置了密碼保護時,slav服務連接master的密碼

masterauth

15. 設置Redis連接密碼,如果配置了連接密碼,客戶端在連接Redis時需要通過AUTH 命令提供密碼,默認關

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

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

Redis 數據類型

Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)

string是redis最基本的類型,你可以理解成與Memcached一模一樣的類型,一個key對應一個value。

string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。

string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。

使用SET命令設置鍵的值,例如:SET name "runoob"

使用GET命令獲取鍵的值,例如:GET name

注意:一個鍵最大能存儲512MB。

Hash(哈希)

Redis hash 是一個鍵名對集合。

Redis hash是一個string類型的field和value的映射表,hash特別適合用於存儲對象。

使用HMSET命令設置對象信息,例如:HMSET user:001 usercode dev password abc888,user:001為鍵key

使用HGETALL命令獲取對象信息,例如:HGETALL user:001

注意:每個 hash 可以存儲 232 -1 鍵值對(40多億)。

List(列表)

Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。

使用LPUSH命令添加list值,例如:

lpush templist zhangsan

lpush templist lisi

lpush templist wangwu

給templist添加了三個值:zhangsan、lisi、wangwu

使用LRANGE命令遍歷list的值,例如:lrange templist 0 10

輸出:

1) "wangwu"

2) "lisi"

3) "zhangsan"

注意:列表最多可存儲 232 - 1 元素 (4294967295, 每個列表可存儲40多億)。

Set(集合)

Redis的Set是string類型的無序集合。

集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。

使用SADD命令添加一個string元素到,key對應的set集合中,成功返回1,如果元素已經在集合中返回0,key對應的set不存在返回錯誤。

例如:

sadd tempset zhangsan

sadd tempset wangwu

sadd tempset lisi

sadd tempset lisi

給tempset添加了四個值:zhangsan、wangwu、lisi、lisi,但lisi添加了兩次,根據集合內元素的唯一性,第二次插入的元素將被忽略。

使用SMEMBERS命令獲取set值,例如:smembers tempset

注意:集合中最大的成員數為 232 - 1(4294967295, 每個集合可存儲40多億個成員)

zset(sorted set:有序集合)

Redis zset 和 set 一樣也是string類型元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。

zset的成員是唯一的,但分數(score)卻可以重複。

使用zadd命令添加元素到集合,元素在集合中存在則更新對應score。

例如:

zadd tempzset 0 zhangsan

zadd tempzset 0 lisi

zadd tempzset 0 wangwu

zadd tempzset 0 lisi

給tempzset添加了四個值:zhangsan、lisi、wangwu、lisi,但集合內元素的唯一性,第二次插入的元素將被忽略。

使用ZRANGEBYSCORE命令獲取zset值,例如:zrangebyscore tempzset 0 1000

HyperLogLog

Redis 在 2.8.9 版本添加了 HyperLogLog 結構。

Redis HyperLogLog 是用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定的、並且是很小的。在 Redis 裡面,每個HyperLogLog鍵只需要花費12KB內存,就可以計算接近2^64個不同元素的基數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。但是,因為HyperLogLog只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以HyperLogLog不能像集合那樣,返回輸入的各個元素。

使用PFADD命令添加值,例如:

pfadd mypf zhangsan

pfadd mypf lisi

使用PFCOUNT命令獲取數量,例如:pfcount mypf

使用PFMERGE命令合併HyperLogLog,例如:

pfadd mypf2 wangwu

pfmerge mypf mypf2 --將mypf2合併到mypf中

Redis 發佈訂閱

Redis 發佈訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。

Redis 客戶端可以訂閱任意數量的頻道。

下圖展示了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:

當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:

例如:

創建一個訂閱頻道為mychat:subscribe mychat

開啟另外一個redis客戶端,然後發佈消息:publish mychat 'hello word!'

訂閱者的客戶端會顯示如下消息:

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "mychat"

3) (integer) 1

1) "message"

2) "mychat"

3) "hello word!"

發佈訂閱命令:

PSUBSCRIBE:訂閱一個或多個符合給定模式的頻道

PUBSUB:查看訂閱與發佈系統狀態

PUBLISH:將信息發送到指定的頻道

PUNSUBSCRIBE:退訂所有給定模式的頻道

SUBSCRIBE:訂閱給定的一個或多個頻道的信息

UNSUBSCRIBE:指退訂給定的頻道

Redis 事務

Redis 事務可以一次執行多個命令, 並且帶有以下兩個重要的保證:

事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

事務是一個原子操作:事務中的命令要麼全部被執行,要麼全部都不執行。

一個事務從開始到執行會經歷以下三個階段:

開始事務

命令入隊

執行事務

Redis 事務命令:

DISCARD:取消事務,放棄執行事務塊內的所有命令。

EXEC:執行所有事務塊內的命令。

MULTI:標記一個事務塊的開始。

UNWATCH:取消 WATCH 命令對所有 key 的監視。

WATCH:監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

Redis 連接命令:

AUTH password:驗證密碼是否正確

ECHO message:打印字符串

PING:查看服務是否運行

QUIT:關閉當前連接

SELECT index:切換到指定的數據庫

Redis 服務器命令:

BGREWRITEAOF:異步執行一個 AOF(AppendOnly File) 文件重寫操作

BGSAVE:在後臺異步保存當前數據庫的數據到磁盤

CLIENT KILL [ip:port] [ID client-id]:關閉客戶端連接

CLIENT LIST:獲取連接到服務器的客戶端連接列表

CLIENT GETNAME:獲取連接的名稱

CLIENT PAUSE timeout:在指定時間內終止運行來自客戶端的命令

CLIENT SETNAME connection-name:設置當前連接的名稱

CLUSTER SLOTS:獲取集群節點的映射數組

COMMAND:獲取 Redis 命令詳情數組

COMMAND COUNT:獲取 Redis 命令總數

COMMAND GETKEYS:獲取給定命令的所有鍵

TIME:返回當前服務器時間

COMMAND INFO command-name [command-name ...]:獲取指定 Redis 命令描述的數組

CONFIG GET parameter:獲取指定配置參數的值

CONFIG REWRITE:對啟動 Redis 服務器時所指定的 redis.conf 配置文件進行改寫

CONFIG SET parameter value:修改 redis 配置參數,無需重啟

CONFIG RESETSTAT:重置 INFO 命令中的某些統計數據

DBSIZE:返回當前數據庫的 key 的數量

DEBUG OBJECT key:獲取 key 的調試信息

DEBUG SEGFAULT:讓 Redis 服務崩潰

FLUSHALL:刪除所有數據庫的所有key

FLUSHDB:刪除當前數據庫的所有key

INFO [section]:獲取 Redis 服務器的各種信息和統計數值

LASTSAVE:返回最近一次 Redis 成功將數據保存到磁盤上的時間,以 UNIX 時間戳格式表示

MONITOR:實時打印出 Redis 服務器接收到的命令,調試用

ROLE:返回主從實例所屬的角色

SAVE:異步保存數據到硬盤

SHUTDOWN [NOSAVE] [SAVE]:異步保存數據到硬盤,並關閉服務器

SLAVEOF host port:將當前服務器轉變為指定服務器的從屬服務器(slave server)

SLOWLOG subcommand [argument]:管理 redis 的慢日誌

SYNC:用於複製功能(replication)的內部命令

Redis 數據備份與恢復

Redis SAVE 命令用於創建當前數據庫的備份;創建 redis 備份文件也可以使用命令 BGSAVE,該命令在後臺執行。

例如:redis 127.0.0.1:6379> SAVE

OK

注:該命令將在 redis 安裝目錄中創建dump.rdb文件。

恢復數據:如果需要恢復數據,只需將備份文件 (dump.rdb) 移動到 redis 安裝目錄並啟動服務即可。獲取 redis 目錄可以使用 CONFIG 命令:CONFIG GET dir

Redis 安全

我們可以通過 redis 的配置文件設置密碼參數,這樣客戶端連接到redis服務就需要密碼驗證,這樣可以讓你的redis服務更安全。

CONFIG get requirepass:查看是否設置了密碼驗證,默認情況下requirepass參數是空的,這就意味著你無需通過密碼驗證就可以連接到redis服務。

CONFIG set requirepass "hwsoft":設置密碼驗證為hwsoft,設置密碼後,客戶端連接redis服務就需要密碼驗證,否則無法執行命令。

AUTH "hwsoft":密碼認證

Redis 客戶端連接

Redis 通過監聽一個 TCP 端口或者 Unix socket 的方式來接收來自客戶端的連接,當一個連接建立後,Redis 內部會進行以下一些操作:

首先,客戶端 socket 會被設置為非阻塞模式,因為 Redis 在網絡事件處理上採用的是非阻塞多路複用模型。

然後為這個 socket 設置 TCP_NODELAY 屬性,禁用 Nagle 算法

然後創建一個可讀的文件事件用於監聽這個客戶端 socket 的數據發送

config get maxclients:獲取最大連接數

config set maxclients 12000:設置最大連接數為12000

Redis 分區

分區是分割數據到多個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

開始在 Java 中使用 Redis 前, 我們需要確保已經安裝了 redis 服務及 Java redis 驅動,且你的機器上能正常使用 Java。 Java的安裝配置可以參考我們的 Java開發環境配置 接下來讓我們安裝 Java redis 驅動:

首先你需要下載驅動包,下載 jedis.jar,確保下載最新驅動包。

在你的classpath中包含該驅動包。

Java實例:

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("runoobkey", "Redis tutorial");

// 獲取存儲的數據並輸出

System.out.println("Stored string in redis:: "+ jedis.get("runoobkey"));

//存儲數據到列表中

jedis.lpush("tutorial-list", "Redis");

jedis.lpush("tutorial-list", "Mongodb");

jedis.lpush("tutorial-list", "Mysql");

// 獲取存儲的數據並輸出

List list = jedis.lrange("tutorial-list", 0 ,5);

for(int i=0; i

System.out.println("Stored string in redis:: "+list.get(i));

}

// 獲取數據並輸出

List list = jedis.keys("*");

for(int i=0; i

System.out.println("List of stored keys:: "+list.get(i));

}

}

}

Spring 整合 Redis

1)工程中引入spring-data-redis、jedis等jar包

2)配置applicationContext.xml:

classpath:etc/redis.properties

p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"

p:pool-config-ref="poolConfig" p:use-pool='true' />

p:connection-factory-ref='connectionFactory'

p:keySerializer-ref="keySerializer"

p:valueSerializer-ref="valueSerializer" />

註解說明:

@CachePut(value="",key="",condition="",unless="")

value:緩存的名字,可以把數據寫到多個緩存

key:緩存key,如果不指定將使用默認的KeyGenerator生成

condition:滿足緩存條件的數據才會放入緩存,condition在調用方法之前和之後都會判斷

unless:用於否決緩存更新的,不像condition,該表達只在方法執行之後判斷,此時可以拿到返回值result進行判斷了

@Cacheable(value="",key="",condition="",unless="")

@CacheEvict(value="",key="",condition="",allEntries=false,beforeInvocation=false)

allEntries:是否移除所有數據,默認值為false

beforeInvocation:是調用方法之前移除/還是調用之後移除,默認值為false

@Caching(put = {},cacheable = {},evict = {})

cacheable:從緩存獲取多個,如果沒有則執行方法體,獲取值後加入緩存

put:緩存多個

evict:從緩存移除多個

CachePut與Cacheable區別:

@CachePut:這個註釋可以確保方法被執行,同時方法的返回值也被記錄到緩存中。

@Cacheable:當重複使用相同參數調用方法的時候,方法本身不會被調用執行,即方法本身被略過了,取而代之的是方法的結果直接從緩存中找到並返回了,如果從緩存中沒有找到數據,則會執行方法,並且將返回值加入到緩存,當再次執行該方法獲取時,會直接從緩存中拿,而不會執行方法體。

RedisTemplate支持

熟悉Spring的JdbcTemplate對象的話,應該大概能猜出來RedisTemplate的作用了,RedisTemplate對象對RedisConnection進行了封裝,它提供了連接管理,序列化等功能,它對Redis的交互進行了更高層次的抽象。另外還提供了Redis操作命令的操作視圖,這極大的方便和簡化了Redis的操作。

下表是具體的操作視圖接口類介紹:

Key類型操作

ValueOperations Redis String/Value 操作

ListOperations Redis List 操作

SetOperations Redis Set 操作

ZSetOperations Redis Sort Set 操作

HashOperations Redis Hash 操作

Value約束操作

BoundValueOperations Redis String/Value key 約束

BoundListOperations Redis List key 約束

BoundSetOperations Redis Set key 約束

BoundZSetOperations Redis Sort Set key 約束

BoundHashOperations Redis Hash key 約束

例如:

//注入redisTemplate

@Resource

private RedisTemplate redisTemplate;

//Redis String/Value 操作

ValueOperations valueops = redisTemplate.opsForValue();

valueops.set(key, obj);


分享到:


相關文章: