集羣概要:java
redis集羣能夠解決哨兵模式分佈式難以搭建的問題、只須要鏈接任何一臺服務器就能夠將分佈式存儲數據,數據遷移簡單node
整個集羣6臺服務器,三主三從,三臺物理機,一臺物理機一主一從web
一、新建一個目錄存放集羣的配置文件redis
cd /home/jionsvolk/proc/redis-4.0.8spring
mkdir conf-cluster數據庫
cp redis.conf conf-cluster/6381.confjson
2.編輯6381.confruby
#bind xxx所有注掉 bind xxx #保護模式關閉 protected-mode no #自定義端口 port 6381 #鏈接空閒關閉超時時間,根據系統負載考量 timeout 600 #TCP鏈接Keepalive時間,根據系統負載考量 tcp-keepalive 600 #打開後臺運行 daemonize yes #PID文件名 由於我以前測試了哨兵模式,已經有redis_6381.pid,爲了區分加了"_c_" pidfile /var/run/redis_c_6381.pid #日誌文件 logfile "/home/jionsvolk/proc/redis-4.0.8/logs-cluster/6381.log" #持久化文件名 dbfilename 6381.rdb #持久化文件存放目錄,千萬要去對應目錄建立該文件夾 dir /home/jionsvolk/data/redis/cluster/dump #另一種持久化方式打開 appendonly yes #AOF文件名 appendfilename "/home/jionsvolk/data/redis/cluster/aof/appendonly.aof" #使用集羣 cluster-enabled yes #集羣使用到的配置文件名 cluster-config-file nodes-6381.conf #集羣中各服務器通訊超時時間 cluster-node-timeout 15000 #最大內存 byte maxmemory 128*1024*1024 #內存管理策略 maxmemory-policy volatile-lru
3.複製一份配置文件給從服務器用服務器
cp 6381.conf 6382.confmvc
vi 6382.conf
#下面的命令是將文件中全部6381改爲6382
:%s/6381/6382/g
4.把兩個服務器的啓動腳本寫在一個文件中
redis-server 6381.conf & redis-server 6382.conf &
配置集羣須要使用到一個工具,該工具須要下載並編譯
1.工具安裝
cd ruby-2.3.1
./configure
make && make install
rubygems是一個用於對 Ruby組件進行打包的 Ruby 打包系統。 它提供一個分發 Ruby 程序和庫的標準格式,還提供一個管理程序包安裝的工具
2.redis的安裝
按照該網址進行安裝https://my.oschina.net/u/3049601/blog/1142841
3.使用redis-trib.rb工具配置集羣
由於常常在conf-cluster目錄操做,因此在該目錄下建立一個硬鏈接文件指向/home/jionsvolk/proc/redis-4.0.8/src/redis-trib.rb
ln redistool /home/jionsvolk/proc/redis-4.0.8/src/redis-trib.rb
3.1在集羣中添加三個主節點
命令:redistool create 192.168.245.111:6381 192.168.245.112:6381 192.168.245.113:6381
執行結果
執行過程當中若是出現以下相似錯誤,需刪除全部的rdb、aof、nodes-xxxx.conf文件
/usr/lib64/ruby/gems/1.8/gems/redis-3.3.2/lib/redis/client.rb:121:in `call': ERR Slot 3853 is already busy (Redis::CommandError)
3.2 檢查集羣
登陸剛纔三臺服務器中的任意一臺
redis-cli -c -p 6381
127.0.0.1:6381> cluster nodes
能夠看到三臺服務器都是master
3.3 將三個從節點添加到集羣當中
redistool add-node --slave --master-id b1ad0d9af8dd6c5ec91e8e92537ec8b44c8c1224 192.168.245.111:6382 192.168.245.111:6381
redistool add-node --slave --master-id b8a1c799b3beb3f25242cd31c277d5a6481371bd 192.168.245.112:6382 192.168.245.111:6381
redistool add-node --slave --master-id 33bc3c223900410922839944deefc8c4c8bc1332 192.168.245.113:6382 192.168.245.111:6381
執行結果以下:
3.4 檢查從節點加入集羣狀況
登陸剛纔三臺服務器中的任意一臺
redis-cli -c -p 6381
127.0.0.1:6381> cluster nodes
能夠看到新加的三臺服務器已是各自主服務器的從服務器
3.5 往集羣中添加數據
redis-cli -c -p 6381
set name Messi
集羣根據哈希取模定位到槽道5798,而5798操做是分配給192.168.245.112:6381這臺服務器的(只有主服務器才能分配到槽道)
1. 普通模式
public static void main(String[] args) { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 最大鏈接數 poolConfig.setMaxTotal(1); // 最大空閒數 poolConfig.setMaxIdle(1); // 最大容許等待時間,若是超過這個時間還未獲取到鏈接,則會報JedisException異常: // Could not get a resource from the pool poolConfig.setMaxWaitMillis(1000); Set<HostAndPort> nodes = new LinkedHashSet<HostAndPort>(); //這裏能夠不把集羣全部機器都添加進來,由於鏈接任何一臺均可以往集羣正確的地方發送數據並存儲 nodes.add(new HostAndPort("192.168.245.111", 6381)); nodes.add(new HostAndPort("192.168.245.111", 6382)); nodes.add(new HostAndPort("192.168.245.112", 6381)); nodes.add(new HostAndPort("192.168.245.112", 6382)); nodes.add(new HostAndPort("192.168.245.113", 6381)); nodes.add(new HostAndPort("192.168.245.114", 6382)); JedisCluster jedis = new JedisCluster(nodes, poolConfig); jedis.set("name", "Messi"); System.out.println(cluster.get("name")); try { cluster.close(); } catch (IOException e) { e.printStackTrace(); } }
2. Spring boot
POM中導入redis啓動器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.5.RELEASE</version> </dependency>
在application.properties中配置redis相關屬性,該配置只適合集羣
################################### redis 集羣配置 ########################################## # REDIS(RedisProperties) # (普通集羣,不使用則不用開啓)在羣集中執行命令時要遵循的最大重定向數目。 # spring.redis.cluster.max-redirects= # (普通集羣,不使用則不用開啓)以逗號分隔的「主機:端口」對列表進行引導。 spring.redis.cluster.nodes=192.168.245.111:6381,192.168.245.111:6382,192.168.245.112:6381,192.168.245.112:6382,192.168.245.113:6381,192.168.245.113:6382 # 鏈接工廠使用的數據庫索引。 spring.redis.database=0 # 鏈接URL,將覆蓋主機,端口和密碼(用戶將被忽略),例如:redis://user:password@example.com:6379 # spring.redis.url= # Redis服務器主機。 #spring.redis.host=localhost # 登陸redis服務器的密碼。 #spring.redis.password= # 啓用SSL支持。 spring.redis.ssl=false # 池在給定時間能夠分配的最大鏈接數。使用負值無限制。 spring.redis.pool.max-active=8 # 池中「空閒」鏈接的最大數量。使用負值表示無限數量的空閒鏈接。 spring.redis.pool.max-idle=8 # 鏈接分配在池被耗盡時拋出異常以前應該阻塞的最長時間量(以毫秒爲單位)。使用負值能夠無限期地阻止。 spring.redis.pool.max-wait=10000 # 目標爲保持在池中的最小空閒鏈接數。這個設置只有在正面的狀況下才有效果。 spring.redis.pool.min-idle=0 # Redis服務器端口。 #spring.redis.port=6379 # (哨兵模式,不使用則不用開啓)Redis服務器的名稱。 # spring.redis.sentinel.master= # (哨兵模式,不使用則不用開啓)主機:端口對的逗號分隔列表。 # spring.redis.sentinel.nodes= # 以毫秒爲單位的鏈接超時。 spring.redis.timeout=10000
在controller中配置使用redis
@Controller @RequestMapping("/web/itemcat") public class WebItemCatController { @Autowired private ItemCatService itemCatService; @Autowired private RedisTemplate redisTemplate; //jsonp格式傳遞三級結構數據 @RequestMapping("/all") @ResponseBody public JSONPObject queryItemCatList(String callback){ ItemCatResult result = itemCatService.queryItemCatsNew(); System.out.println(result); redisTemplate.opsForValue().set("name", "Havi"); System.out.println("redisTemplate.opsForValue().get(\"name\"):"+redisTemplate.opsForValue().get("name")); JSONPObject jsonpResult=new JSONPObject(callback, result); return jsonpResult; } }
RedisTemplate是spring boot自動實例化到容器中,並注入到個人controller
3.spring boot 本身寫代碼注入redis集羣對象
配置共享上面的內容
@ConfigurationProperties("spring.redis") public class RedisConfig { @Value("cluster.nodes:null") private String nodes; @Value("pool.max-active:10") private Integer maxActive; @Value("pool.max-idle:5") private Integer maxIdle; @Value("pool.max-wait:10000") private Integer maxWait; @Value("pool.min-idle:0") private Integer minIdle; @Value("timeout:10000") private Integer timeout; /** * 初始化Jedis配置對象 * @return */ public JedisPoolConfig getConfig(){ JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(maxActive); config.setMaxIdle(maxIdle); config.setMaxWaitMillis(maxWait); config.setMinIdle(minIdle); return config; } /* * 初始化鏈接池,並經過@Bean將鏈接池放入到容器中 * * 爲了讓開發人員更方便的使用,還須要對方法進一步封裝 */ @Bean public JedisCluster initCluster(){ Set<HostAndPort> set = new HashSet<>(); String[] hps = nodes.split(","); for(String hp : hps) { HostAndPort hpConfig = new HostAndPort(hp.split(":")[0], Integer.parseInt(hp.split(":")[1])); set.add(hpConfig); } JedisCluster cluster = new JedisCluster(set,timeout); return cluster; } }
既然Spring Boot已經給我們封裝好了,直接用就好了,不用這麼麻煩再本身搞代碼放入容器,若是是使用原生的spring和spring mvc可使用這種方式