(一)什么是Redis?
Redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。與Memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis 是一個高性能的key-value數據庫。Redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部分場合可以對關系數據庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。[1]
Redis支持主從同步。數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。
(二)Redis與Memcached的區別
u 持久化:
l Redis可以用來做緩存,也可以做存儲;支持ADF和RDB兩種持久化方式
l Memcached只能緩存數據
u 數據結構:
l Redis有豐富的數據類型:字符串、鏈表,Hash、集合,有序集合
l Memcached一般就是字符串和對象
(三)Redis的安裝與配置
1.解壓:tar -zxvf redis-3.0.5.tar.gz
2.make
3.make PREFIX=/root/training/redis install
4.cp ~/tools/redis-3.0.5/redis.conf /root/training/redis/etc/
Redis的核心配置文件:redis.conf

Redis的命令腳本:
redis-benchmark 性能測試工具
redis-check-aof 檢查AOF日志
redis-check-dump 檢查RDB日志
redis-cli 啟動命令行客戶端
redis-sentinel
redis-server 啟動Redis服務
啟動Redis:
./redis-server ../etc/redis6379.conf
./redis-server ../etc/redis6380.conf
這樣就在6379和6380端口上,各自啟動了一個Redis實例;也可以通過ps命令查看:

啟動Redis的客戶端:redis-cli
l 默認連接6739端口,也可以通過-p指定連接的端口號:
l ./redis-cli --help顯式幫助信息
(四)Redis的操作
http://www.redis.cn/commands.html
key操作
redis 的 key 是以 string 儲存的,redis 對於 key 常用的操作指令如下:
1.select db_name 使用指定數據庫 select 1 # 使用數據庫 1
2.exits key_name 檢查指定的 key 是否存在
3.get key_name 獲取指定 key 的 value
4.mget key1 [key2 ..] 獲取指定多個 key 的 value,
5.randomkey 隨機獲取一個 key
6.set key_name key_value 設置 key-value
7.getset key_name key_value 設置 key-value,並返回 key 的舊值
8.setnx key_name value 只有在 key 不存在時,才設置 key
9.mset key1 val1[ key1 val2...] 同時設置多個 key-value
10.del key_name 刪除指定的 key
11.rename key_name new_key_name 重命名指定key
12.type key_name 返回指定 key 的 value 的類型
13.dump key_name 序列化指定 key,並返回該 key 序列化后的 value
14.keys pattern 查找所有符合給定 pattern 的 key,支持使用 * 作為通配符;
15.keys a* # 查找所有以 ‘a’ 開頭的 key
16.keys * # 查找所有 key
17.move key_name db_name 將指定 key-value 移動到指定數據庫
18.expire key_name seconds pexpire key_name milliseconds
給指定key設置過期時間,單位分別為秒,毫秒
19.expireat key_name timestamp 設置指定的key 在指定的UNIX時間戳過期
20.ttl key_name pttl key_name
返回 key 的 TTL(Time to Live)生存時間,分別以 秒,毫秒為單位;
21.persist key_name 移除指定 key 的過期時間,該 key 將持久保存
22.flushdb 刪除當前數據庫的所有 key
23.flushall 刪除所有數據庫的 key
其他操作可進入鏈接查看
數據類型
① 字符串
② 鏈表
③ Hash
④ 無序集合
⑤ 有序集合
⑥ Redis數據類型案例分析:網站統計用戶登錄的次數
- 1億個用戶,有經常登錄的,也有不經常登錄的
- 如何來記錄用戶的登錄信息
- 如何查詢活躍用戶:比如:一周內,登錄3次的
解決方案一:采用關系型數據庫
解決方案二:采用Redis存儲登錄信息
可以使用Redis的setbit,登錄與否:有1和0就可以表示
25.Java客戶端
① 基本操作
② 連接池
③ 使用Redis實現分布式鎖
使用Maven搭建工程:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
(五)Redis的事務和消息機制
1.Redis的事務
Redis對事務的支持目前還比較簡單。redis只能保證一個client發起的事務中的命令可以連續的執行,而中間不會插入其他client的命令。 由於redis是單線程來處理所有client的請求的所以做到這點是很容易的。一般情況下redis在接受到一個client發來的命令后會立即處理並 返回處理結果,但是當一個client在一個連接中發出multi命令有,這個連接會進入一個事務上下文,該連接后續的命令並不是立即執行,而是先放到一個隊列中。當從此連接受到exec命令后,redis會順序的執行隊列中的所有命令。並將所有命令的運行結果打包到一起返回給client.然后此連接就 結束事務上下文。
Oracle數據庫中的事務和Redis的事務對比
|
|
Oracle |
Redis |
| 開啟事務的方式 |
自動開啟事務 |
multi |
| 操作 |
DML語句 |
Redis命令 |
| 提交事務 |
commit |
exec |
| 回滾事務 |
rollback |
discard |
2.Redis的事務示例:銀行轉賬
從Tom轉100塊錢給Mike
- set tom 1000
- set mike 1000
- multi
- decrby tom 100
- incrby mike 100
- exec
3.Redis的鎖機制:watch
l 舉例:買票
4.Java應用程序中的事務和鎖
① 事務
② 鎖
5.Redis的消息機制:消息的發布與訂閱,適合做在線聊天
publish:發布消息
格式:publish channel名稱 “消息內容”
subscribe: 訂閱消息
格式:subscribe channel名稱
psubscribe: 使用通配符定義消息
格式:psubscribe channel*名稱
使用Java程序實現消息的發布與訂閱,需要繼承JedisPubSub類
(六)Redis的持久化
Redis 提供了多種不同級別的持久化方式:
- RDB 持久化可以在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。
- AOF (Append-only file)持久化記錄服務器執行的所有寫操作命令,並在服務器啟動時,通過重新執行這些命令來還原數據集。 AOF 文件中的命令全部以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還可以在后台對 AOF 文件進行重寫(rewrite),使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。
- Redis 還可以同時使用 AOF 持久化和 RDB 持久化。 在這種情況下, 當 Redis 重啟時, 它會優先使用 AOF 文件來還原數據集, 因為 AOF 文件保存的數據集通常比 RDB 文件所保存的數據集更完整。
- 你甚至可以關閉持久化功能,讓數據只在服務器運行時存在。
1、RDB
工作原理:每隔一定時間給內存照一個快照,將內存中的數據寫入文件(rdb文件)配置參數:redis.conf文件(在conf文件中找到對應位置)
- RDB示例測試:可以使用redis-benchmark進行壓力測試
- ./bin/redis-benchmark -n 100000 表示執行100000個操作
- RDB的缺點:
- 在兩次快照之間,如果發生斷電,數據會丟失
- 舉例:在生成rdb后,插入新值。突然斷電,數據可能會丟失
2、AOF:通過日志的方式
- 工作原理:記錄操作的命令
- 配置參數:

