本文配置文件部分,进行了引用
https://www.cnblogs.com/zxtceq/p/7676911.html
https://blog.youkuaiyun.com/u010648555/article/details/79430105
https://www.cnblogs.com/yuanermen/p/5717885.html
一个pc运行多个redis
只需复制一份配置文件,redis.conf,改掉其中的一些配置,使两个不冲突即可
# Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
# 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid
daemonize yes
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
# 这里多个配置文件不能相同
pidfile /var/run/redis.pid
# 指定Redis监听端口,默认端口为6379
# 如果指定0端口,表示Redis不监听TCP连接
# 端口不能相同
port 6379
# 指定本地数据库文件名,默认值为dump.rdb
# 工作目录.
# 指定本地数据库存放目录,文件名由上一个dbfilename配置项指定
# 这里路径和文件名的组合 不能冲突
dbfilename dump.rdb
dir ./
然后通过redis-server命令,后接不同的配置文件即可
实现主从复制
在作为从服务器的redis配置文件中加上如下配置即可
# 填写master的ip和端口号
slaveof 127.0.0.1 6379
之后便可以启动两个redis,输入info命令进行查看
此时从服务器只能读,不能写
哨兵模式
需要配合主从使用,自动把从服务器切换成主服务器
建立配置文件sentinel.conf,拷贝多个,此处使用3个即可
# 当前Sentinel服务运行的端口
# 多个配置文件 端口不能相同
port 26379
# 哨兵监听的主服务器
# 后面的数字代表当有足够数量的 Sentinel在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
# 主观下线和客观下线可以网上搜一下
sentinel monitor mymaster 127.0.0.1 6379 1
# 3s内mymaster无响应,则认为mymaster宕机了
sentinel down-after-milliseconds mymaster 3000
# 如果10秒后,mysater仍没启动过来,则启动failover
sentinel failover-timeout mymaster 10000
# 执行故障转移时, 最多有1个从服务器同时对新的主服务器进行同步
sentinel parallel-syncs mymaster 1
然后启动哨兵
redis-sentinel ../sentinel.conf
在人工关闭master之后
redis-cli -p 6379 shutdown
可以看到,从服务器的角色会更改为master
测试代码
package cluster;
/**
* @program: MyMaven
* @description: redis主从切换测试
* @author: dengbin
* @create: 2019-02-12 17:02
**/
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
public class Main {
private static JedisSentinelPool pool = null;
// 自带的哨兵模式 JedisSentinelPool, 并在一开始初始化连接池
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
// 控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
// 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
config.setMaxTotal(Integer.valueOf(1000));
// 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
config.setMaxIdle(Integer.valueOf(20));
// 表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
config.setMinEvictableIdleTimeMillis(Integer.valueOf(-1));
// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
config.setTestOnBorrow(Boolean.valueOf(true));
// master名称和配置文件中配置的要一样
String master = "mymaster";
//setinel客户端提供了master自动发现功能
Set<String> sentinels = new HashSet<String>();
sentinels.add("127.0.0.1:26379");
sentinels.add("127.0.0.1:26380");
pool = new JedisSentinelPool(master, sentinels, config);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 构建redis连接池
*
* @return JedisPool
*/
public static JedisSentinelPool getPool() {
return pool;
}
/**
* 返还到连接池
*
* @param pool
* @param redis
*/
public static void returnResource(JedisSentinelPool pool, Jedis redis) {
if (redis != null) {
try {
pool.returnResource(redis);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 测试redis线程池是否正常
* @param args
*/
public static void main(String[] args) {
JedisSentinelPool pool = Main.getPool();
Jedis redis = pool.getResource();
System.out.println("redis = " + redis);
System.out.println(redis.get("test"));
if(redis != null){
returnResource(pool,redis);
}
}
}
集群模式
此处采用六个redis服务器,一台机器启动多个redis在上文已经写了
在配置文件中更改如下配置,六个配置文件都需要更改,然后启动六台服务器
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_7000.conf //集群的配置 配置文件首次启动自动生成,这个文件名可以和端口对应
cluster-node-timeout 5000 //请求超时 设置5秒够了
官方的redis cluster采用ruby语言,所以需要先安装ruby,自行百度
安装完之后,执行下面的命令
gem install redis #安装redis接口
然后创建集群
# 最后面的1代表一个master一个cluster
redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
可以看到如下提示,代表成功,分了三主三从,一共16384个slots
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:6382 to 127.0.0.1:6379
Adding replica 127.0.0.1:6383 to 127.0.0.1:6380
Adding replica 127.0.0.1:6384 to 127.0.0.1:6381
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: af4afba85db1489a66067d6007d024b0f1715806 127.0.0.1:6379
slots:[0-5460] (5461 slots) master
M: e7e31b33a9d5174cad30bca246e38cb03d73aa76 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
M: ad88c6649777c407b7feb2170c5a2608693dddcf 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
S: 904bf19376035b3914ea8bc863c0fd8f6e71a306 127.0.0.1:6382
replicates ad88c6649777c407b7feb2170c5a2608693dddcf
S: 27d8e610c2426f21937bd2190d14273c5b64a5f2 127.0.0.1:6383
replicates af4afba85db1489a66067d6007d024b0f1715806
S: 780aa05b6f6bb1d23779bd05ec76593f0eb5729a 127.0.0.1:6384
replicates e7e31b33a9d5174cad30bca246e38cb03d73aa76
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: af4afba85db1489a66067d6007d024b0f1715806 127.0.0.1:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 904bf19376035b3914ea8bc863c0fd8f6e71a306 127.0.0.1:6382
slots: (0 slots) slave
replicates ad88c6649777c407b7feb2170c5a2608693dddcf
M: e7e31b33a9d5174cad30bca246e38cb03d73aa76 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 780aa05b6f6bb1d23779bd05ec76593f0eb5729a 127.0.0.1:6384
slots: (0 slots) slave
replicates e7e31b33a9d5174cad30bca246e38cb03d73aa76
S: 27d8e610c2426f21937bd2190d14273c5b64a5f2 127.0.0.1:6383
slots: (0 slots) slave
replicates af4afba85db1489a66067d6007d024b0f1715806
M: ad88c6649777c407b7feb2170c5a2608693dddcf 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
若看到如下报错信息,删除redis的备份文件-dump.rdb,同时在redis执行命令 flushdb,重新执行命令即可
[ERR] Node 127.0.0.1:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
在命令行使用redis集群时,加上-c参数 redis-cli -c -p 6379,否则会提示error,因为这个key不在当前服务器,加上后,在进行操作时,会自动路由到对应的服务器上
连接上任意一台redis服务器,可通过如下命令查看当前节点信息
cluster nodes
780aa05b6f6bb1d23779bd05ec76593f0eb5729a 127.0.0.1:6384@16384 slave e7e31b33a9d5174cad30bca246e38cb03d73aa76 0 1550108575491 6 connected
# myself代表当前自己连接的服务器
e7e31b33a9d5174cad30bca246e38cb03d73aa76 127.0.0.1:6380@16380 myself,master - 0 1550108575000 2 connected 5461-10922
# 这台redis之前是master,被我手动关闭,现在成了fail,之前他的slave6383成了master
af4afba85db1489a66067d6007d024b0f1715806 127.0.0.1:6379@16379 master,fail - 1550108554453 1550108553000 1 disconnected
27d8e610c2426f21937bd2190d14273c5b64a5f2 127.0.0.1:6383@16383 master - 0 1550108577009 7 connected 0-5460
ad88c6649777c407b7feb2170c5a2608693dddcf 127.0.0.1:6381@16381 master - 0 1550108575000 3 connected 10923-16383
904bf19376035b3914ea8bc863c0fd8f6e71a306 127.0.0.1:6382@16382 slave ad88c6649777c407b7feb2170c5a2608693dddcf 0 1550108575593 4 connected
java测试代码
private static JedisCluster jedis;
static {
// 添加集群的服务节点Set集合
Set<HostAndPort> hostAndPortsSet = new HashSet<HostAndPort>();
// 添加节点
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6379));
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6380));
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6381));
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6382));
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6383));
hostAndPortsSet.add(new HostAndPort("127.0.0.1", 6384));
// Jedis连接池配置
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲连接数, 默认8个
jedisPoolConfig.setMaxIdle(100);
// 最大连接数, 默认8个
jedisPoolConfig.setMaxTotal(500);
//最小空闲连接数, 默认0
jedisPoolConfig.setMinIdle(0);
// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
// 设置2秒
jedisPoolConfig.setMaxWaitMillis(2000);
//对拿到的connection进行validateObject校验
jedisPoolConfig.setTestOnBorrow(true);
jedis = new JedisCluster(hostAndPortsSet, jedisPoolConfig);
}
public static void main(String[] args){
System.out.println(jedis.get("1"));
}