Redis链接字符串可以提出来放到 Config文件当中:

  <connectionStrings>
    <add name="Connection_Redis" connectionString="127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,password=123456,abortConnect=false" />
  </connectionStrings>

当有多个Redis实例时,可以设置链接多个实例,中间用逗号分隔即可(比如:使用Redis集群)。

public class RedisCacheHelper
{
    private readonly Logger _log = LogManager.GetCurrentClassLogger();

    /// <summary>
    /// 连接字符串
    /// </summary>
    private static string _connectionString;

    /// <summary>
    /// redis 连接对象
    /// </summary>
    private static IConnectionMultiplexer _connMultiplexer;

    /// <summary>
    /// 实例化对象
    /// </summary>
    private static RedisCacheHelper _cacheHelper;
    /// <summary>
    /// 实例
    /// </summary>
    private static RedisCacheHelper _instance;

    /// <summary>
    /// 锁
    /// </summary>
    private static readonly object Locker = new object();

    /// <summary>
    /// 数据库
    /// </summary>
    private IDatabase _db;


    /// <summary>
    /// 默认链接实例
    /// </summary>
    private RedisCacheHelper()
    {
        _connectionString = ConfigurationManager.ConnectionStrings["Connection_Redis"].ConnectionString;
        _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
        //添加注册事件
        AddRegisterEvent();
    }

    /// <summary>
    /// 获取 Redis 连接对象
    /// </summary>
    private IConnectionMultiplexer Connnection
    {
        get
        {
            if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
            {
                lock (Locker)
                {
                    if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
                    {
                        _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
                    }
                }
            }
            return _connMultiplexer;
        }
    }

    /// <summary>
    /// 获取指定db,默认不指定
    /// </summary>
    /// <param name="db"></param>
    /// <returns></returns>
    private IDatabase GetDatabase(int db = -1)
    {
        return Connnection.GetDatabase(db);
    }

    /// <summary>
    /// 调用实例,通过该实例调用Redis
    /// </summary>
    public static RedisCacheHelper Instance
    {
        get
        {
            if (_cacheHelper != null) return _cacheHelper;
            lock (Locker)
            {
                if (_cacheHelper != null) return _cacheHelper;
                _cacheHelper = new RedisCacheHelper();
            }
            return _cacheHelper;
        }
    }

    #region 注册事件

    /// <summary>
    /// 添加注册事件
    /// </summary>
    private void AddRegisterEvent()
    {
        _connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
        _connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
        _connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
        _connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
        _connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
        _connMultiplexer.InternalError += ConnMultiplexer_InternalError;
        _connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
    }

    /// <summary>
    /// 重新配置广播时(通常意味着主从同步更改)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
    {
        _log.Info($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
    }

    /// <summary>
    /// 发生内部错误时(主要用于调试)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
    {
        _log.Error($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
    }

    /// <summary>
    /// 更改集群时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
    {
        _log.Info(
            $"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}");
    }

    /// <summary>
    /// 配置更改时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
    {
        _log.Info($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
    }

    /// <summary>
    /// 发生错误时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
    {
        _log.Error($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
    }

    /// <summary>
    /// 物理连接失败时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
    {
        _log.Fatal($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
    }

    /// <summary>
    /// 建立物理连接时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
    {
        _log.Info($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
    }

    #endregion
}

以上Redis链接就配置好了,使用方式如下:首先在把集群中的主从服务都开启,3主、3从
在这里插入图片描述

然后在代码中进行操作验证,向缓存中插入一条数据,然后循环读写数据,循环的时候手动任意关闭Redis服务当中的 1~2个 服务器

while (true)
            {
                //设置age
                RedisCacheHelper.Instance.Set("age", "10", new TimeSpan(0, 5, 0));

                //获取age
                var getage = RedisCacheHelper.Instance.Get("age");
                Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + ":" + getage);

                Thread.Sleep(1000); // 等待1s
            }
//设置name
RedisCacheHelper.Instance.Set("name", "李四", new TimeSpan(0, 2, 0));
RedisCacheHelper.Instance.Set("age", "10", new TimeSpan(0, 2, 0));

//获取name
var getname = RedisCacheHelper.Instance.Get("name");
Console.WriteLine(getname);

//获取age
var getage = RedisCacheHelper.Instance.Get("age");
Console.WriteLine(getage);

成功将缓存存入到服务器当中,运行效果如下:
在这里插入图片描述
此时查看Redis集群,发现主从实例都有数据了,接下来我们把其中任意1个 Redis实例关掉 (上边运行的循环代码程序不要关闭)
在这里插入图片描述
发现程序正常运行:
在这里插入图片描述
但是上边的步骤,我经过多次测试,在任意关闭某个实例的时候,偶尔会报如下错误:集群挂了
在这里插入图片描述
我们把写的方法注释掉,只保留读取的代码,同样会偶尔报异常。
在这里插入图片描述
但是大部分情况下,关掉其中一个实例,程序都正常运行:
在这里插入图片描述
在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