- 什么是AOF的重寫:rewrite
- 將內存中的key逆向生成命令,如同一個可以,反復操作了100次,aof文件會記錄100次操作,這樣會導致AOF文件過大
例如:
set age 0
incr age
incr age
... 100次
最后 age的值是100
經過重寫后,直接執行: set age 100
2.可以通過觀察aof日志文件的大小
3、Redis持久化注意的問題
- RDB恢復的速度快
- 如果RDB和AOF都有,默認使用AOF進行恢復
(七)Redis的集群
1.集群的作用
l 主從備份 防止主機宕機
l 讀寫分離,分擔master的任務
l 任務分離,如從服分別分擔備份工作與計算工作
2.Redis 集群的兩種部署方式
3.Redis主從服務的通信原理
4.配置Redis的集群(主從模式)
- 主節點:關閉rdb和aof即可
- 從節點:slaveof localhost 6379 開啟rdb和aof
5.Redis集群的高可用性
- Redis 2.4+自帶了一個HA實現Sentinel
- 配置文件:sentinel.conf
- redis-sentinel ../etc/sentinel.conf
- 查看日志:
6.實現Redis的代理分片
- Twemproxy是一種代理分片機制,由Twitter開源。
- Twemproxy作為代理,可接受來自多個程序的訪問,按照路由規則,轉發給后台的各個Redis服務器,再原路返回。該方案很好的解決了單個Redis實例承載能力的問題。

