前言,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;
}
}