上次咱們搭建了Redis的主從架構,哨兵架構以及咱們的集羣架構,可是咱們一直還未投入到實戰中去,此次咱們用jedis和springboot兩種方式來操做一下咱們的redishtml
主從架構java
如何配置我上次已經講過了,http://www.javashuo.com/article/p-ulodfahx-eo.html。咱們此次主要看如何用java來操做redis,先來複習一下上次的配置,準備三臺服務器,安裝redis,保證互通,兩臺改成slave,配置replicaof IP 端口,主從複製是經過rdb文件來複制的。大概就這麼多,配置再也不多說了,咱們直接上代碼。node
jedisweb
建立一個Maven項目,引入咱們的jedis依賴包redis
<!-- 加入jedis依賴 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
這裏我就不封裝鏈接工具類啦,咱們直接看下測試代碼吧spring
public static void main(String[] args) { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(20); jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMinIdle(5); // timeout,這裏既是鏈接超時又是讀寫超時,從Jedis 2.8開始有區分connectionTimeout和soTimeout的構造函數 JedisPool jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379, 3000, null); Jedis jedis = null; try { //從redis鏈接池裏拿出一個鏈接執行命令 jedis = jedisPool.getResource(); System.out.println(jedis.set("xiaocai", "666")); System.out.println(jedis.get("xiaocai")); } catch (Exception e) { e.printStackTrace(); } finally { //注意這裏不是關閉鏈接,在JedisPool模式下,Jedis會被歸還給資源池。 if (jedis != null) jedis.close(); } }
主從的鏈接很簡單的,設置鏈接參數,直接鏈接就能夠操做咱們的redis了,主從的鏈接,就是基本的連接。數據庫
springbootapache
咱們再來看一下springboot怎麼來鏈接吧,創建一個springboot項目,什麼也不用設置,創建一個最簡單的就能夠的,首先仍是加入咱們的Maven驅動包springboot
<!-- 加入redis鏈接池--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
加入咱們的redis的配置信息,放置在application.yml文件下便可。服務器
spring: redis: database: 0 # Redis數據庫索引(默認爲0) host: 127.0.0.1 # Redis服務器地址 port: 6379 # Redis服務器鏈接端口 password: # Redis服務器鏈接密碼(默認爲空) timeout: 5000 # 鏈接超時時間(毫秒) jedis: pool: max-active: 8 # 鏈接池最大鏈接數(使用負值表示沒有限制) max-wait: -1 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 8 # 鏈接池中的最大空閒鏈接 min-idle: 0 # 鏈接池中的最小空閒鏈接
這個也就不存在什麼工具類了,內部都已經封裝好了,咱們直接來上測試類吧
package com.redisclient.master_slave; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.data.redis.core.StringRedisTemplate; @RestController public class RedisMasterSlave { @Autowired private StringRedisTemplate stringRedisTemplate; @GetMapping(value = "/") public String getIndex(){ stringRedisTemplate.opsForValue().set("xiaocai", "888"); System.out.println(stringRedisTemplate.opsForValue().get("xiaocai")); return "小菜技術"; } }
相比咱們上面的jedis還要簡單,直接自動裝配一下咱們的StringRedisTemplate便可,剩下的就是咱們的redis操做了,五種數據的基本操做以下。
redisTemplate.opsForValue();//操做字符串 redisTemplate.opsForHash();//操做hash redisTemplate.opsForList();//操做list redisTemplate.opsForSet();//操做set redisTemplate.opsForZSet();//操做有序set
還有什麼更多的操做不知道的,歡迎來個人公衆號內問答,我會依依給你解釋清楚的。
哨兵架構
哨兵架構,是主從的升級版,master節點宕機後,能夠主動選取咱們的master節點。
咱們仍是分爲jedis和springboot兩種方式分別來嘗試鏈接一下咱們的哨兵架構,搭建我就不說啦,上次博文已經說過了。http://www.javashuo.com/article/p-ulodfahx-eo.html
jedis
仍是老規矩,引入依賴,剩下的咱們直接來寫測試類吧。
package com.redisclient.sentinel; import redis.clients.jedis.*; import java.util.HashSet; import java.util.Set; public class JedisClientSentinel { public static void main(String[] args) { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(20); jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMinIdle(5); String masterName = "mymaster"; Set<String> sentinels = new HashSet<String>(); sentinels.add(new HostAndPort("47.105.97.79", 6380).toString()); sentinels.add(new HostAndPort("47.105.97.142", 6380).toString()); sentinels.add(new HostAndPort("118.190.147.181", 6380).toString()); //JedisSentinelPool其實本質跟JedisPool相似,都是與redis主節點創建的鏈接池 //JedisSentinelPool並非說與sentinel創建的鏈接池,而是經過sentinel發現redis主節點並與其創建鏈接 JedisSentinelPool jedisPool = new JedisSentinelPool(masterName, sentinels, jedisPoolConfig, 5000, null); Jedis jedis = null; try { //從redis鏈接池裏拿出一個鏈接執行命令 jedis = jedisPool.getResource(); System.out.println(jedis.set("xiaocai888", "666888")); System.out.println(jedis.get("xiaocai888")); } catch (Exception e) { e.printStackTrace(); } finally { //注意這裏不是關閉鏈接,在JedisPool模式下,Jedis會被歸還給資源池。 if (jedis != null) jedis.close(); } } }
最簡單的理解就是咱們創建了一個set鏈接池。當哨兵節點宕機一個的時候,會嘗試鏈接其它節點,當master節點宕機時,會報錯鏈接錯誤,稍後會自動恢復的。 ✨
springboot
咱們先來修改一下咱們yml配置文件
#哨兵模式
spring:
redis:
database: 0 # Redis數據庫索引(默認爲0)
host: 120.27.27.4 # Redis服務器地址
port: 6379 # Redis服務器鏈接端口
password: # Redis服務器鏈接密碼(默認爲空)
timeout: 5000 # 鏈接超時時間(毫秒)
sentinel:
master: mymaster #主服務器所在集羣名稱
nodes: 115.28.208.105:26379,47.105.92.89:26379,118.190.151.92:26379
而咱們的測試類和主從是同樣的配置就能夠了,springboot主要改一下配置就能夠了。
集羣架構
上次咱們說過了咱們的集羣架構,就是不少個小主從集合在一塊兒,內部有半數機制,建議設置大於3的奇數個主從服務。
這從咱們來搭建三組一主一從服務,咱們先來看一下jedis的代碼,咱們內部redis是將16384分爲了三個片區,爲了確保每一個片區都存入數據咱們採用了隨機生成的key。
jedis
package com.redisclient.cluster; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.*; import java.io.IOException; import java.util.HashSet; import java.util.Random; import java.util.Set; public class JedisClientCluster { public static void main(String[] args) throws IOException { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(20); config.setMaxIdle(10); config.setMinIdle(5); //這裏將全部主從節點所有放入 Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>(); jedisClusterNode.add(new HostAndPort("120.27.27.4", 6379)); jedisClusterNode.add(new HostAndPort("47.105.86.150", 6379)); jedisClusterNode.add(new HostAndPort("47.105.84.186", 6379)); jedisClusterNode.add(new HostAndPort("115.28.208.105", 6379)); jedisClusterNode.add(new HostAndPort("47.105.92.89", 6379)); jedisClusterNode.add(new HostAndPort("118.190.151.92", 6379)); JedisCluster jedisCluster = null; try { //connectionTimeout:指的是鏈接一個url的鏈接等待時間 //soTimeout:指的是鏈接上一個url,獲取response的返回等待時間 jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "xiaocai", config); while (true) { try { jedisCluster.set(getRandomString(4), "value" + getRandomString(4)); Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } finally { if (jedisCluster != null) jedisCluster.close(); } } //length用戶要求產生字符串的長度 public static String getRandomString(int length) { String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(62); sb.append(str.charAt(number)); } return sb.toString(); } }
springboot
仍是老規矩改一下配置類
# 集羣模式
spring:
redis:
database: 0 # Redis數據庫索引(默認爲0)
host: 120.27.27.4 # Redis服務器地址
port: 6379 # Redis服務器鏈接端口
password: xiaocai # Redis服務器鏈接密碼(默認爲空)
timeout: 5000 # 鏈接超時時間(毫秒)
cluster:
nodes: 115.28.208.105:6379,47.105.92.89:6379,118.190.151.92:6379
說到這裏咱們的三種模式的鏈接就所有寫完了,這些使用仍是一個比一個簡單的,咱們來看下內部的通信和選舉機制吧。
選舉機制
當slave發現本身的master變爲FAIL狀態時,便嘗試進行Failover,以期成爲新的master。因爲掛掉的master可能會有 多個slave,從而存在多個slave競爭成爲master節點的過程, 其過程以下:
1.slave發現本身的master變爲FAIL
2.將本身記錄的集羣currentEpoch加1,並廣播FAILOVER_AUTH_REQUEST 信息
3.其餘節點收到該信息,只有master響應,判斷請求者的合法性,併發送FAILOVER_AUTH_ACK,對每個epoch只發 送一次ack
4.嘗試failover的slave收集master返回的FAILOVER_AUTH_ACK
5.slave收到超過半數master的ack後變成新Master(這裏解釋了集羣爲何至少須要三個主節點,若是隻有兩個,當其 中一個掛了,只剩一個主節點是不能選舉成功的)
6.廣播Pong消息通知其餘集羣節點。從節點並非在主節點一進入 FAIL 狀態就立刻嘗試發起選舉,而是有必定延遲,必定的延遲確保咱們等待FAIL狀態在 集羣中傳播,slave若是當即嘗試選舉,其它masters或許還沒有意識到FAIL狀態,可能會拒絕投票
最近公司有一些事情,就先說到這裏吧,有時間給你們說一下redis來實現分佈式鎖的機制,還有一個炒雞好用的redis分佈式鎖。
最進弄了一個公衆號,小菜技術,歡迎你們的加入