- 安裝
./configure --prefix=/root/training/proxy
make
make install
- 配置文件

- 檢查配置文件是否正確
./nutcracker -t conf/nutcracker.yml - 啟動代理服務器
./nutcracker -d -c conf/nutcracker.yml
(八)Redis Cluster分布式解決方案
1.什么是Redis Cluster?
Redis Cluster是Redis的分布式解決方案,在Redis 3.0版本正式推出的,有效解決了Redis分布式方面的需求。當遇到單機內存、並發、流量等瓶頸時,可以采用Cluster架構達到負載均衡的目的。
- redis使用中遇到的瓶頸
我們日常在對於redis的使用中,經常會遇到一些問題:
(1) 高可用問題,如何保證redis的持續高可用性。
(2) 容量問題,單實例redis內存無法無限擴充,達到32G后就進入了64位世界,性能下降。
(3) 並發性能問題,redis號稱單實例10萬並發,但也是有盡頭的。
- redis-cluster的優勢
(1) 官方推薦,毋庸置疑。
(2) 去中心化,集群最大可增加1000個節點,性能隨節點增加而線性擴展。
(3) 管理方便,后續可自行增加或摘除節點,移動分槽等等。
(4) 簡單,易上手。
2.數據分布理論與Redis的數據分區
分布式數據庫首要解決把整個數據集按照分區規則映射到多個節點的問題,即把數據集划分到多個節點上,每個節點負責整個數據的一個子集。常見的分區規則有哈希分區和順序分區。Redis Cluster采用哈希分區規則。
虛擬槽分區巧妙地使用了哈希空間,使用分散度良好的哈希函數把所有的數據映射到一個固定范圍內的整數集合,整數定義為槽(slot)。比如Redis Cluster槽的范圍是0 ~ 16383。槽是集群內數據管理和遷移的基本單位。
Redis Cluster采用虛擬槽分區,所有的鍵根據哈希函數映射到0 ~ 16383,計算公式:slot = CRC16(key)&16383。每一個節點負責維護一部分槽以及槽所映射的鍵值數據。
3.Redis Cluster的體系架構
我們以6個節點為例,來介紹Redis Cluster的體系架構。其中:三個為master節點,另外三個為slave節點。
4.安裝與部署(方式一:使用配置文件)
① Redis的編譯安裝
- 安裝Linux操作系統和GCC編譯
- 編譯安裝Redis
解壓:tar -zxvf redis-3.0.5.tar.gz
make
make PREFIX=/root/training/redis install
cp ~/tools/redis-3.0.5/redis.conf /root/training/redis/etc/
② 安裝Ruby環境和Ruby Redis接口
由於創建和管理需要使用到redis-trib 工具,該工具位於 Redis 源碼的 src 文件夾中, 它是一個 Ruby 程序, 這個程序通過向實例發送特殊命令來完成創建新集群,檢查集群,或者對集群進行重新分片(reshared)等工作,所以需要安裝Ruby環境和相應的Redis接口
下面是可以使用yum來安裝Ruby:
[media]
name=Red Hat Enterprise Linux 7.4
baseurl=file:///cdroom
enabled=1
gpgcheck=1
gpgkey=file:///cdroom/RPM-GPG-KEY-redhat-release
③ 以6個節點為例,安裝和部署Redis Cluster
- 主節點:6379、6380、6381
- 從節點:6382、6383、6384
- 需要修改的參數如下:其中紅色字體部分需要每個實例修改。
daemonize yes
port 6379
cluster-enabled yes
cluster-config-file nodes/nodes-6379.conf
cluster-node-timeout 15000
dbfilename dump6379.rdb
appendonly yes
appendfilename "appendonly6379.aof"
- 配置文件一共六個:
redis6379.conf
redis6380.conf
redis6381.conf
redis6382.conf
redis6383.conf
redis6384.conf
④ 啟動Redis 實例
bin/redis-server conf/redis6379.conf
bin/redis-server conf/redis6380.conf
bin/redis-server conf/redis6381.conf
bin/redis-server conf/redis6382.conf
bin/redis-server conf/redis6383.conf
bin/redis-server conf/redis6384.conf
通過ps命令查看進程:
⑤ 使用redis-trib.rb自動部署方式
bin/redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384
注意:redis-trib.rb位於 Redis 源碼的 src 文件夾中,拷貝到bin目錄下。
其中:–replicas 1 表示我們希望為集群中的每個主節點創建一個從節點。
開始配置集群:
⑥ 測試Redis Cluster
- 使用客戶端登錄:bin/redis-cli -c -p 6379
-c表示:登錄集群
可以使用:cluster nodes命令查看集群中的節點

