Redis——Lettuce的主从哨兵模式

x33g5p2x  于2022-05-05 转载在 Redis  
字(4.2k)|赞(0)|评价(0)|浏览(727)

Lettuce操作主从服务器使用的是MasterReplica.connect()方法创建的主从专用StatefulRedisMasterReplicaConnection,跟普通的通过client创建有点区别,Lettuce连接哨兵则使用client的connectSentinel()方法,创建的是哨兵专用的StatefulRedisSentinelConnection;

另外,主从模式可以设置ReadFrom读取数据来源:(还是挺方便的)

  • MASTER:只从主服务读取数据;
  • MASTER_PREFERRED:优先从主服务读取数据,主服务不可用时再从从服务读取;
  • UPSTREAM:同MASTER;
  • UPSTREAM_PREFERRED:同MASTER_PREFERRED;
  • REPLICA_PREFERRED:优先从从服务读取数据,没有可用从服务时再从主服务读取;
  • REPLICA:只从从服务读取数据;
  • LOWEST_LATENCY:使用延迟低的读取;
  • ANY:可从任何节点读取;
  • ANY_REPLICA:从任何从服务读取;

测试Demo:

使用的redis版本6.2.6,Lettuce版本6.1.8;

主从redis:192.168.1.31:6379、192.168.1.31:6380、192.168.1.31:6381;

哨兵:192.168.1.31:26379;

/**
 * 2022年4月29日下午2:46:43
 */
package testlettuce;

import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import io.lettuce.core.ClientOptions;
import io.lettuce.core.ReadFrom;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.codec.StringCodec;
import io.lettuce.core.masterreplica.MasterReplica;
import io.lettuce.core.masterreplica.StatefulRedisMasterReplicaConnection;
import io.lettuce.core.pubsub.RedisPubSubListener;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands;
import io.lettuce.core.sentinel.api.StatefulRedisSentinelConnection;
import io.lettuce.core.sentinel.api.sync.RedisSentinelCommands;

/**
 * @author XWF
 *
 */
public class TestLettuceMasterReplicaAndSentinel {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//sentinel
		RedisURI sentinelUri = RedisURI.builder()
				.withSentinel("192.168.1.31", 26379, "111111")	//哨兵地址和密码
				.withSentinelMasterId("mymaster")
				.withPassword("123456".toCharArray())
				.build();
		RedisClient sentinelClient = RedisClient.create(sentinelUri);
		StatefulRedisSentinelConnection<String, String> sentinelConn = sentinelClient.connectSentinel();
		RedisSentinelCommands<String, String> sentinelCmd = sentinelConn.sync();
		System.out.println(sentinelCmd.info("sentinel"));
		List<Map<String, String>> masters = sentinelCmd.masters();
		System.out.println(masters);
		Map<String, String> mymaster = sentinelCmd.master("mymaster");
		System.out.println(mymaster.get("name") + "," + mymaster.get("ip") + "," + mymaster.get("port"));
		List<Map<String, String>> slaves = sentinelCmd.slaves("mymaster");
		slaves.forEach(x -> {
			System.out.println(x.get("ip") + ":" + x.get("port"));
		});
		
		StatefulRedisPubSubConnection<String, String> sentinelPubSubConn = sentinelClient.connectPubSub();//需要设置主从密码
		sentinelPubSubConn.addListener(new RedisPubSubListener<String, String>() {
			@Override
			public void unsubscribed(String channel, long count) {
				System.out.println(String.format("unsubscribed:%s", channel));
			}
			@Override
			public void subscribed(String channel, long count) {
				System.out.println(String.format("subscribed:%s", channel));
			}
			@Override
			public void punsubscribed(String pattern, long count) {
			}
			@Override
			public void psubscribed(String pattern, long count) {
			}
			@Override
			public void message(String pattern, String channel, String message) {
			}
			@Override
			public void message(String channel, String message) {
				System.out.println(String.format("message:%s -> %s", channel, message));
			}
		});
		RedisPubSubCommands<String, String> sentinelPubSubCmd = sentinelPubSubConn.sync();
		sentinelPubSubCmd.subscribe("__sentinel__:hello");
		
		try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}
		
		sentinelPubSubCmd.unsubscribe("__sentinel__:hello");
		
		//MasterReplica
		RedisClient client = RedisClient.create();
		ClientOptions options = ClientOptions.builder()
				.autoReconnect(true)	//是否自动重连
				.pingBeforeActivateConnection(true)	//连接激活之前是否执行PING命令
				.build();
		client.setOptions(options);
		StatefulRedisMasterReplicaConnection<String, String> conn = MasterReplica.connect(client, StringCodec.UTF8, sentinelUri);
		conn.setReadFrom(ReadFrom.ANY);		//设置可从任何一个服务读数据
		for (int i = 0; i < 5; i++) {
			try {
				RedisCommands<String, String> cmd = conn.sync();
				cmd.set("aa", String.valueOf(i));
				System.out.print(cmd.get("aa") + "--");
				Stream.of(cmd.info("server").split("\n")).filter(x -> x.startsWith("tcp_port")).forEach(System.out::print);
			} catch (Exception e) {
				System.err.println(e);
			}
		}
	}

}

运行结果:

相关文章

最新文章

更多