ServiceStack.Redis的源码分析

本文详细分析了ServiceStack.Redis的连接池获取RedisClient的流程,从PooledRedisClientManager的GetClient()方法入手,介绍了连接池耗尽后的处理、Client创建过程以及哨兵模式下Master节点的选择策略。通过源码解析,展示了RedisSentinelResolver如何确保连接到Master节点,并涉及异常处理和故障转移机制。
摘要由CSDN通过智能技术生成

前几天在生产环境上redis创建连接方面的故障,分析过程中对ServiceStack.Redis的连接创建和连接池机制有了进一步了解。问题分析结束后,通过此问题系统的将学习到的知识点整理出来。

从连接池获取RedisClient的流程

业务程序中通过PooledRedisClientManager对象的GetClient()方法获取客户端对象,就以此处的源码作为入口:

查看代码

public IRedisClient GetClient()        {            RedisClient redisClient = null;            DateTime now = DateTime.Now;            for (; ; )            {                if (!this.deactiveClientQueue.TryPop(out redisClient))                {                    if (this.redisClientSize >= this.maxRedisClient)                    {                        Thread.Sleep(3);                        if (this.PoolTimeout != null && (DateTime.Now - now).TotalMilliseconds >= (double)this.PoolTimeout.Value)                        {                            break;                        }                    }                    else                    {                        redisClient = this.CreateRedisClient();                        if (redisClient != null)                        {                            goto Block_5;                        }                    }                }                else                {                    if (!redisClient.HadExceptions)                    {                        goto Block_6;                    }                    List<RedisClient> obj = this.writeClients;                    lock (obj)                    {                        this.writeClients.Remove(redisClient);                        this.redisClientSize--;                    }                    RedisState.DisposeDeactivatedClient(redisClient);                }            }            bool flag2 = true;            if (flag2)            {                throw new TimeoutException("Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use.");            }            return redisClient;        Block_5:            this.writeClients.Add(redisClient);            return redisClient;        Block_6:            redisClient.Active = true;            this.InitClient(redisClient);            return redisClient;        }

此方法的主体是死循环,主要实现了这几项功能:

  • this.deactiveClientQueue代表空闲的Client集合,是ConcurrentStack<RedisClient>类型的。
  • 当this.deactiveClientQueue能够Pop出redisClient时,则跳转到Block_6分支:标记redisClient.Active属性,并执行this.InitClient(redisClient),然后将redisClient实例返回。
  • 当this.deactiveClientQueue没有可以Pop的元素时,首先执行Client数量上限的判断this.redisClientSize >= this.maxRedisClient;如果未到达上限,则执行redisClient = this.CreateRedisClient();如果达到上限,则先休眠3毫秒,然后判断是否超过连接池超时时间this.PoolTimeout,单位毫秒。超时的话直接break中断循环,不超时的话继续下一次for循环。

上述流程就是从连接池获取Client的主要流程,其中this.deactiveClientQueue相当于“Client池”。需要注意this.PoolTimeout的含义是当连接池耗尽时调用方等待的时间。

上述过程通过流程图表示为:

创建新Client的过程:CreateRedisClient()

源码如下:

查看代码

 private RedisClient CreateRedisClient(){if (this.redisClientS
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值