前言,Redis寫過一篇,雖然自己覺得內容很實用,但是寫的不詳細與清晰,後來自己看也挺費勁。於是這裏重新寫下。
1、Redis單機搭建。單機也很重要,這裏記錄下。
1、官網下載包。我首先使用的2.x搭建單機方便後續完成手動主從與哨兵搭建。
2、環境下載安裝。yum -y install gcc tcl
3、redis包解壓。tar zxvf redis-2.8.18.tar.gz
4、安裝 .make && make /opt/cloudwise/redis install
5、環境變量。 vi /etc/profile 在後面配置中加 export REDIS_PREFIX=/opt/cloudwise/redis
6、服務開啓.。/opt/cloudwise/redis/bin/redis-server
7、Jedis操作單機redis並能插入數據到對應數據庫實例中。
package com.cloudwise.redis;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import redis.clients.jedis.Jedis;
/**
* jedis單實例 可以哨兵來做ha 但是沒有解決單點瓶頸
* <p>Title: JedisDaoImpl</p>
* <p>Description: </p>
* @author back
* @date 2019年9月19日
*/
public class JedisDaoImpl implements RedisDao{
private Jedis jedis;
private int db;
public JedisDaoImpl(int dbNum){
jedis = new Jedis("192.168.231.131", 6379,1500);
this.db = dbNum;
jedis.select(db);
}
@Override
public boolean isExist(String key) {
return jedis.exists(key);
}
@Override
public String set(String key, String value) {
return jedis.set(key, value);
}
@Override
public String get(String key) {
return jedis.get(key);
}
@Override
public String setex(String key, String value, int seconds) {
return jedis.setex(key, seconds, value);
}
@Override
public long delete(String key) {
return jedis.del(key);
}
@Override
public long incr(String key) {
return jedis.incr(key);
}
/**
* 測試對應db中寫數據,經測試成功。
* @param args
*/
public static void main(String[] args) {
ExecutorService execotor = Executors.newFixedThreadPool(2);
for (int i = 1; i < 3; i++) {
execotor.execute(new Task(i));
}
execotor.shutdown();
}
}
二、Redis主從。手動切換、哨兵模式兩種。
1)手動切換。
主節點服務:redis-server --port 6380
從節點服務:redis-server --port 6380 --slaveof 192.168.231.131 6380
手動主從成功。
主節點故障時,從節點執行SLAVEOF no one.執行的從節點成爲主節點。
2)哨兵模式。
內置哨兵命令位置:redis-2.8.18/src/redis-sentinel.將它防置redis設置的環境變量的bin目錄。
找個目錄添加文件,我的目錄爲:~/sentinel/s1.conf
內容爲:port爲當前哨兵端口。cloudwise爲redis集羣名稱,自定義一個即可。後面的ip與端口爲主redis節點地址。最後面的2爲投票數。比如我有三個哨兵節點,當主節點掛掉,從節點有多個,三個哨兵節點投票,如果有兩票在某一從節點上,則該從節點提升爲主節點。
服務開啓:
主節點:redis-server 從節點:redis-server --SLAVEOF 192.168.231.134 6379
redis節點開啓後開啓哨兵。redis-sentinel ~/sentinel/s1.conf
Java 操作哨兵模式:實測好用
package com.cloudwise.redis;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Sets;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
/**
* 哨兵模式
* <p>Title: SentinelPoolRedisDao</p>
* <p>Description: </p>
* @author back
* @date 2019年9月19日
*/
public class SentinelPoolRedisDao implements RedisDao{
private JedisSentinelPool pool ;
private Jedis jedis;
public SentinelPoolRedisDao(int num){
pool = JedisAllPoolFactory.getJedisSentinelPool();
this.jedis = pool.getResource();
this.jedis.select(num);
}
@Override
public boolean isExist(String key) {
return jedis.exists(key);
}
@Override
public String set(String key, String value) {
return jedis.set(key, value);
}
@Override
public String get(String key) {
return jedis.get(key);
}
@Override
public String setex(String key, String value, int seconds) {
return jedis.setex(key, seconds, value);
}
@Override
public long delete(String key) {
return jedis.del(key);
}
@Override
public long incr(String key) {
return jedis.incr(key);
}
public static void main(String[] args) {
SentinelPoolRedisDao dao = new SentinelPoolRedisDao(1);
dao.set("cc", "b");
System.out.println("成功! 拿到value:"+dao.get("cc"));
}
}
三、各種redis集羣方案配置
1、codis做redis集羣
1),下載codis,我在git上下的3.1 release版本。安裝jdk要求1.8以上。jdk環境變量設置等就不再說了
2),安裝go環境。我安裝的 go1.6.2.linux-amd64 。go環境變量如圖。這裏注意GOPATH是爲codis而設置的,codis的安裝目錄。不設置安裝會報錯。
3)安裝zookeeper集羣。這裏不再介紹。
4)下載的codis安裝包解壓後放入:/opt/cloudwise/codis/src/github.com/CodisLabs/ 目錄下 前面的/opt/cloudwise/codis爲GOPATH中設置的。後面的一定要如此。否則安裝會報錯。正確的路徑如圖所示:
5) 在上面的目錄下 yum install autoconf
6)當前目錄 make
7)config目錄下dashboard.toml vi /opt/cloudwise/codis/src/github.com/CodisLabs/codis/config/dashboard.toml。coordinator設置zookeeper地址。把原來的filesystem的註釋掉。admin_addr爲本機ip
8)開啓codis組件dashboard進程。nohup ./bin/codis-dashboard --ncpu=1 --config=./config/dashboard.toml --log=dashboard.log –log-level=WARN &
設置cpu核數 config路徑 log輸出文件與日誌級別。開啓成功則在zookeeper有codis節點。
停止進程:./bin/codis-admin --dashboard=192.168.231.133:18080 --shutdown
9)config目錄下proxy.toml vi /opt/cloudwise/codis/src/github.com/CodisLabs/codis/config/proxy.toml。設置本地和代理ip 端口
10)開啓codis組件proxy。nohup ./bin/codis-proxy --ncpu=1 --config=./config/proxy.toml --log=proxy.log --log-level=WARN &
停止進程:./bin/codis-admin --proxy=192.168.231.133:11080 –auth=”” --shutdown
11)此時proxy還沒有添加到集羣。./bin/codis-admin --dashboard=192.168.231.133:18080 –create-proxy -x 192.168.247.133:11080 這個命令添加到集羣。在 proxy.log日誌中能看到效果。
12)啓動redis-server。修改config/redis.conf.redis綁定IP 和保護模式的設置。
13)啓動codis-fe:nohup ./bin/codis-fe --ncpu=1 --log=fe.log --log-level=WARN --zookeeper=192.168.231.135:2181 --listen=192.168.231.133:8080 &
前一個參數是zk的地址端口,後面一個是fe的地址端口
各種pool的工廠
package com.cloudwise.redis;
import java.util.Arrays;
import java.util.Set;
import com.google.common.collect.Sets;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
/**
* 防止重複代碼的 獲取各種pool的工廠
* <p>Title: JedisAllPoolFactory</p>
* <p>Description: </p>
* @author back
* @date 2019年9月19日
*/
public class JedisAllPoolFactory {
private static JedisPoolConfig getConfig(){
JedisPoolConfig config = new JedisPoolConfig();
//最大連接數
config.setMaxTotal(30);
//最大空閒連接數
config.setMaxIdle(10);
//每次釋放連接的最大數目
config.setNumTestsPerEvictionRun(1024);
// 釋放連接的掃描間隔(毫秒)
config.setTimeBetweenEvictionRunsMillis(30000);
//連接最小空閒時間
config.setMinEvictableIdleTimeMillis(1800000);
//連接空閒多久後釋放, 當空閒時間>該值 且 空閒連接>最大空閒連接數 時直接釋放
config.setSoftMinEvictableIdleTimeMillis(10000);
//獲取連接時的最大等待毫秒數,小於零:阻塞不確定的時間,默認-1
config.setMaxWaitMillis(1500);
//在獲取連接的時候檢查有效性, 默認false
config.setTestOnBorrow(true);
//在空閒時檢查有效性, 默認false
config.setTestWhileIdle(true);
//連接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true
config.setBlockWhenExhausted(false);
return config;
}
/**
* 單機的pool
* @return
*/
public static JedisPool getJedisPool(){
JedisPoolConfig config = getConfig();
JedisPool pool = new JedisPool(config, "192.168.231.131", 6379,15000);
return pool;
}
public static JedisSentinelPool getJedisSentinelPool(){
String hosts = "";
JedisPoolConfig config = getConfig();
Set<String> sentinels = transferHostsForSentinel(hosts);
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, config, 15000);
return pool;
}
public static JedisCluster getJedisCluster(){
String hosts = "192.168.231.131:6379";
Set<HostAndPort> nodes = transferHostsForJedisCluster(hosts);
JedisPoolConfig config = getConfig();
JedisCluster jedisCluster = new JedisCluster(nodes, config);
return jedisCluster;
}
private static Set<HostAndPort> transferHostsForJedisCluster(String hosts){
Set<HostAndPort> set = Sets.newHashSet();
Arrays.asList(hosts.split(",")).forEach(host1 -> {
String[] meta = host1.trim().split(":");
HostAndPort hostAndPort = new HostAndPort(meta[0].trim(),Integer.parseInt(meta[1].trim()));
set.add(hostAndPort);
});
return set;
}
private static Set<String> transferHostsForSentinel(String hosts){
Set<String> set = Sets.newHashSet(Arrays.asList(
hosts.split(",")
));
return set;
}
}