http://www.javashuo.com/article/p-eapbamhf-gp.html
http://www.javashuo.com/article/p-kozpdeps-db.html
http://www.javashuo.com/article/p-ozppdxgj-kg.html
只需复制一份配置文件,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:[email protected] slave e7e31b33a9d5174cad30bca246e38cb03d73aa76 0 1550108575491 6 connected # myself代表当前自己连接的服务器 e7e31b33a9d5174cad30bca246e38cb03d73aa76 127.0.0.1:[email protected] myself,master - 0 1550108575000 2 connected 5461-10922 # 这台redis之前是master,被我手动关闭,现在成了fail,之前他的slave6383成了master af4afba85db1489a66067d6007d024b0f1715806 127.0.0.1:[email protected] master,fail - 1550108554453 1550108553000 1 disconnected 27d8e610c2426f21937bd2190d14273c5b64a5f2 127.0.0.1:[email protected] master - 0 1550108577009 7 connected 0-5460 ad88c6649777c407b7feb2170c5a2608693dddcf 127.0.0.1:[email protected] master - 0 1550108575000 3 connected 10923-16383 904bf19376035b3914ea8bc863c0fd8f6e71a306 127.0.0.1:[email protected] 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")); }