Jedis下的ShardedJedis(分布式)使用方法(一)

标签: jedis shardedjedis 分布 | 发表时间:2017-07-22 12:33 | 作者:lixuguang
出处:http://www.iteye.com

原来项目中有用到Redis用作缓存服务,刚开始时只用一台Redis就能够满足服务,随着项目的慢慢进行,发现一台满足不了现有的项目需求,因为Redis操作都是原子性这样的特性,造成有时同时读写缓存造成查询效率的下降。但是由于我们现在用的还是2.X版本,还是没有集群功能的(Redis作者在3.0版本中已经加入了集群功能), 因此只能使用2.x版本中自带的一个叫做ShardedJedis的来实现分布式缓存。

ShardedJedis是通过 一致性哈希来实现分布式缓存的,通过一定的策略把不同的key分配到不同的redis server上,达到横向扩展的目的。那么ShardedJedis内部是怎么实现的呢,文章会慢慢讲解。

 

 1.ShardedJedis使用方法

ShardedJedis的使用方法除了配置时有点区别,其他和Jedis基本类似,有一点要注意的是 ShardedJedis 不支持多命令操作,像mget、mset、brpop等可以在redis命令后一次性操作多个key的命令,具体包括哪些,大家可以看Jedis下的  MultiKeyCommands 这个类,这里面就包含了所有的多命令操作。很贴心的是,Redis作者已经把这些命令从ShardedJedis过滤掉了,使用时也调用不了这些方法,大家知道下就行了。

好了,现在来看基本的使用

 

  //设置连接池的相关配置
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(2);
        poolConfig.setMaxIdle(1);
        poolConfig.setMaxWaitMillis(2000);
        poolConfig.setTestOnBorrow(false);
        poolConfig.setTestOnReturn(false);

        //设置Redis信息
        String host = "127.0.0.1";
        JedisShardInfo shardInfo1 = new JedisShardInfo(host, 6379, 500);
        shardInfo1.setPassword("test123");
        JedisShardInfo shardInfo2 = new JedisShardInfo(host, 6380, 500);
        shardInfo2.setPassword("test123");
        JedisShardInfo shardInfo3 = new JedisShardInfo(host, 6381, 500);
        shardInfo3.setPassword("test123");

        //初始化ShardedJedisPool
        List<JedisShardInfo> infoList = Arrays.asList(shardInfo1, shardInfo2, shardInfo3);
        ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, infoList);

        //进行查询等其他操作
       ShardedJedis jedis = null;
        try {
            jedis = jedisPool.getResource();
              jedis.set("test", "test");
              jedis.set("test1", "test1");
            String test = jedis.get("test");
            System.out.println(test);
            ......
        } finally {
             //使用后一定关闭,还给连接池    
   if(jedis!=null) {
    jedis.close();    
    } }

 

 

jedis获取后 一定要关闭,这和我们使用数据库连接池是一样的,放在finally块中保证jedis的关闭.

ps:如果大家使用的jdk是1.7版本或者以上的话,可以使用1.7加入的 try-with-resources语句

 

       try(ShardedJedis jedis = jedisPool.getResource()) {
            jedis.set("test", "test");
            jedis.set("test1", "test1");
            String test = jedis.get("test");
            System.out.println(test);
        }

 

try-with-resources的效果和我们上面写法是一样的,只是jedis.close()语法它会帮我们调用,它会默认调用我们在 try-with-resources语句中声明的,实现了 Closeable 接口的对象的close方法(像上面的ShardedJedis),我们经常用到的数据库连接Connection和一些输入输出流都可以使用这种方法。

 

 从代码上看,除了初始化 ShardedJedisPool时需要加入多个Redis服务器信息,其他的和Jedis使用差不多。

在初始化 ShardedJedisPool 时,我们还可以传入 ShardedJedis采用的hash算法,支持 MURMUR_HASH 和 MD5两种算法,默认是使用 MURMUR_HASH(可以查看 redis.clients.util.Hashing 类查看相关的信息)

另外还可以传入 keyTagPattern来指定我们key的分布策略,所有能够匹配 keyTagPattern的key(通过正则匹配)将放在同一个redis里,默认的是直接使用key来进行判定。Redis自带了一个 Sharded. keyTagPattern,如下

 

Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile("\\{(.+?)\\}");

 

我们可以用下面的代码来实际测试下

        ShardedJedis jedis = jedisPool.getResource();    

jedis.set("cnblog", "cnblog"); jedis.set("redis", "redis"); jedis.set("test", "test"); jedis.set("123456", "1234567"); Client client1 = jedis.getShard("cnblog").getClient(); Client client2 = jedis.getShard("redis").getClient(); Client client3 = jedis.getShard("test").getClient(); Client client4 = jedis.getShard("123456").getClient(); ////打印key在哪个server中 System.out.println("cnblog in server:" + client1.getHost() + " and port is:" + client1.getPort()); System.out.println("redis in server:" + client2.getHost() + " and port is:" + client2.getPort()); System.out.println("test in server:" + client3.getHost() + " and port is:" + client3.getPort()); System.out.println("123456 in server:" + client4.getHost() + " and port is:" + client4.getPort());

 

 

