I am trying to use the sentinel to get the connection address of my master, the problem is that the sentinel sends the address only on failover, but if my master is down and the slave was promoted master and my application is just booted it would not know and won't get the message that the original master is down, is there any way to communicate with the sentinel and ask him who he thinks the master is using C# servicestack redis client?
Getting Redis Master address from Sentinel C#
Asked Answered
Had to do it the hard way, I imitate the redis-cli command using the next code snippet: (all is left is to parse the result from the response)
public string GetMasterFromSentinel(string sentinelAddress)
{
TcpClient server;
try
{
var splittedAddress = sentinelAddress.Split(':');
server = new TcpClient(splittedAddress[0], splittedAddress[1].ParseInt());
}
catch (SocketException)
{
_log.Error("Unable to connect to server");
return string.Empty;
}
NetworkStream ns = server.GetStream();
var payload = new byte[] { 0x2a, 0x32, 0x0d, 0x0a, 0x24, 0x38, 0x0d, 0x0a, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c,
0x0d, 0x0a, 0x24, 0x37, 0x0d, 0x0a, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x73, 0x0d, 0x0a };
ns.Write(payload, 0, payload.Length);
ns.Flush();
var data = new byte[1024];
ns.Read(data, 0, data.Length);
var recv = ns.Read(data, 0, data.Length);
ns.Close();
server.Close();
return ParseResponse(data);
}
I've write some test code for getting Master's IP and Port --- via IP and Port of (slave or master will work) Sentinel. This code use NuGet package from StackExchange.Redis
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Test
{
public class Sentinel
{
private ConnectionMultiplexer Conn { get; }
private IServer Server { get; }
protected StringWriter ConnectionLog { get; }
public Sentinel()
{
var options = new ConfigurationOptions()
{
CommandMap = CommandMap.Sentinel,
EndPoints = { { "192.168.1.64", 26379 } }, //IP and Port of Sentinel
AllowAdmin = true,
TieBreaker = "",
SyncTimeout = 5000
};
Conn = ConnectionMultiplexer.Connect(options, ConnectionLog);
Server = Conn.GetServer("192.168.1.64", 26379); //IP and Port of Sentinel
}
public void SentinelGetMasterAddressByNameTest(string nameOfMaster)
{
var endpoint = Server.SentinelGetMasterAddressByName(nameOfMaster);
var ipEndPoint = endpoint as IPEndPoint;
Console.WriteLine("The Master's <IP:Port>: {0}:{1}", ipEndPoint.Address, ipEndPoint.Port);
}
}
class Program
{
static void Main(string[] args)
{
var sentinel = new Sentinel();
sentinel.SentinelGetMasterAddressByNameTest("redis-test"); //Passing name of the master
Console.ReadLine();
}
}
}
Had to do it the hard way, I imitate the redis-cli command using the next code snippet: (all is left is to parse the result from the response)
public string GetMasterFromSentinel(string sentinelAddress)
{
TcpClient server;
try
{
var splittedAddress = sentinelAddress.Split(':');
server = new TcpClient(splittedAddress[0], splittedAddress[1].ParseInt());
}
catch (SocketException)
{
_log.Error("Unable to connect to server");
return string.Empty;
}
NetworkStream ns = server.GetStream();
var payload = new byte[] { 0x2a, 0x32, 0x0d, 0x0a, 0x24, 0x38, 0x0d, 0x0a, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c,
0x0d, 0x0a, 0x24, 0x37, 0x0d, 0x0a, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x73, 0x0d, 0x0a };
ns.Write(payload, 0, payload.Length);
ns.Flush();
var data = new byte[1024];
ns.Read(data, 0, data.Length);
var recv = ns.Read(data, 0, data.Length);
ns.Close();
server.Close();
return ParseResponse(data);
}
There's a new
RedisSentinel.GetSentinelInfo()
API that's now available on MyGet. –
Zelikow © 2022 - 2024 — McMap. All rights reserved.
RedisSentinel.GetSentinelInfo()
API that's now available on MyGet. – Zelikow