使用redis时,如果数据量比较大,很容易出现单个redis不够存储的情况,例如数据有10G,而单个redis只能存存储2G的情况,这个时候就需要对redis进行分片存储。
我们需要将10G数据分片存储到多个Redis中,如果直接操作多个客户端无疑是非常麻烦的,不便于管理和使用,我们可以通过在redis上加一层代理来实现数据的统一操作,而具体操作哪个redis则由代理来决定,具体的内部映射规则交由代理实现,我们只需要操作redis代理即可。
实现redis客户端的代理,我们可以通过定义一种规则,建立key值与客户端的映射,这样根据key我们就能获取到相应的客户端,从而进行相应操作。
在使用时,我们直接调用redis客户端代理,然后由代理去进行具体的操作,这样我们在编写代码操作redis时就可以不关注具体的分片细节,简化统一操作。
我们可以简单的通过key的hashcode值来与具体的redisclient建立映射,实现redis客户端代理,简易实现代码如下(这里代码只是说明下原理,节点变更后的数据变更、代理模式、具体代理的位置、hash算法的一致性等等统统没考虑,具体生产使用的集群方案实现有redis cluster、codis、twemproxy等):
public class MyRedisClientProxy {
private ArrayList<StatefulRedisConnection<String, String>> clients;
public MyRedisClientProxy(RedisClient[] redisClients) {
clients = new ArrayList<>();
Arrays.stream(redisClients).forEach(obj -> clients.add(obj.connect()));
}
public void addClient(RedisClient redisClient){
clients.add(redisClient.connect());
}
private StatefulRedisConnection<String, String> getClientByKey(String key){
return clients.get(key.hashCode()%clients.size());
}
public void set(String key, String value){
getClientByKey(key).sync().set(key, value);
}
public String get(String key){
return getClientByKey(key).sync().get(key);
}
}
测试:
@Test
public void testRedisProxy() {
RedisClient[] redisClients = new RedisClient[4];
for (int i = 0; i < 4; i++) {
RedisURI redisURI2 = RedisURI.Builder.redis("127.0.0.1").withPort(6379 + i).withPassword("00000000").build();
redisClients[i] = RedisClient.create(redisURI2);
}
MyRedisClientProxy proxy = new MyRedisClientProxy(redisClients);
for (int i = 0; i < 4; i++) {
proxy.set(i + "", "this is " + i);
}
for (int i = 0; i < 4; i++) {
System.out.println(proxy.get(i + ""));
}
}