目录
一、前言
二、Redis Cluster集群
1、基本原理
2、网络拓扑:
3、通信协议:
4、自动数据分片
5、数据迁移(节点扩缩容)
6、数据离散性
7、应用
三、后话
上一篇文章我们聊到客户端分片(Redis Sharding)技术,这里我们接着聊一下Redis Cluster这种服务端分片的解决方案。我对服务端分片的理解是对1)具体数据片数如何实现;2)服务端的数据的存储、迁移;3)数据分片的高可用对客户端来说就是透明无感的。
Gossip天然是容错的,每个节点既是通信主节点又是通信从节点,网络中每个节点的加入退出都会被相邻节点发现并同步扩散到其他节点,这从另外一个侧面也说明了该网络作为一个整体的整体健壮性。另外,该协议天然对网络质量没有严格要求,因此很多的算法实现基本上是基于UDP,因此从网络层容错来说也算是逻辑自洽。
这个主要从信息同步的速度来讲的。假设网络中有N个节点,那信息同步到全网络的速度理论上仅需为O(log(N))次(具体每个节点一次同步的节点数由fanout参数决定)。还记得高数吗?这种对数函数的收敛速度是很快的。当然,因为它只负责发送而不负责接收确认ACK,也因此存在一定的传播冗余度和非强一致性,但是却能保证最终一致性,我认为它更应该叫具备冗余特性的最终一致性算法。
实际上Gossip协议还是基于一种叫SWIM的可扩展的弱一致性具备传染特性的进程组成员协议( S calable W eakly-consistent I nfection-style Process Group M embership Protocol)。各个节点通过push、pull或push/pull等方式进行节点信息同步以致整个网络达成统一,中间过程不存在所谓的中心节点。
package com.imooc.web.utils;
import redis.clients.util.JedisClusterCRC16;
import java.util.Random;
public class CRC16Util {
/**
* 生成随机Key
*
* @length
* @return
*/
public String getRandomStringwithLength(int length){
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random=new Random();
StringBuffer sb=new StringBuffer();
for(int i=0;i=1 && slot <=4096){
node1Count++;
}else if(slot >=4097 && slot <8192){
node2Count++;
}else if(slot >=8193 && slot <12288){
node3Count++;
}else{
node4Count++;
}
totalCount = node1Count+node2Count+node3Count+node4Count;
}
}
System.out.println("总共" + totalCount + "条记录");
System.out.println("节点1:"+ node1Count + "条记录");
System.out.println("节点2:"+ node2Count + "条记录");
System.out.println("节点3:"+ node3Count + "条记录");
System.out.println("节点4:"+ node4Count + "条记录");
}
}
redis.clients
jedis
2.8.0
RedisConfiguration.java
@Configuration
public class RedisConfiguration {
@Bean
public JedisCluster jedisCluser(){
Set set = new HashSet<>();
set.add(new HostAndPort("192.168.32.101", 6379));
set.add(new HostAndPort("192.168.32.102", 6380));
set.add(new HostAndPort("192.168.32.103", 6381));
JedisCluster jedisCluster = new JedisCluster(set);
return jedisCluster;
}
}
RedisConfigurationTest.java
@Configuration
public class RedisConfigurationTest {
@Test
public void testCluster (){
ApplicationContext ctx = new AnnotationConfigApplicationContext(RedisClusterTest.class);
JedisCluster jedisCluster = ctx.getBean(JedisCluster.class);
jedisCluster.set("redisCluster4Test", "2016-3-22");
String value = jedisCluster.get("redisCluster4Test");
System.out.println(value);
}
}