`
fjg0427
  • 浏览: 42411 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

jedis

 
阅读更多
前段时间细节的了解了Jedis的使用,Jedis是redis的java版本的客户端实现。
本文做个总结,主要分享如下内容:

【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】
好了,一个一个来。
一、 Pipeline
官方的说明是:starts a pipeline,which is a very efficient way to send lots of command and read all the responses when you finish sending them。简单点说pipeline适用于批处理。当有大量的操作需要一次性执行的时候,可以用管道。
示例:
Jedis jedis = new Jedis(String, int);
Pipeline p = jedis.pipelined();
p.set(key,value);//每个操作都发送请求给redis-server
p.get(key,value);

p.sync();//这段代码获取所有的response
这里我进行了20w次连续操作(10w读,10w写),不用pipeline耗时:187242ms,用pipeline耗时:1188ms,可见使用管道后的性能上了一个台阶。看了代码了解到,管道通过一次性写入请求,然后一次性读取响应。也就是说jedis是:request response,request response,...;pipeline则是:request request... response response的方式。这样无需每次请求都等待server端的响应。

二、 跨jvm的id生成器
谈到这个话题,首先要知道redis-server端是单线程来处理client端的请求的。
这样来实现一个id生成器就非常简单了,只要简单的调用jdeis.incr(key);就搞定了。
你或许会问,incr是原子操作吗,能保证不会出现并发问题吗,不是说了吗,server端是单线程处理请求的。

三、 【跨jvm的锁实现【watch】【multi】】
首先说下这个问题的使用场景,有些时候我们业务逻辑是在不同的jvm进程甚至是不同的物理机上的jvm处理的。这样如何来实现不同jvm上的同步问题呢,其实我们可以基于redis来实现一个锁。
具体事务和监听请参考文章:redis学习笔记之事务
暂时找到三种实现方式:
1. 通过jedis.setnx(key,value)实现
     import java.util.Random;
import org.apache.commons.pool.impl.GenericObjectPool.Config;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;

/**
* @author Teaey
*/
public class RedisLock {
    //加锁标志
    public static final String LOCKED = "TRUE";
    public static final long ONE_MILLI_NANOS = 1000000L;
    //默认超时时间(毫秒)
    public static final long DEFAULT_TIME_OUT = 3000;
    public static JedisPool pool;
    public static final Random r = new Random();
    //锁的超时时间(秒),过期删除
    public static final int EXPIRE = 5 * 60;
    static {
        pool = new JedisPool(new Config(), "host", 6379);
    }
    private Jedis jedis;
    private String key;
    //锁状态标志
    private boolean locked = false;

    public RedisLock(String key) {
        this.key = key;
        this.jedis = pool.getResource();
    }

    public boolean lock(long timeout) {
        long nano = System.nanoTime();
        timeout *= ONE_MILLI_NANOS;
        try {
            while ((System.nanoTime() - nano) < timeout) {
                if (jedis.setnx(key, LOCKED) == 1) {
                    jedis.expire(key, EXPIRE);
                    locked = true;
                    return locked;
                }
                // 短暂休眠,nano避免出现活锁
                Thread.sleep(3, r.nextInt(500));
            }
        } catch (Exception e) {
        }
        return false;
    }
    public boolean lock() {
        return lock(DEFAULT_TIME_OUT);
    }

    // 无论是否加锁成功,必须调用
    public void unlock() {
        try {
            if (locked)
                jedis.del(key);
        } finally {
            pool.returnResource(jedis);
        }
    }
}2. 通过事务(multi)实现
由于采纳第一张方法,第二种跟第三种实现只贴了关键代码,望谅解。^_^
     public boolean lock_2(long timeout) {        long nano = System.nanoTime();
        timeout *= ONE_MILLI_NANOS;
        try {
            while ((System.nanoTime() - nano) < timeout) {
                Transaction t = jedis.multi();
                // 开启事务,当server端收到multi指令
                // 会将该client的命令放入一个队列,然后依次执行,知道收到exec指令
                t.getSet(key, LOCKED);
                t.expire(key, EXPIRE);
                String ret = (String) t.exec().get(0);
                if (ret == null || ret.equals("UNLOCK")) {
                    return true;
                }
                // 短暂休眠,nano避免出现活锁
                Thread.sleep(3, r.nextInt(500));
            }
        } catch (Exception e) {
        }
        return false;
    }3. 通过事务+监听实现
    public boolean lock_3(long timeout) {        long nano = System.nanoTime();
        timeout *= ONE_MILLI_NANOS;
        try {
            while ((System.nanoTime() - nano) < timeout) {
                jedis.watch(key);
                // 开启watch之后,如果key的值被修改,则事务失败,exec方法返回null
                String value = jedis.get(key);
                if (value == null || value.equals("UNLOCK")) {
                    Transaction t = jedis.multi();
                    t.setex(key, EXPIRE, LOCKED);
                    if (t.exec() != null) {
                        return true;
                    }
                }
                jedis.unwatch();
                // 短暂休眠,nano避免出现活锁
                Thread.sleep(3, r.nextInt(500));
            }
        } catch (Exception e) {
        }
        return false;
    }最终采用第一种实现,因为加锁只需发送一个请求,效率最高。
四、 【redis分布式】
    最后一个话题,jedis的分布式。在jedis的源码里发现了两种hash算法(MD5,MURMUR Hash(默认)),也可以自己实现redis.clients.util.Hashing接口扩展。
    List<JedisShardInfo> hosts = new ArrayList<JedisShardInfo>();        //server1
        JedisShardInfo host1 = new JedisShardInfo("", 6380, 2000);
        //server2
        JedisShardInfo host2 = new JedisShardInfo("", 6381, 2000);
        hosts.add(host1);
        hosts.add(host2);
        ShardedJedis jedis = new ShardedJedis(hosts);
        jedis.set("key", "");

另外写博客真费力。。。尤其是外网机没有demo的情况下。
分享到:
评论

相关推荐

    使用redisson替代jedis

    ### 使用Redisson替代Jedis 在分布式系统中,Redis作为一种高性能的键值存储数据库,被广泛应用于缓存、消息队列、数据同步等场景。在Java开发领域,开发者可以选择多种客户端来与Redis进行交互,其中最常用的是...

    jedis-3.6.0-API文档-中文版.zip

    赠送jar包:jedis-3.6.0.jar; 赠送原API文档:jedis-3.6.0-javadoc.jar; 赠送源代码:jedis-3.6.0-sources.jar; 赠送Maven依赖信息文件:jedis-3.6.0.pom; 包含翻译后的API文档:jedis-3.6.0-javadoc-API文档-...

    jedis相关jar包

    标题中的“jedis相关jar包”指的是用于操作Redis数据库的Java客户端库Jedis的相关依赖文件。Jedis是一个高效、轻量级的Java客户端,它使得Java开发者能够方便地与Redis进行交互,执行各种数据操作。 描述中提到了两...

    jedis-2.9.0.jar

    jedis-2.9.0.jar jedis-2.9.0 jar 包,不包含源码,源码下载地址: http://download.csdn.net/download/tan3739/9993938 测试代码: 导入依赖包: commons-lang-2.5.jar commons-pool2-2.4.2.jar jedis-2.9.0 jar ...

    jedis-2.9.0.jar和commons-pool2-2.6.0.jar下载(jedis连接redis数据库)

    标题"jedis-2.9.0.jar和commons-pool2-2.6.0.jar下载(jedis连接redis数据库)"指的是两个Java库的下载信息,用于连接Redis数据库。其中,`jedis-2.9.0.jar`是Jedis的特定版本,它是Java开发人员用来操作Redis的...

    jedis-2.9.0-API文档-中文版.zip

    赠送jar包:jedis-2.9.0.jar; 赠送原API文档:jedis-2.9.0-javadoc.jar; 赠送源代码:jedis-2.9.0-sources.jar; 包含翻译后的API文档:jedis-2.9.0-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId...

    jedis依赖jar包

    **Jedis:Redis的Java客户端** Jedis是Java开发者用于操作Redis数据库的首选客户端库。Redis是一个开源的、高性能的键值对存储系统,常被用作数据缓存、消息中间件以及数据库。Jedis提供了丰富的API,允许开发人员...

    Jedis API中文使用文档.-比较详细

    Jedis API中文使用文档详解 Jedis 是 Redis 官方首选的 Java 客户端开发包,用于操作 Redis 数据库。下面是 Jedis API 的详细使用文档,适合新手和老程序员进行复习。 Jedis 的基本使用 Jedis 提供了多种方式来...

    jedis jedis.jar

    Jedis是Java开发的一款高效、轻量级的Redis客户端,专为处理Redis数据库服务而设计。Redis是一款开源的、高性能的键值存储系统,常用于数据缓存、消息队列、分布式锁等场景。Jedis提供了丰富的API,使得开发者能够...

    Jedis所需jar包

    在Java环境中与Redis进行交互,我们通常会使用Jedis这个客户端库。Jedis提供了丰富的API,能够帮助开发者轻松完成各种Redis操作,如设置和获取键值、执行事务、订阅/发布消息等。 Jedis的主要功能包括: 1. 基本...

    jedis-3.3.0.jar文件

    **Redis与Jedis** Redis,全称Remote Dictionary Server,是一款高性能的键值对存储系统,常用于数据库缓存和消息中间件。它支持丰富的数据结构,如字符串、哈希、列表、集合、有序集合等,这使得Redis在各种场景下...

    jedis调用redis源码Demo

    jedis调用redis源码Demo,直接导入工程就可以运行。 redis目录下有redis安装文件和入门电子书 redis64-2.8.9.zip redisbin_x32.zip Redis入门指南(JB51.NET).pdf Redis设计与实现.pdf src: FirestJedisTest.java ...

    jedis-2.9.0.jar及连接池分享

    Jedis是Java开发的一款高效的Redis客户端库,广泛应用于与Redis服务器进行交互的Java项目中。在本资源包中,我们提供了jedis-2.9.0.jar,这是Jedis的一个稳定版本,支持多种Redis操作,如键值操作、事务处理、发布...

    jedis-2.9.0.jar+commons-pool2-2.4.2.jar

    Jedis是一个Java客户端,用于高效地与Redis服务器通信。在这个主题中,我们将深入探讨`jedis-2.9.0.jar`和`commons-pool2-2.4.2.jar`这两个jar包在Redis连接池中的作用。 `jedis-2.9.0.jar`是Jedis的特定版本,它是...

    jedis源码 (学习jedis)

    Jedis是Java开发的一款高效的Redis客户端库,广泛用于与Redis服务器进行交互,提供丰富的API来操作Redis中的数据结构。在学习Jedis的过程中,了解其源码对于深入理解Redis操作的底层实现以及提升Java编程能力非常有...

    jedis-2.9.0 最新版Redis客户端CSDN下载

    1. 创建Jedis实例:`Jedis jedis = new Jedis("localhost", 6379);` 2. 配置连接池:使用`JedisPoolConfig`和`JedisPool`,以更好地管理和复用连接。 3. 执行命令:如`jedis.set("key", "value")`来设置键值对,`...

    jedis-2.9.0+commons-pool2-2.4.2redis依赖包

    标题中的"jedis-2.9.0+commons-pool2-2.4.2redis依赖包"指的是一款基于Java实现的Redis客户端库Jedis的2.9.0版本,与Apache Commons Pool 2.4.2版本相结合的依赖包。这个组合主要用于优化Redis连接池管理,提高应用...

    jedis-3.2.0.jar + commons-pool2-2.6.2.jar

    标题中的"jedis-3.2.0.jar + commons-pool2-2.6.2.jar"提到了两个关键的Java库:Jedis和Apache Commons Pool2。Jedis是Java编程语言中广泛使用的Redis客户端,而Apache Commons Pool2则是一个对象池实现,用于有效地...

    jedis单机版,集群版工具类

    **Jedis:Redis操作的Java库** `Jedis` 是一个高效的、开源的 Java 客户端,专门用于连接和操作 Redis 数据库。它提供了全面的 Redis 命令支持,使得在 Java 应用中集成 Redis 变得简单易行。在本文中,我们将深入...

Global site tag (gtag.js) - Google Analytics