看输出内容:

可以看到我们保存的4个key,cnblog和redis在同一个redis server中,另外两个分别在另外的redis server中。

ShardedJedis里面采用了一致性哈希的算法,来决定每个key的保存位置,具体是怎么样计算的,在下一篇中会研究下Jedis的源码来看看。



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [jedis shardedjedis 分布] 推荐:

Jedis下的ShardedJedis(分布式)使用方法(一)

- - 互联网 - ITeye博客
原来项目中有用到Redis用作缓存服务,刚开始时只用一台Redis就能够满足服务,随着项目的慢慢进行,发现一台满足不了现有的项目需求,因为Redis操作都是原子性这样的特性,造成有时同时读写缓存造成查询效率的下降. 但是由于我们现在用的还是2.X版本,还是没有集群功能的(Redis作者在3.0版本中已经加入了集群功能), 因此只能使用2.x版本中自带的一个叫做ShardedJedis的来实现分布式缓存.

使用Jedis的ShardedJedis做Redis集群

- - 丕子
之前一直没仔细看过ShardedJedis的代码,最近遇到了shard后集群扩容后的 数据迁移问题. 今天在看ShardedJedis源码的时候,发现ShardedJedis并没有使用节点的Ip和port做hash,而是用的instance的顺序或者name,太赞了. 一开始你可以设置足够多的instance,数据扩容的时候,只需要将几个instance的数据copy到别的机器上.

Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式等)介绍

- - 数据库 - ITeye博客
        redis是一个著名的key-value存储系统,而作为其官方推荐的java版客户端jedis也非常强大和稳定,支持事务、管道及有jedis自身实现的分布式.         在这里对jedis关于事务、管道和分布式的调用方式做一个简单的介绍和对比:.         最简单和基础的调用方式.

Redis客户端之Spring整合Jedis

- - 开源软件 - ITeye博客
1.下载相关jar包,并引入工程:. 2.将以下XML配置引入spring. 3.将shardedJedisPool注入相关的类中即可使用. * 设置一个key的过期时间(单位:秒). * @param key key值. * @param seconds 多少秒后过期. * @return 1:设置了过期时间 0:没有设置过期时间/不能设置过期时间.

Redis客户端Jedis使用示例

- - 移动开发 - ITeye博客
Jedis 是 Redis 官方首选的 Java 客户端开发包. 工作过程总结的一个示例,贴出来,如下:.      * 在不同的线程中使用相同的Jedis实例会发生奇怪的错误. 但是创建太多的实现也不好因为这意味着会建立很多sokcet连接, .      * 也会导致奇怪的错误发生. 单一Jedis实例不是线程安全的.

Jedis的Publish/Subscribe功能的运用

- - 开源软件 - ITeye博客
转自: http://kingxss.iteye.com/blog/1420264. 一、Redis服务器端的安装和客户端Jedis的安装.    下载地址: http://redis.googlecode.com/files/redis-2.4.8.tar.gz. 在linux下运行如下命令进行安装.

[FAQ] Jedis使用过程中踩过的那些坑

- - 互联网 - ITeye博客
1. 一个 大坑:若实例化 JedisShardInfo 时不设置节点名称(name属性),那么当Redis节点列表的顺序发生变化时,会发生“ 键 rehash 现象”. 使用BTrace追踪redis.clients.util.Sharded的实时状态,验证“Jedis分片机制的一致性哈希算法”实现;.

基于jedis、redis-sentinel的redis主从、高可用、sharding架构

- - 开源软件 - ITeye博客
最近项目上需要对Redis(目前redis用的是2.8版本)做高可用、集群等优化,就扩展了jedis客户端(MasterSlaveJedis、MasterSlaveJedisPool、ShardedMasterSlaveJedis、ShardedMasterSlaveJedisPool),以满足以下几个需求:.

JedisPool异常Jedis链接处理 - wc的一些事一些情

- - 博客园_首页
基于JedisPool管理Jedis对象,通过get方法获取值,出现key对应的value值错误,例如:. 通过获取key为a的值,但获取了值b来. 同一套代码的项目,分别部署在两个不同的应用集群,其中一个集群出现这种问题,而另一个集群却没有出现. 通过表象可以看出,应该是链接池的Jedis对象链接出现错乱而导致的.

分布式日志

- - Java - 编程语言 - ITeye博客
最近完成一个简单的日志管理系统,拿出来跟大家分享一下. 3、支持文件输出、habse输出、mongodb输出. 基于以上三点功能,我们下面详细说明. 说道支持这个功能,有个同事认为没有这个必要,他的观点是log4j的配置不需要经常变动,不需要支持这样的功能;本人的观点是“配置可以进行统一管理、而且正式机跟测试机的log4j的配置肯定会有一些差异的”,因此这个功能是必须的.