5.安裝與部署(方式二:使用create-cluster命令)
將源碼的utils/create-cluster目錄下,將create-cluster拷貝到安裝目錄的bin目錄下
修改create-cluster命令的路徑

- 啟動和創建Redis集群
- bin/create-cluster start
- bin/create-cluster create
- 使用客戶端測試集群

6.使用Java程序測試Redis Cluster
jar包:commons-pool2-2.3.jar jedis-2.7.0.jar
import java.util.HashSet; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; public class TestRedisCluster { public static void main(String[] args) throws Exception { // 指定集群的節點 HashSet<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.56.72", 6379)); nodes.add(new HostAndPort("192.168.56.72", 6380)); nodes.add(new HostAndPort("192.168.56.72", 6381)); nodes.add(new HostAndPort("192.168.56.72", 6382)); nodes.add(new HostAndPort("192.168.56.72", 6383)); nodes.add(new HostAndPort("192.168.56.72", 6384)); // 創建集群 JedisCluster cluster = new JedisCluster(nodes); // 插入3*16383條數據 for (int i = 0; i < 3 * 16383; i++) { System.out.println("插入數據:" + i); cluster.set("mykey" + i, "myvalue:" + i); } // 關閉集群客戶端 cluster.close(); System.out.println("完成"); } }
7.基本的Redis Cluster管理
使用cluster <command> 命令來管理Redis Cluster:
| 命令 |
說明 |
| info |
打印集群的信息。 |
| nodes |
列出集群當前已知的所有節點(node)的相關信息。 |
| meet <ip> <port> |
將ip和port所指定的節點添加到集群當中。 |
| addslots <slot> [slot ...] |
將一個或多個槽(slot)指派(assign)給當前節點。 |
| delslots <slot> [slot ...] |
移除一個或多個槽對當前節點的指派。 |
| slots |
列出槽位、節點信息。 |
| slaves <node_id> |
列出指定節點下面的從節點信息。 |
| replicate <node_id> |
將當前節點設置為指定節點的從節點。 |
| saveconfig |
手動執行命令保存保存集群的配置文件,集群默認在配置修改的時候會自動保存配置文件。 |
| keyslot <key> |
列出key被放置在哪個槽上。 |
| flushslots |
移除指派給當前節點的所有槽,讓當前節點變成一個沒有指派任何槽的節點。 |
| countkeysinslot <slot> |
返回槽目前包含的鍵值對數量。 |
| getkeysinslot <slot> <count> |
返回count個槽中的鍵。 |
| setslot <slot> node <node_id> |
將槽指派給指定的節點,如果槽已經指派給另一個節點,那么先讓另一個節點刪除該槽,然后再進行指派。 |
| setslot <slot> migrating <node_id> |
將本節點的槽遷移到指定的節點中。 |
| setslot <slot> importing <node_id> |
從 node_id 指定的節點中導入槽 slot 到本節點。 |
| setslot <slot> stable |
取消對槽 slot 的導入(import)或者遷移(migrate) |
| failover |
手動進行故障轉移。 |
| forget <node_id> |
從集群中移除指定的節點,這樣就無法完成握手,過期時為60s,60s后兩節點又會繼續完成握手。 |
| reset [HARD|SOFT] |
重置集群信息,soft是清空其他節點的信息,但不修改自己的id,hard還會修改自己的id,不傳該參數則使用soft方式。 |
| count-failure-reports <node_id> |
列出某個節點的故障報告的長度。 |
| SET-CONFIG-EPOCH |
設置節點epoch,只有在節點加入集群前才能設置。 |
命令詳解:cluster info
命令詳解:cluster nodes(可以使用excel 導入命令輸出,方便查看)
幾點說明:
- ping-sent: 最近一次發送ping的時間,這個時間是一個unix毫秒時間戳,0代表沒有發送過.
- pong-recv: 最近一次收到pong的時間,使用unix時間戳表示.
- config-epoch: 節點的epoch值(or of the current master if the node is a slave)。每當節點發生失敗切換時,都會創建一個新的,獨特的,遞增的epoch。如果多個節點競爭同一個哈希槽時,epoch值更高的節點會搶奪到。
命令詳解:cluster slots
其他幾個命令:
節點的添加與刪除
- 增加節點(每次添加2個)
① 增加新的配置文件:redis6385.conf 和 redis6386.conf
② 按照之前的配置修改對應參數
③ 啟動新的節點
bin/redis-server conf/redis6385.conf
bin/redis-server conf/redis6386.conf
④ 添加主節點
bin/redis-trib.rb add-node 192.168.56.72:6385 192.168.56.72:6379
其中:
192.168.56.72:6385是新添加的節點
192.168.56.72:6379是集群中,任一個舊節點
⑤ 檢查集群的節點信息
bin/redis-trib.rb check 192.168.56.72:6379
⑥ 添加從節點
bin/redis-trib.rb add-node --slave --master-id f27013eaebcf998078edf1621e4433534f8d8b11 192.168.56.72:6386 192.168.56.72:6379
其中:
--slave:表示添加的是一個從節點
--master-id:表示該從節點的主節點
192.168.56.72:6386:新添加的從節點
192.168.56.72:6379:是集群中,任一個舊節點
⑦ 重新檢查集群的狀態信息
bin/redis-trib.rb check 192.168.56.72:6379
⑧ 重新分配slot
bin/redis-trib.rb reshard 192.168.56.72:6379
⑨ 重新查看集群的節點槽的信息,可以看到新添加的節點信息。
cluster slots
或者使用:
bin/redis-trib.rb check 192.168.56.72:6379
刪除節點
① 先刪除從節點:
bin/redis-trib.rb del-node 192.168.56.72:6385 21e3e82610ce206708aa8f4189e2c9b2f3d1c540
② 再刪除主節點
bin/redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01
③ 如果出現以下錯誤,需要先清空(移動)該節點上的slot,再刪除
第一步:bin/redis-trib.rb reshard 192.168.56.72:6386
第二步:bin/redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01
④ 重新檢查集群的信息,發生節點已經被刪除
bin/redis-trib.rb check 192.168.56.72:6379
8.Redis Cluster節點的失敗遷移
① 首先,為了看到演示的效果,清除一下之前的設置,還是以六個節點為例
② 啟動每個節點,並創建集群
bin/redis-server conf/redis6379.conf
bin/redis-server conf/redis6380.conf
bin/redis-server conf/redis6381.conf
bin/redis-server conf/redis6382.conf
bin/redis-server conf/redis6383.conf
bin/redis-server conf/redis6384.conf
bin/redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384
③ 檢查集群狀態
bin/redis-trib.rb check 192.168.56.72:6379
④ 殺掉6379上的主節點,並重新檢查集群的狀態
⑤ 稍等一段時間,重新檢查集群的狀態
⑥ 如果重新啟動6379上的實例,它將變成6382的從節點
