/// <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); }
// 初始化集群管理 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(); } }
// 重新刷新集群信息 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); } } }