redis下的shareJedis使用
redis分区:
分区就是将数据分散到多个redis实例中,每个redis实例只保存一部分数据
分区/分片的意义:
单机的机器存储容量会限制redis的服务能力,为了存储的横向扩展,可以将数据分散到多台机器上
[code]ShardedJedis是通过一致性哈希来实现将不同的key分散到不同的redis server中
shareJedis使用:
[code]@Test public void test3() { //设置连接池的相关配置 JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(2); poolConfig.setMaxIdle(1); poolConfig.setMaxWaitMillis(2000); poolConfig.setTestOnBorrow(false); poolConfig.setTestOnReturn(false); //定义redis的多个节点机器 List<JedisShardInfo> list = new ArrayList<JedisShardInfo>() {{ add(new JedisShardInfo("127.0.0.1", 6379)); add(new JedisShardInfo("127.0.0.1", 6380)); add(new JedisShardInfo("127.0.0.1", 6381)); }}; //定义redis分片连接池 ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, list); //获取连接操作redis 进行查询等其他操作 //使用后一定关闭,还给连接池 try (ShardedJedis jedis = jedisPool.getResource()) { //向redis中添加20个记录查看分片结果 for (int i = 0; i < 10; i++) { //增加的记录格式为 key=NUM_i value=i jedis.set("NUM_" + i, "" + i); jedis.get("NUM_" + i); } } }
测试数据分布情况
分布情况是根据shareJedis中对key进行一致性哈希来确定记录的存放区域
shareJedis讲解
1.继承体系
shareJedis存储数的核心代码:
[code] private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>(); public String set(final String key, final String value) { Jedis j = getShard(key); return j.set(key, value); } public R getShard(String key) { return resources.get(getShardInfo(key)); } public S getShardInfo(String key) { return getShardInfo(SafeEncoder.encode(getKeyTag(key))); } 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()); }
主要的操作是:Jedis j = getShard(key);获取对应的jedis实例,方法(getShardInfo(byte[] key))nodes是个treeMap,algo是Hashing类型,key分片所使用的hash算法,主要步骤:
1.从treeMap中取出大于等于key之后的部分视图SortMap
2.从sortMap取出第一个键值对的值,对象S
3.从resource中取出R(Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();)
根据下面的代码发现 S是JesdisShareInfo,R就是redis实例
[code]public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo> implements BinaryJedisCommands {} public class Sharded<R, S extends ShardInfo<R>>{}
JedisShardInfo具体信息如下:里面包含了jedis服务器的一些信息,最重要的是它的父类中有一个weight字段,作为本jedis服务器的权值,实际是根据存储的jedis信息去获取jedis的实例
整体的存储流程:
1.将key值进行hash算法,然后根据这个hash出来的key从treeMap中获取jedisShareInfo
2.根据jedisShareInfo中的信息获取jedis实例,最终返回,执行操作
[code] 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() + "*" + n), shardInfo); } resources.put(shardInfo, shardInfo.createResource()); } }
Shared中的初始化方法, 将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重),保存在TreeMap中,
然后把每台服务器节点的信息和物理连接以键值对保存LinkedHashMap中。
[code]shardInfo.createResource()根据shareInfo中存储的redis创建redis实例信息
其中初始化方法调用实在 ShardedJedis jedis = jedisPool.getResource() 这里进行初始化的,实际是通过连接池来实现的,具体感兴趣的可以自己调试一下
ShardedJedis分布式具体的的实现思路:
redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)
将划分虚拟节点采用TreeMap存储
对每个redis服务器的物理连接采用LinkedHashMap存储
对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点
sharded采用的hash算法:MD5 和 MurmurHash两种;默认采用64位的MurmurHash算法;
分区的不足:
- 分区是多台redis共同作用的,如果其中一台出现了宕机现象,则整个分片都将不能使用,虽然是在一定程度上缓减了内存的压力,但是没有实现高可用。
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
高可用的解决方案:可以采用哨兵机制实现主从复制从而实现高可用。
博主初次涉猎,如果有什么问题以及说的不明白的,请留言告知 一起交流提升
欢迎关注作者公众号交流以及投稿
守望希望 原创文章 10获赞 0访问量 841 关注 私信
- Windows10下Redis安装配置使用
- Pycharm中使用django-redis 的问题
- 使用spring-data-redis对redis集群进行KEY模糊删除的几种方式
- windows下使用redis,Redis入门使用,Redis基础命令
- Java中使用Jedis操作Redis
- Redis for Windows(C#缓存)安装和使用
- .NET中使用Redis
- Redis使用中的一些问题
- python中redis的使用
- 在windows上部署使用Redis(摘录)
- redis——学习之路五(简单的C#使用redis)
- win7 64位安装redis 及Redis Desktop Manager使用
- 【redis】3.Spring 集成注解 redis 项目配置使用
- phpredis安装使用(1)
- 转 redis使用场景 简介
- 使用redis的比较完美的加锁解锁
- 使用redis的setbit和bitcount来进行区间统计的坑
- 在 Ubuntu 下安装 Redis 并使用 init 脚本启动
- 【Linux】在centos中使用命令安装redis
- Springboot使用redis进行api防刷限流过程详解