Beispiel #1
0
        /// <summary>
        /// 配置 REDIS 集群
        /// </summary>
        /// <param name="nodes">集群节点</param>
        /// <param name="config"><see cref="RedisClientManagerConfig"/> 客户端缓冲池配置</param>
        /// <returns></returns>
        public static RedisCluster Configure(IEnumerable <ClusterNode> nodes, RedisClientManagerConfig config)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }

            if (nodes == null || nodes.Count() == 0)
            {
                throw new ArgumentException("There is no nodes to configure cluster.");
            }

            if (_cluster == null)
            {
                lock (_factory)
                {
                    if (_cluster == null)
                    {
                        RedisCluster c = new RedisCluster(nodes, config);
                        _cluster = c;
                    }
                }
            }

            return(_cluster);
        }
Beispiel #2
0
        // 初始化集群管理
        void Initialize(IList <InternalClusterNode> clusterNodes = null)
        {
            // 从 redis 读取集群信息
            IList <InternalClusterNode> nodes = clusterNodes == null?RedisCluster.ReadClusterNodes(_source) : clusterNodes;

            // 生成主节点,每个主节点的 slot 对应一个REDIS客户端缓冲池管理器
            IList <InternalClusterNode> masters = null;
            IDictionary <int, PooledRedisClientManager> managers = null;

            foreach (var n in nodes)
            {
                // 节点无效或者
                if (!(n.IsMater &&
                      !string.IsNullOrEmpty(n.Host) &&
                      string.IsNullOrEmpty(n.NodeFlag) &&
                      (string.IsNullOrEmpty(n.LinkState) || n.LinkState == InternalClusterNode.CONNECTED)))
                {
                    continue;
                }

                n.SlaveNodes = nodes.Where(x => x.MasterNodeId == n.NodeId);
                if (masters == null)
                {
                    masters = new List <InternalClusterNode>();
                }
                masters.Add(n);

                // 用每一个主节点的哈希槽做键,导入REDIS客户端缓冲池管理器
                // 然后,方法表指针(又名类型对象指针)上场,占据 4 个字节。 4 * 16384 / 1024 = 64KB
                if (managers == null)
                {
                    managers = new Dictionary <int, PooledRedisClientManager>();
                }

                string[] writeHosts = new[] { n.HostString };
                string[] readHosts  = n.SlaveNodes.Where(n => false).Select(n => n.HostString).ToArray();
                var      pool       = new PooledRedisClientManager(writeHosts, readHosts, _config);
                managers.Add(n.Slot.Start, pool);
                if (n.Slot.End != null)
                {
                    // 这个范围内的哈希槽都用同一个缓冲池
                    for (int s = n.Slot.Start + 1; s <= n.Slot.End.Value; s++)
                    {
                        managers.Add(s, pool);
                    }
                }
                if (n.RestSlots != null)
                {
                    foreach (var slot in n.RestSlots)
                    {
                        managers.Add(slot.Start, pool);
                        if (slot.End != null)
                        {
                            // 这个范围内的哈希槽都用同一个缓冲池
                            for (int s = slot.Start + 1; s <= slot.End.Value; s++)
                            {
                                managers.Add(s, pool);
                            }
                        }
                    }
                }
            }

            _masters             = masters;
            _redisClientManagers = managers;
            _clusterNodes        = nodes != null ? nodes : null;

            if (_masters == null)
            {
                _masters = new List <InternalClusterNode>(0);
            }
            if (_clusterNodes == null)
            {
                _clusterNodes = new List <InternalClusterNode>(0);
            }
            if (_redisClientManagers == null)
            {
                _redisClientManagers = new Dictionary <int, PooledRedisClientManager>(0);
            }

            if (_masters.Count > 0)
            {
                _source = _masters.Select(n => new ClusterNode(n.Host, n.Port, n.Password)).ToList();
            }
        }
Beispiel #3
0
        // 重新刷新集群信息
        private bool DiscoveryNodes(IEnumerable <ClusterNode> source, RedisClientManagerConfig config)
        {
            bool lockTaken = false;

            try
            {
                // noop
                if (_isDiscoverying)
                {
                }

                Monitor.Enter(_objLock, ref lockTaken);

                _source         = source;
                _config         = config;
                _isDiscoverying = true;

                // 跟上次同步时间相隔 {MONITORINTERVAL} 秒钟以上才需要同步
                if ((DateTime.Now - _lastDiscoveryTime).TotalMilliseconds >= MONITORINTERVAL)
                {
                    bool isRefresh = false;
                    IList <InternalClusterNode> newNodes = RedisCluster.ReadClusterNodes(_source);
                    foreach (var node in newNodes)
                    {
                        var n = _clusterNodes.FirstOrDefault(x => x.HostString == node.HostString);
                        isRefresh =
                            n == null ||                        // 新节点
                            n.Password != node.Password ||      // 密码变了
                            n.IsMater != node.IsMater ||        // 主变从或者从变主
                            n.IsSlave != node.IsSlave ||        // 主变从或者从变主
                            n.NodeFlag != node.NodeFlag ||      // 节点标记位变了
                            n.LinkState != node.LinkState ||    // 节点状态位变了
                            n.Slot.Start != node.Slot.Start ||  // 哈希槽变了
                            n.Slot.End != node.Slot.End ||      // 哈希槽变了
                            (n.RestSlots == null && node.RestSlots != null) ||
                            (n.RestSlots != null && node.RestSlots == null);
                        if (!isRefresh && n.RestSlots != null && node.RestSlots != null)
                        {
                            var slots1 = n.RestSlots.OrderBy(x => x.Start).ToList();
                            var slots2 = node.RestSlots.OrderBy(x => x.Start).ToList();
                            for (int index = 0; index < slots1.Count; index++)
                            {
                                isRefresh =
                                    slots1[index].Start != slots2[index].Start ||   // 哈希槽变了
                                    slots1[index].End != slots2[index].End;         // 哈希槽变了
                                if (isRefresh)
                                {
                                    break;
                                }
                            }
                        }

                        if (isRefresh)
                        {
                            break;
                        }
                    }

                    if (isRefresh)
                    {
                        // 重新初始化集群
                        this.Dispose();
                        this.Initialize(newNodes);
                        this._lastDiscoveryTime = DateTime.Now;
                    }
                }

                // 最后刷新时间在 {MONITORINTERVAL} 内,表示是最新群集信息 newest
                return((DateTime.Now - _lastDiscoveryTime).TotalMilliseconds < MONITORINTERVAL);
            }
            finally
            {
                if (lockTaken)
                {
                    _isDiscoverying = false;
                    Monitor.Exit(_objLock);
                }
            }
        }