Redis特性
多數據庫
Redis 內部自帶有16個數據庫,序號分別從0 - 15 。 默認我們操作的數據都是存放在 0 號數據庫中
1. 切換數據庫
select 1 選擇1號數據庫
2. 遷移數據到指定數據庫
move key 1 從當前數據庫中遷移 key到 1號數據庫
如 : move myset 1
消息訂閱&發佈
訂閱&發佈需要多個客戶端協同工作。 由A客戶端訂閱 指定頻道消息、由B客戶端發佈 指定頻道的消息 。 一般會在網絡聊天室中出現、實際開發當中這個知識點比較少用到。
演示如下:
分別啟動兩個終端。
A終端使用:
subscribe cctv5 : 意思是 ,該終端在訂閱頻道名為 cctv5的消息。
當然也可以進行批量訂閱:
subscribe cctv* 只要頻道是以cctv 打頭的都進行訂閱。
B 終端使用
publish cctv5 'i love china...' 發佈消息
一旦B終端發佈消息,那麼A終端就會收到消息。
事務
Redis的事務 與關係型數據庫的事務還是有一點區別的。 雖然都是包含了一組操作邏輯,但是關係型數據庫是 只要這一組中有一個小動作失敗,那麼組內的所有邏輯都以失敗告終。
Redis的卻是,如果有一個小動作失敗了,那麼剩下的動作依然可以繼續往下執行。但是Redis的事務卻可以保證Redis 的服務器在沒有執行完事務中的所有邏輯,不會再為其他Redis的客戶端服務。也就是確保了事務不會被打斷或者執行到一半的時候,突然被別的客戶端插進來執行。
演示如下:
set num 10
開啟事務:
multi
執行邏輯1
incrby num 5
執行邏輯2
incrby num x
執行邏輯3
incrby num 10
提交事務
exec (等同於我們平常見到的 commit)
回滾事務:
discard
Redis持久化
Redis提供兩種持久化方案 , 分別是 RDB 和 AOF
RDB 快照 :
默認就支持的,無需配置。該機制是:在指定的時間間隔內將內存中的數據寫入磁盤中。
設置持久化快照的條件
在redis.conf中修改持久化快照的條件,如下:
在redis.conf中可以指定持久化文件存儲的目錄
Rdb問題
一旦redis非法關閉,那麼會丟失最後一次持久化之後的數據。
如果數據不重要,則不必要關心。
如果數據不能允許丟失,那麼要使用aof方式。
AOF方式:
需要配置,該機制是: 以日誌的方式記錄服務器所處理的每一個動作。Redis服務器在啟動的時候,會讀取該文件來重新構建數據庫,以保證啟動後的數據庫數據是完整的。
Redis默認是不使用該方式持久化的。Aof方式的持久化,是操作一次redis數據庫,則將操作的記錄存儲到aof持久化文件中。
第一步:開啟aof方式的持久化方案
將redis.conf中的appendonly改為yes,即開啟aof方式的持久化方案。
Aof文件存儲的目錄和rdb方式的一樣。
Aof文件存儲的名稱
Redis的主從複製
持久化保證了即使redis服務重啟也不會丟失數據,因為redis服務重啟後會將硬盤上持久化的數據恢復到內存中,但是當redis服務器的硬盤損壞了可能會導致數據丟失,如果通過redis的主從複製機制就可以避免這種單點故障,如下圖:
說明:
- 主redis中的數據有兩個副本(replication)即從redis1和從redis2,即使一臺redis服務器宕機其它兩臺redis服務也可以繼續提供服務。
- 主redis中的數據和從redis上的數據保持實時同步,當主redis寫入數據時通過主從複製機制會複製到兩個從redis服務上。
- 只有一個主redis,可以有多個從redis。
- 主從複製不會阻塞master,在同步數據時,master 可以繼續處理client 請求
- 一個redis可以即是主又是從,如下圖:
主從複製設置
主機配置
無需配置
從機配置
第一步:複製出一個從機
[root@itPX redis1]# cp bin/ bin2 –r
第二步:修改從機的redis.conf
語法:Slaveof masterip masterport
slaveof 192.168.242.137 6379
第三步:修改從機的port地址為6380
在redis.conf中修改
第四步:清除從機中的持久化文件
[root@itPX bin2]# rm -rf appendonly.aof dump.rdb
第五步:啟動從機
[root@itPX bin2]# ./redis-server redis.conf
第六步:啟動6380的客戶端
[root@itPX bin2]# ./redis-cli -p 6380
注意:
主機一旦發生增刪改操作,那麼從機會將數據同步到從機中
從機不能執行寫操作
127.0.0.1:6380> set s2 222
(error) READONLY You can't write against a read only slave.
Redis集群
redis-cluster架構圖
架構細節:
- 所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
- 節點的fail是通過集群中超過半數的節點檢測失效時才生效.
- 客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可
- redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護nodeslotvalue
Redis 集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點
redis-cluster投票:容錯
集群中所有master參與投票,如果半數以上master節點與其中一個master節點通信超時(cluster-node-timeout),認為該master節點掛掉.
如果集群任意master掛掉,且當前master沒有slave,則集群進入fail狀態。也可以理解成集群的[0-16383]slot映射不完全時進入fail狀態。
如果集群超過半數以上master掛掉,無論是否有slave,集群進入fail狀態。
搭建集群
安裝ruby
集群管理工具(redis-trib.rb)是使用ruby腳本語言編寫的。
第一步:安裝ruby
[root@itPX bin2]# yum install ruby
[root@itPX bin2]# yum install rubygems
第二步:將redis-3.0.0.gem文件上傳到linux系統
第三步:安裝ruby和redis接口
[root@itPX ~]# gem install redis-3.0.0.gem
第四步:將redis-3.0.0包下src目錄中的以下文件拷貝到redis19/redis-cluster/
[root@itPX src]# cd /usr/local/redis19/
[root@itPX redis19]# mkdir redis-cluster
[root@itPX redis19]# cd /root/redis-3.0.0/src/
[root@itPX src]# cp redis-trib.rb /usr/local/redis19/redis-cluster
第五步:查看是否拷貝成功
搭建集群最少也得需要3臺主機,如果每臺主機再配置一臺從機的話,則最少需要6臺機器。
端口設計如下:7001-7006
第一步:複製出一個7001機器
[root@itPX redis19]# cp bin ./redis-cluster/7001 –r
第二步:如果存在持久化文件,則刪除
[root@itPX 7001]# rm -rf appendonly.aof dump.rdb
第三步:設置集群參數
第四步:修改端口
第五步:複製出7002-7006機器
[root@itPX redis-cluster]# cp 7001/ 7002 -r
[root@itPX redis-cluster]# cp 7001/ 7003 -r
[root@itPX redis-cluster]# cp 7001/ 7004 -r
[root@itPX redis-cluster]# cp 7001/ 7005 -r
[root@itPX redis-cluster]# cp 7001/ 7006 –r
第六步:修改7002-7006機器的端口
第七步:啟動7001-7006這六臺機器
第八步:修改start-all.sh文件的權限
[root@itPX redis-cluster]# chmod u+x start-all.sh
[root@itPX redis-cluster]# ./start-all.sh
第九步:創建集群
[root@itPX redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.242.137:7001 192.168.242.137:7002 192.168.242.137:7003 192.168.242.137:7004 192.168.242.137:7005 192.168.242.137:7006
>>> Creating cluster
Connecting to node 192.168.242.137:7001: OK
Connecting to node 192.168.242.137:7002: OK
Connecting to node 192.168.242.137:7003: OK
Connecting to node 192.168.242.137:7004: OK
Connecting to node 192.168.242.137:7005: OK
Connecting to node 192.168.242.137:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.242.137:7001
192.168.242.137:7002
192.168.242.137:7003
Adding replica 192.168.242.137:7004 to 192.168.242.137:7001
Adding replica 192.168.242.137:7005 to 192.168.242.137:7002
Adding replica 192.168.242.137:7006 to 192.168.242.137:7003
M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001
slots:0-5460 (5461 slots) master
M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002
slots:5461-10922 (5462 slots) master
M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003
slots:10923-16383 (5461 slots) master
S: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004
replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24
S: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005
replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7
S: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006
replicates cb7c5def8f61df2016b38972396a8d1f349208c2
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join..
>>> Performing Cluster Check (using node 192.168.242.137:7001)
M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001
slots:0-5460 (5461 slots) master
M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002
slots:5461-10922 (5462 slots) master
M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003
slots:10923-16383 (5461 slots) master
M: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004
slots: (0 slots) master
replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24
M: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005
slots: (0 slots) master
replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7
M: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006
slots: (0 slots) master
replicates cb7c5def8f61df2016b38972396a8d1f349208c2
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@itPX redis-cluster]#
連接集群
[root@itPX 7001]# ./redis-cli -h 192.168.242.137 -p 7001 –c
-c:指定是集群連接
查看集群信息
192.168.242.137:7002> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:2372
cluster_stats_messages_received:2372
192.168.242.137:7002>
查看集群節點
192.168.242.137:7002> cluster nodes
8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001 master - 0 1451581348093 1 connected 0-5460
cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003 master - 0 1451581344062 3 connected 10923-16383
66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004 slave 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 0 1451581351115 1 connected
a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006 slave cb7c5def8f61df2016b38972396a8d1f349208c2 0 1451581349101 3 connected
4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002 myself,master - 0 0 2 connected 5461-10922
cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005 slave 4f52a974f64343fd9f1ee0388490b3c0647a4db7 0 1451581350108 5 connected
jedis連接集群
設置防火牆
[root@itPX redis-cluster]# vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7001 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7002 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7003 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7004 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7005 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7006 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7007 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
"/etc/sysconfig/iptables" 23L, 1146C 已寫入
[root@itPX redis-cluster]# service iptables restart
iptables:清除防火牆規則: [確定]
iptables:將鏈設置為政策 ACCEPT:filter [確定]
iptables:正在卸載模塊: [確定]
iptables:應用防火牆規則: [確定]
[root@itPX redis-cluster]#
代碼
使用spring
配置applicationContext.xml
測試代碼
private ApplicationContext applicationContext; @Before public void init() { applicationContext = new ClassPathXmlApplicationContext( "classpath:applicationContext.xml"); } // redis集群 @Test public void testJedisCluster() { JedisCluster jedisCluster = (JedisCluster) applicationContext .getBean("jedisCluster"); jedisCluster.set("name", "zhangsan"); String value = jedisCluster.get("name"); System.out.println(value); }