Redis实现分布式存储
来源:互联网 发布:《java并发编程实战》 编辑:程序博客网 时间:2024/04/28 18:45
Memcache是在服务端实现分片的分布式的缓存系统,而Redis是基于Master-Slave(主从),如果想把Reids做成分布式缓存,就要多做几套Master-Slave,每套Master-Slave完成各自的容灾处理,另外,Redis只能在客户端完成分片。
Redis有中语言的客户端,其中基于Java语言的客户端叫做Jedis,Jedis客户端已经为Redis实现了分布式存储。下面分别介绍了Jedis分布式存储的简单使用以及Spring与Jedis的整合使用。
一、Jedis分布式存储举例
package com.ghs.test;import java.util.ArrayList;import java.util.List;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.junit.Before;import org.junit.Test;import redis.clients.jedis.JedisShardInfo;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPool;public class TestShardJedis { ShardedJedisPool pool = null; ShardedJedis jedis = null; @Before public void setup(){ JedisShardInfo shardInfo1 = new JedisShardInfo("192.168.1.108"); JedisShardInfo shardInfo2 = new JedisShardInfo("..."); List<JedisShardInfo> shardInfos = new ArrayList<JedisShardInfo>(); shardInfos.add(shardInfo1); shardInfos.add(shardInfo2); pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shardInfos); } @Test public void testShard(){ jedis = pool.getResource(); //CRUD jedis.set("name", "zhangsan"); System.out.println(jedis.get("name")); jedis.del("name"); //释放对象 pool.returnResource(jedis); }}
二、Spring+Jedis实现分布式存储
spring中的配置:
这里只是把示例一中JedisShardInfo和ShardJedisPool的示例交给Sping容器管理。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <context:property-placeholder location="classpath:redis.properties" /> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxActive" value="${redis.pool.maxActive}" /> <property name="maxIdle" value="${redis.pool.maxIdle}" /> <property name="maxWait" value="${redis.pool.maxWait}" /> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /> </bean> <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"> <constructor-arg index="0" ref="jedisPoolConfig" /> <constructor-arg index="1"> <list> <bean class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis1.ip}" /> <constructor-arg index="1" value="${redis.port}" type="int" /> </bean> <bean class="redis.clients.jedis.JedisShardInfo"> <constructor-arg index="0" value="${redis2.ip}" /> <constructor-arg index="1" value="${redis.port}" type="int" /> </bean> </list> </constructor-arg> </bean></beans>
对访问操作进行封装:
package com.ghs.test;import java.util.List;import javax.annotation.Resource;import redis.clients.jedis.ShardedJedis;import redis.clients.jedis.ShardedJedisPool;public class SpringRedisClient implements IRedisClient{ @Resource(name="shardedJedisPool") private ShardedJedisPool shardedJedisPool; private ShardedJedis getResource(){ return shardedJedisPool.getResource(); } @Override public String set(String key,String value){ return getResource().set(key,value); } @Override public String get(String key){ return getResource().get(key); } @Override public Long del(String key) { return getResource().del(key); } @Override public Long lpush(String key, String... strings) { return getResource().lpush(key, strings); } @Override public Long rpush(String key, String... strings) { return getResource().rpush(key, strings); } @Override public List<String> lrange(String key, int start, int end){ return getResource().lrange(key, start,end); } //…………………………}
三、Jedis分布式存储实现原理
1、JedisShardInfo类
这个类封装了Redis主机的一些基本信息:
private int timeout; private String host; private int port; private String password = null; private String name = null;
最重要的是它的父类中有一个weight字段,作为本Redis服务器的权值。
这个类还有一个继承自父类的方法createResource(),用来生成这个Redis服务器对应的Jedis对象,即往Redis服务器存取数据的对象。
2、Sharded类
我们先来熟悉一下一致性哈希算法:
http://blog.csdn.net/u011983531/article/details/49507729
对一致性哈希算法熟悉以后,对Sharded类的理解就不难了,通过这个类来为每个分片创建虚拟节点,为每次操作获取分片。
Sharded中的三个字段,nodes是用来模拟一致性哈希算法用的;algo是用来对字符串产生哈希值的hash函数,这里默认的是murmurhash,这个算法的随机分布特征表现比较好;resources这个map是用来存储JedisShardInfo与其对应的Jedis类之间的映射关系。
public static final int DEFAULT_WEIGHT = 1; private TreeMap<Long, S> nodes;//机器节点 private final Hashing algo; private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();//每个机器节点关联的虚拟节点
下面我们来看看初始化操作和获取分片的操作:
//初始化操作,为每个主机管理虚拟节点 private void initialize(List<S> shards) { nodes = new TreeMap<Long, S>(); for (int i = 0; i != shards.size(); ++i) { final S shardInfo = shards.get(i); if (shardInfo.getName() == null) for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo); } else for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo); } resources.put(shardInfo, shardInfo.createResource()); } }
在for循环中,遍历主机列表(shards.get(i)),之后对每个主机按照单权重160的比例计算shard值,将shard值和主机信息(shardInfo)放到nodes中,将主机信息(shardInfo)和其对应的链接资源(Jedis)映射放入到resources中。
Weight是权重,用于调节单个主机被映射值个数,如果weight为1,那么当前主机将被映射为160个值,weight为2,当前主机将被映射为320个值,因此weight为2的节点被访问到的概率就会高一些。
遍历list中的每一个shardInfo,将其权重weight*160生成n,然后用名字或者编号来生成n个哈希值(这个是为了保证哈希算法的平衡性而生成的虚拟节点),然后将其和本shardInfo的对应关系存储到treemap里面(这是在模拟一致性哈希算法中将虚拟节点映射到环上的操作),最后将shardInfo与对应的Jedis类的映射关系存储到resources里面。
//获取分片 public S getShardInfo(byte[] key) { SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key)); if (tail.isEmpty()) { return nodes.get(nodes.firstKey()); } return tail.get(tail.firstKey()); } public S getShardInfo(String key) { return getShardInfo(SafeEncoder.encode(getKeyTag(key))); }
首先根据传入的key按照hash算法(默认为murmurhash)取得其value,然后用这个value到treemap中找key大于前面生成的value值的第一个键值对,这个键值对的value既是对应的shardedInfo。
- Redis实现分布式存储
- Redis SpringSession+Redis实现分布式Session存储
- 通过redis实现分布式存储fastdfs的文件名对应记录
- Spring Session + Redis 实现Session的分布式存储
- redis 一致性hash ,分布式存储
- Redis实现分布式锁
- Redis 分布式锁实现
- Redis 分布式锁实现
- Redis实现分布式锁
- redis实现分布式锁
- Redis实现分布式锁
- 分布式锁redis实现
- Redis 分布式锁实现
- redis分布式锁实现
- redis实现分布式锁
- Redis分布式锁实现
- redis分布式锁实现
- redis实现分布式锁
- HDU 46093-idiots
- Java对象序列化工具类
- 阿里“三活”数据中心实践经验:没人能做,我们就自己做
- TCP三次握手和四次挥手协议
- 同时输出数据到标准输出和文件
- Redis实现分布式存储
- 关于测试方面一些版本控制及管理工具的安装及使用
- Linux rpm 命令参数使用详解[介绍和应用]
- Tomcat shutdown无法结束进程的问题
- Android编译中m、mm、mmm的区别
- 子线程与主线程通信的其他方法概述
- 一道面试题:用shell写一个从1加到100的程序
- PAT 1017. Queueing at Bank (25)
- JAVA反射机制作用是什么