welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ群:162333776 邮箱:admin@xlongwei.com

jedis sharded 分片模式


分类 Java   关键字 分享   标签 java   linux   spring   redis   发布 hongwei  1470980781404
注意 转载须保留原文链接,译文链接,作者译者等信息。  
redis有三种工作模式:单机模式、分片模式、集群模式。集群模式比较复杂,分片模式可以将数据分散缓存到多个目标,简单高效。

分片模式示例,此时各redis实例是彼此独立的,也不需要开启cluster功能。
List<JedisShardInfo> nodes = new ArrayList<>();
nodes.add(new JedisShardInfo("127.0.0.1", 6379));
nodes.add(new JedisShardInfo("127.0.0.1", 6380));
nodes.add(new JedisShardInfo("127.0.0.1", 6381));

ShardedJedis shardedJedis = new ShardedJedis(nodes2);
for(int i=0;i<10;i++) {
String key = "test-"+i, value="value-"+i;
shardedJedis.set(key, value);
System.out.println(shardedJedis.get(key));
}

spring-data-redis封装了jedis,并且支持缓存框架@Cacheable等,但RedisTemplate、RedisCacheManager等是对应的是单机模式,因此需要对分片模式手动实现
public class MyShardedRedisCacheManager implements CacheManager, DisposableBean {
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
private final Collection<String> names = new HashSet(caches.keySet());
private ShardedJedis shardedJedis;
private RedisCachePrefix cachePrefix = new DefaultRedisCachePrefix();
private RedisSerializer keySerializer = new StringRedisSerializer();//键最好是String类型
private RedisSerializer valueSerializer = new JdkSerializationRedisSerializer();//值序列化方式可自定义
private long defaultExpiration = 604800L;//默认7天超时
private Map<String, Long> expires = null;

public void setHostsAndPorts(String hostsAndPorts) {
String[] hostAndPortArray = hostsAndPorts.split("[,;]");
List<JedisShardInfo> nodes = new ArrayList<>();
for(String hostAndPort : hostAndPortArray) {
String[] hostPort = hostAndPort.split("[:]");
nodes.add(new JedisShardInfo(hostPort[0], Integer.parseInt(hostPort[1])));
}
shardedJedis = new ShardedJedis(nodes);
}

public static class MyShardedRedisCache implements Cache {
private static final int PAGE_SIZE = 128;
private final String name;
private final ShardedJedis shardedJedis;
private final RedisSerializer keySerializer, valueSerializer;
private final byte[] prefix;
private final byte[] setName;
private final long expiration;

MyShardedRedisCache(String name, byte[] prefix, MyShardedRedisCacheManager myShardedRedisCacheManager, long expiration) {
this.name = name;
this.shardedJedis = myShardedRedisCacheManager.shardedJedis;
this.keySerializer = myShardedRedisCacheManager.keySerializer;
this.valueSerializer = myShardedRedisCacheManager.valueSerializer;
this.prefix = prefix;
this.expiration = expiration;
this.setName = keySerializer.serialize(name + "~keys");
}

@Override
public ValueWrapper get(Object key) {
byte[] computeKey = computeKey(key);
byte[] bs = shardedJedis.get(computeKey);
Object value = valueSerializer.deserialize(bs);
return (bs == null ? null : new SimpleValueWrapper(value));
}

@Override
public void put(Object key, Object value) {
byte[] k = computeKey(key);
byte[] v = valueSerializer.serialize(value);
shardedJedis.set(k, v);
shardedJedis.zadd(setName, 0, k);
if (expiration > 0) {
shardedJedis.expire(k, (int)expiration);
shardedJedis.expire(k, (int)expiration);
}
}
}
}

配置cache.xml,如果需要使用RedisTemplate,则保留相关配置即可(有些命令仅单机模式才支持)。
<bean id="springCacheManager" class="com.itecheast.ite.domain.util.MyShardedRedisCacheManager">
<property name="hostsAndPorts" value="127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381" />
<property name="defaultExpiration" value="604800" />
<property name="expires">
<map>
<entry key="passwordRetryCache" value="60"/>
<entry key="authorizationCache" value="3600"/>
<entry key="authenticationCache" value="3600"/>
<entry key="shiro-activeSessionCache" value="3600"/>
</map>
</property>
</bean>

测试示例
@Test public void sharded() {
CacheManager cacheManager = SpringUtil.getBean(CacheManager.class);
Cache cache = cacheManager.getCache("test");
for(int i=0;i<10;i++) {
cache.put("test-"+i, "value-"+i);
System.out.println(cache.get("test-"+i, String.class));
}
}

运行多个redis示例:修改端口号即可


效果示例:


评论列表