Redis持久化及Redis集群

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持久化及Redis集群

Redis持久化及Redis集群

在redis.conf中可以指定持久化文件存儲的目錄

Redis持久化及Redis集群

Rdb問題

一旦redis非法關閉,那麼會丟失最後一次持久化之後的數據。

如果數據不重要,則不必要關心。

如果數據不能允許丟失,那麼要使用aof方式。

AOF方式:

需要配置,該機制是: 以日誌的方式記錄服務器所處理的每一個動作。Redis服務器在啟動的時候,會讀取該文件來重新構建數據庫,以保證啟動後的數據庫數據是完整的。

Redis默認是不使用該方式持久化的。Aof方式的持久化,是操作一次redis數據庫,則將操作的記錄存儲到aof持久化文件中。

第一步:開啟aof方式的持久化方案

將redis.conf中的appendonly改為yes,即開啟aof方式的持久化方案。

Redis持久化及Redis集群

Redis持久化及Redis集群

Aof文件存儲的目錄和rdb方式的一樣。

Aof文件存儲的名稱

Redis持久化及Redis集群

Redis的主從複製

持久化保證了即使redis服務重啟也不會丟失數據,因為redis服務重啟後會將硬盤上持久化的數據恢復到內存中,但是當redis服務器的硬盤損壞了可能會導致數據丟失,如果通過redis的主從複製機制就可以避免這種單點故障,如下圖:

Redis持久化及Redis集群

說明:

  • 主redis中的數據有兩個副本(replication)即從redis1和從redis2,即使一臺redis服務器宕機其它兩臺redis服務也可以繼續提供服務。
  • 主redis中的數據和從redis上的數據保持實時同步,當主redis寫入數據時通過主從複製機制會複製到兩個從redis服務上。
  • 只有一個主redis,可以有多個從redis。
  • 主從複製不會阻塞master,在同步數據時,master 可以繼續處理client 請求
  • 一個redis可以即是主又是從,如下圖:

Redis持久化及Redis集群

主從複製設置

主機配置

無需配置

從機配置

第一步:複製出一個從機

 [root@itPX redis1]# cp bin/ bin2 –r

第二步:修改從機的redis.conf

語法:Slaveof masterip masterport

 slaveof 192.168.242.137 6379
Redis持久化及Redis集群

第三步:修改從機的port地址為6380

在redis.conf中修改

Redis持久化及Redis集群

第四步:清除從機中的持久化文件

 [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持久化及Redis集群

架構細節:

  1. 所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
  2. 節點的fail是通過集群中超過半數的節點檢測失效時才生效.
  3. 客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可
  4. redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護nodeslotvalue

Redis 集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點

redis-cluster投票:容錯

Redis持久化及Redis集群

集群中所有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

第三步:設置集群參數

Redis持久化及Redis集群

第四步:修改端口

Redis持久化及Redis集群

第五步:複製出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這六臺機器

Redis持久化及Redis集群

第八步:修改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:指定是集群連接

Redis持久化及Redis集群

查看集群信息

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]#

代碼

Redis持久化及Redis集群

使用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);
	}


分享到:


相關文章: