今天早上因爲zookeeper和redis集羣不在同一虛擬機致使出了點很小錯誤(人爲),因此這裏總結一下redis集羣的搭建以便往後所需同時也但願能對你有所幫助。 筆主這裏使用的是Centos7.若是你碰到任何問題均可以來問我,留言或者加我微信:bwcx9393.php
關於Linux的一些資料 連接:pan.baidu.com/s/1Opgu6kQe… 密碼:8yk4html
Redis是c語言開發的。 安裝redis須要c語言的編譯環境。若是沒有gcc須要在線安裝:yum install gcc-c++java
第一步:獲取源碼包:wget http://download.redis.io/releases/redis-3.0.0.tar.gznode
第二步:解壓縮redis:tar zxvf redis-3.0.0.tar.gzc++
第三步:編譯。進入redis源碼目錄(cd redis-3.0.0)。執行 make面試
第四步:安裝。make install PREFIX=/usr/local/redisredis
PREFIX參數指定redis的安裝目錄。通常軟件安裝到/usr目錄下算法
這樣Redis就成功裝在了咱們的usr/local/redis目錄下。spring
第五步:設置後臺啓動: [root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/ (把/root/redis-3.0.0/redis.conf複製到/usr/local/redis/bin目錄下)vim
修改配置文件:把daemonize後面的參數改成yes
測試啓動:[root@localhost bin]# ./redis-server redis.conf
查看redis進程: [root@localhost bin]# ps aux|grep redis
3.0版本以前的redis是不支持集羣的,3.0版本以前想要搭建redis集羣的話須要中間件來找到存值和取值的對應節點。
Redis 集羣中內置了 16384個哈希槽,當須要在 Redis 集羣中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大體均等的將哈希槽映射到不一樣的節點。
根據下圖應該更容易理解了。(圖片來源:http://www.cnblogs.com/liyasong/p/redis_jiqun.html)
redis集羣中有多臺redis服務器不可避免會有服務器掛掉。redis集羣服務器之間經過互相的ping-pong判斷是否節點能夠鏈接上。若是有一半以上的節點去ping一個節點的時候沒有迴應,集羣就認爲這個節點宕機了。
上面就是咱們常說的爲了容錯而生的redis集羣投票機制。
redis集羣搭建起來很簡單,咱們這裏用一臺虛擬機模擬搭建包含6個redis服務器的集羣,實際工做中與使用多臺服務器搭建是一個操做。
咱們上面已經裝好了一個redis實例,如今咱們須要把它複製6份並修改相應端口。
第一步: 新建redis-cluster文件夾
第二步:複製redis實例
[root@Snailclimb local]# cp redis/bin redis-cluster/redis1
若是你複製過去的redis實例有dump.rdb文件的話最好也要刪除。
第三步:修改配置文件
修改bin目錄下的redis.conf配置文件
第四步:繼續複製5個redis實例
咱們用上面的redis實例複製5個redis實例,而後把他們的配置文件的端口號改成7002-7006
第五步 :新建一個執行腳本: [root@Snailclimb redis-cluster]# vim start-all.sh 腳本內容以下:
cd redis1/bin
./redis-server redis.conf
cd ..
cd ..
cd redis2/bin
./redis-server redis.conf
cd ..
cd ..
cd redis3/bin
./redis-server redis.conf
cd ..
cd ..
cd redis4/bin
./redis-server redis.conf
cd ..
cd ..
cd redis5/bin
./redis-server redis.conf
cd ..
cd ..
cd redis6/bin
./redis-server redis.conf
複製代碼
爲腳本賦予執行權限:
[root@Snailclimb redis-cluster]# chmod u+x start-all.sh
同時啓動6個redis實例:
[root@Snailclimb redis-cluster]# ./start-all.sh
第六步:將redis-trib.rb複製到redis-cluster目錄下面:
併爲腳本賦予執行權限: [root@Snailclimb redis-cluster]# chmod u+x redis-trib.rb第七步:安裝ruby和ruby運行環境
yum install ruby
yum install rubygems
gem install redis-3.0.0.gem
第八步:使用ruby腳本搭建集羣:
[root@Snailclimb redis-cluster]#./redis-trib.rb create --replicas 1 192.168.25.155:7001 192.168.25.155:7002 192.168.25.155:7003 192.168.25.155:7004 192.168.25.155:7005 192.168.25.155:7006
查看集羣:
注意:端口修改錯誤或者沒有將cluster-enabled yes前的註釋去掉都會致使集羣搭建失敗。總的來講,redis集羣搭建仍是很簡單的。
這樣一個完整的redis集羣就已經搭建完畢了。。。
添加Maven依賴:
<!-- Redis客戶端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
複製代碼
單機版redis測試:
@Test
public void testJedis() throws Exception {
// 建立一個鏈接Jedis對象,參數:host、port
Jedis jedis = new Jedis("192.168.25.155", 6379);
// 直接使用jedis操做redis。全部jedis的命令都對應一個方法。
jedis.set("bwcx9393", "歡迎關注Java面試通關手冊");
String string = jedis.get("bwcx9393");
System.out.println(string);//輸出內容:歡迎關注微信公衆號:Java面試通關手冊
// 關閉鏈接
jedis.close();
}
複製代碼
使用鏈接池測試單機版redis:
@Test
public void testJedisPool() throws Exception {
// 建立一個鏈接池對象,兩個參數host、port
JedisPool jedisPool = new JedisPool("192.168.25.155", 6379);
// 從鏈接池得到一個鏈接,就是一個jedis對象。
Jedis jedis = jedisPool.getResource();
// 使用jedis操做redis
String string = jedis.get("bwcx9393");
System.out.println(string);//輸出內容:歡迎關注微信公衆號:Java面試通關手冊
// 關閉鏈接,每次使用完畢後關閉鏈接。鏈接池回收資源。
jedis.close();
// 關閉鏈接池。
jedisPool.close();
}
複製代碼
測試集羣版redis:
@Test
public void testJedisCluster() throws Exception {
// 建立一個JedisCluster對象。有一個參數nodes是一個set類型。set中包含若干個HostAndPort對象。
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.25.155", 7001));
nodes.add(new HostAndPort("192.168.25.155", 7002));
nodes.add(new HostAndPort("192.168.25.155", 7003));
nodes.add(new HostAndPort("192.168.25.155", 7004));
nodes.add(new HostAndPort("192.168.25.155", 7005));
nodes.add(new HostAndPort("192.168.25.155", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
// 直接使用JedisCluster對象操做redis。
jedisCluster.set("test", "123");
String string = jedisCluster.get("test");
System.out.println(string);
// 關閉JedisCluster對象
jedisCluster.close();
}
複製代碼
咱們如何才能在項目中實現本身想用的單機redis就用單機redis想用redis集羣就用redis集羣而不要修改項目代碼呢???
建立相應類和接口
接口:import java.util.List;
public interface JedisClient {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
Boolean hexists(String key, String field);
List<String> hvals(String key);
Long del(String key);
}
複製代碼
集羣版使用:
import java.util.List;
import redis.clients.jedis.JedisCluster;
public class JedisClientCluster implements JedisClient {
private JedisCluster jedisCluster;
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}
@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}
@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
@Override
public Boolean hexists(String key, String field) {
return jedisCluster.hexists(key, field);
}
@Override
public List<String> hvals(String key) {
return jedisCluster.hvals(key);
}
@Override
public Long del(String key) {
return jedisCluster.del(key);
}
}
複製代碼
單機版使用:
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisClientPool implements JedisClient {
private JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}
@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}
@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}
@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}
@Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
}
@Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
}
@Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
}
}
複製代碼
applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 鏈接redis單機版 -->
<bean id="jedisClientPool" class="xx.xx.xx.JedisClientPool">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.155"/>
<constructor-arg name="port" value="6379"/>
</bean>
<!-- 鏈接redis集羣 -->
<!-- <bean id="jedisClientCluster" class="xx.xx.xx.JedisClientCluster"> <property name="jedisCluster" ref="jedisCluster"/> </bean> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg name="nodes"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7001"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7002"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7003"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7004"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7005"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.155"></constructor-arg> <constructor-arg name="port" value="7006"></constructor-arg> </bean> </set> </constructor-arg> </bean> -->
</beans>
複製代碼
測試代碼:
public class JedisClientTest {
@Test
public void testJedisClient() throws Exception {
//初始化spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
//從容器中得到JedisClient對象
JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
jedisClient.set("aaa", "111");
String string = jedisClient.get("aaa");
System.out.println(string);
}
}
複製代碼
這樣在實際項目中咱們無需修改代碼就能夠實現單機和集羣版的相關切換。。
關於Redis的一些常見面試問題總結,我寫了另一篇文章:《面試中關於Redis的問題看這篇就夠了》:juejin.im/post/5ad6e4…
歡迎關注個人微信公衆號:"Java面試通關手冊"(堅持原創,分享美文,分享各類Java學習資源,面試題,以及企業級Java實戰項目回覆關鍵字免費領取):。