运行结果
==========>>>>RedisKey:user:001:name 被路由到服务器:192.168.222.101 ==========>>>>RedisKey:user:001:age 被路由到服务器:192.168.222.101 ==========>>>>RedisKey:user:001:sex 被路由到服务器:192.168.222.101
可以看出 , Redis的key被路由到同一个节点了 , 我们使用增加虚拟节点来避免折中情况 。
一致性hash算法(有虚拟节点)
public class HashDemo2 { public static void main(String[] args) { //step1 初始化:把服务器节点IP的哈希值对应到哈希环上 // 定义服务器ip String[] servers = new String[]{"192.167.222.101", "192.168.222.103", "191.169.222.123"}; // 创建一个排序的hashMap,key存储hash值 , value存储服务器IP地址 , 并按照Hash值排序 SortedMap hashServerMap = new TreeMap<>(); // 定义针对每个真实服务器虚拟出来?个节点 int virtualCount = 3; for (String redisServer : servers) { // 求出每?个ip的hash值 , 对应到hash环上 , 存储hash值与ip的对应关系 int serverHash = Math.abs(redisServer.hashCode()); // 存储hash值与ip的对应关系 hashServerMap.put(serverHash, redisServer); // 处理虚拟节点 for(int i = 0; i < virtualCount; i++) { int virtualHash = Math.abs((redisServer + "#" + i).hashCode()); hashServerMap.put(virtualHash,"----由虚拟节点"+ i + "映射过来的请求:"+ redisServer); } } //step2 针对客户端IP求出hash值 // 定义客户端传递过来的RedisKey String[] redisKeys = new String[]{ "user:001:name", "order:001:name", "product:001:name", "user:002:name", "order:002:name", "product:002:name", }; for (String redisKey : redisKeys) { // 计算redisKey的hash值 int redisKeyHash = Math.abs(redisKey.hashCode()); //step3 针对客户端,找到能够处理当前RedisKey的服务器(哈希环上顺时针最近) // 根据redisKey的哈希值去找出哪?个服务器节点能够处理 // tailMap返回此映射的键大于或等于fromKey的部分 , 也就是比redisKey的hash值大的排序列表 , 取第一个就是最近的服务器节点 SortedMap filteredSortedMap = hashServerMap.tailMap(redisKeyHash); // 获取key落到那台服务器 , filteredSortrdMap为空 , 直接取服务器列表hashServerMap第一个 , 不为空 , 则取出最近一个filteredSortrdMap Integer hashKey = filteredSortedMap.isEmpty() ? hashServerMap.firstKey() : filteredSortedMap.firstKey(); System.out.println("==========>>>>RedisKey:" + redisKey + " 被路由到服务器:" + hashServerMap.get(hashKey)); } } }
运行结果
==========>>>>RedisKey:user:001:name 被路由到服务器:192.167.222.101 ==========>>>>RedisKey:order:001:name 被路由到服务器:191.169.222.123 ==========>>>>RedisKey:product:001:name 被路由到服务器:191.169.222.123 ==========>>>>RedisKey:user:002:name 被路由到服务器:----由虚拟节点2映射过来的请求:191.169.222.123 ==========>>>>RedisKey:order:002:name 被路由到服务器:191.169.222.123 ==========>>>>RedisKey:product:002:name 被路由到服务器:191.169.222.123
可以看出 , 虚拟节点确实生效了 。
2、Redis集群
Redis3.0之后 , Redis官方提供了完整的集群解决方案 , 称为Rediscluster 。
Redis集群方案采用去中心化的方式 , 包括:sharding(分区)、replication(复制)、failover(故障转移) 。
Redis5.0前采用redis-trib进行集群的创建和管理 , 需要ruby支持 。Redis5.0可以直接使用Redis-cli进行集群的创建和管理 。
2.1、Redis集群部署架构
文章插图
Redis的部署架构时没有中心的 , 每个节点都是主节点 , 是一个P2P(点对点)的去中心化集群架构 , 依靠gossip协议用于集群间传播 。
2.2、Gossip协议
Gossip协议是一个通信协议 , 一种传播消息的方式 , 它起源于病毒传播 。
Gossip协议基本思想
一个节点周期性(每秒)随机选择一些节点 , 并把信息传递给这些节点 。
这些收到信息的节点接下来会做同样的事情 , 即把这些信息传递给其他一些随机选择的节点 。
信息会周期性的传递给N个目标节点 。这个N被称为fanout(扇出) 。
gossip协议包含多种消息 , 包括meet、ping、pong、fail、publish等等 。
推荐阅读
- Redis 的大 Key 对持久化有什么影响?
- 手机防窥膜的原理是什么?真的会影响视力吗?
- 碘酒消毒的原理是什么?
- 三大指纹识别原理 指纹识别技术
- 玄空风水原理和方法 大玄空风水
- 图解涡轮增压器工作原理 涡轮增压器工作原理
- 跳绳减肥原理是什么
- 瘦身舞蹈瘦腿的原理是什么?
- 详解反渗透膜(RO 反渗透膜原理工作原理)
- 精索静脉曲张手术原理
