<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-4  評(píng)論-10  文章-0  trackbacks-0
    創(chuàng)建日期:2012年7月3日
    修改日期:2012年7月19日
    前段時(shí)間細(xì)節(jié)的了解了Jedis的使用,Jedis是redis的java版本的客戶端實(shí)現(xiàn)。
    本文做個(gè)總結(jié),主要分享如下內(nèi)容:

    【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】
    好了,一個(gè)一個(gè)來(lái)。
    一、 Pipeline
    官方的說(shuō)明是:starts a pipeline,which is a very efficient way to send lots of command and read all the responses when you finish sending them。簡(jiǎn)單點(diǎn)說(shuō)pipeline適用于批處理。當(dāng)有大量的操作需要一次性執(zhí)行的時(shí)候,可以用管道。
    示例:
    Jedis jedis = new Jedis(String, int);
    Pipeline p = jedis.pipelined();
    p.set(key,value);//每個(gè)操作都發(fā)送請(qǐng)求給redis-server
    p.get(key,value);

    p.sync();//這段代碼獲取所有的response
    這里我進(jìn)行了20w次連續(xù)操作(10w讀,10w寫),不用pipeline耗時(shí):187242ms,用pipeline耗時(shí):1188ms,可見(jiàn)使用管道后的性能上了一個(gè)臺(tái)階。看了代碼了解到,管道通過(guò)一次性寫入請(qǐng)求,然后一次性讀取響應(yīng)。也就是說(shuō)jedis是:request response,request response,...;pipeline則是:request request... response response的方式。這樣無(wú)需每次請(qǐng)求都等待server端的響應(yīng)。

    二、 跨jvm的id生成器 
    談到這個(gè)話題,首先要知道redis-server端是單線程來(lái)處理client端的請(qǐng)求的。
    這樣來(lái)實(shí)現(xiàn)一個(gè)id生成器就非常簡(jiǎn)單了,只要簡(jiǎn)單的調(diào)用jdeis.incr(key);就搞定了。
    你或許會(huì)問(wèn),incr是原子操作嗎,能保證不會(huì)出現(xiàn)并發(fā)問(wèn)題嗎,前面說(shuō)過(guò),server端是單線程處理請(qǐng)求的。

    三、 【跨jvm的鎖實(shí)現(xiàn)【watch】【multi】】
    首先說(shuō)下這個(gè)問(wèn)題的使用場(chǎng)景,有些時(shí)候我們業(yè)務(wù)邏輯是在不同的jvm進(jìn)程甚至是不同的物理機(jī)上的jvm處理的。這樣如何來(lái)實(shí)現(xiàn)不同jvm上的同步問(wèn)題呢,其實(shí)我們可以基于redis來(lái)實(shí)現(xiàn)一個(gè)鎖。
    具體事務(wù)和監(jiān)聽請(qǐng)參考文章:redis學(xué)習(xí)筆記之事務(wù)
     暫時(shí)找到三種實(shí)現(xiàn)方式:
    1. 通過(guò)jedis.setnx(key,value)實(shí)現(xiàn)
         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 {
        //加鎖標(biāo)志
        public static final String LOCKED = "TRUE";
        public static final long ONE_MILLI_NANOS = 1000000L;
        //默認(rèn)超時(shí)時(shí)間(毫秒)
        public static final long DEFAULT_TIME_OUT = 3000;
        public static JedisPool pool;
        public static final Random r = new Random();
        //鎖的超時(shí)時(shí)間(秒),過(guò)期刪除
        public static final int EXPIRE = 5 * 60;
        static {
            pool = new JedisPool(new Config(), "host", 6379);
        }
        private Jedis jedis;
        private String key;
        //鎖狀態(tài)標(biāo)志
        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避免出現(xiàn)活鎖
                    Thread.sleep(3, r.nextInt(500));
                }
            } catch (Exception e) {
            }
            return false;
        }
        public boolean lock() {
            return lock(DEFAULT_TIME_OUT);
        }

        // 無(wú)論是否加鎖成功,必須調(diào)用
        public void unlock() {
            try {
                if (locked)
                    jedis.del(key);
            } finally {
                pool.returnResource(jedis);
            }
        }
    }
    2. 通過(guò)事務(wù)(multi)實(shí)現(xiàn)
    由于采納第一張方法,第二種跟第三種實(shí)現(xiàn)只貼了關(guān)鍵代碼,望諒解。^_^
         public boolean lock_2(long timeout) {
            long nano = System.nanoTime();
            timeout *= ONE_MILLI_NANOS;
            try {
                while ((System.nanoTime() - nano) < timeout) {
                    Transaction t = jedis.multi();
                    // 開啟事務(wù),當(dāng)server端收到multi指令
                    
    // 會(huì)將該client的命令放入一個(gè)隊(duì)列,然后依次執(zhí)行,知道收到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避免出現(xiàn)活鎖
                    Thread.sleep(3, r.nextInt(500));
                }
            } catch (Exception e) {
            }
            return false;
        }
    3. 通過(guò)事務(wù)+監(jiān)聽實(shí)現(xiàn)
        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的值被修改,則事務(wù)失敗,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避免出現(xiàn)活鎖
                    Thread.sleep(3, r.nextInt(500));
                }
            } catch (Exception e) {
            }
            return false;
        }
    最終采用第一種實(shí)現(xiàn),因?yàn)榧渔i只需發(fā)送一個(gè)請(qǐng)求,效率最高。
    四、 【redis分布式】
        最后一個(gè)話題,jedis的分布式。在jedis的源碼里發(fā)現(xiàn)了兩種hash算法(MD5,MURMUR Hash(默認(rèn))),也可以自己實(shí)現(xiàn)redis.clients.util.Hashing接口擴(kuò)展。
        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", "");


    另外寫博客真費(fèi)力。。。
    posted on 2012-07-03 13:32 沖杯茶喝 閱讀(24080) 評(píng)論(6)  編輯  收藏

    評(píng)論:
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】 2013-01-25 10:08 | finallygo
    2.6之后,支持了script,又有新的辦法了  回復(fù)  更多評(píng)論
      
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】 2013-05-03 09:54 | 沖杯茶喝
    沒(méi)時(shí)間研究了,如果有新的,可以完善本文@finallygo
      回復(fù)  更多評(píng)論
      
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】 2013-05-23 00:53 | leealways887
    請(qǐng)問(wèn)博主,為什么我用了pipeline之后,設(shè)置10萬(wàn)條數(shù)據(jù),程序反應(yīng)不過(guò)來(lái),倒是不用pipeline,程序還能正常運(yùn)行呢?  回復(fù)  更多評(píng)論
      
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】[未登錄](méi) 2014-02-11 15:44 | young
    @leealways887
    數(shù)據(jù)量太大了吧 內(nèi)存用完了  回復(fù)  更多評(píng)論
      
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】 2014-11-03 17:36 | louzhu
    什么叫反應(yīng)不過(guò)來(lái)!據(jù)我說(shuō)之,redis服務(wù)器應(yīng)該不會(huì)反應(yīng)不過(guò)來(lái)。

    @leealways887
      回復(fù)  更多評(píng)論
      
    # re: Jedis使用總結(jié)【pipeline】【分布式的id生成器】【分布式鎖【watch】【multi】】【redis分布式】 2016-05-20 10:13 | fruwei
    第二種的t.expire(key, EXPIRE);有問(wèn)題吧 ,如果一直有鎖請(qǐng)求,豈不是每次都把這個(gè)過(guò)期時(shí)間重新設(shè)置了?應(yīng)該先判斷下有沒(méi)有超時(shí),沒(méi)有就設(shè)置,有的話就不設(shè)置。  回復(fù)  更多評(píng)論
      

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 久久国产精品免费一区二区三区| 亚洲一级毛片免费在线观看| 亚洲高清在线播放| 四虎永久在线精品免费观看视频| 亚洲av无码日韩av无码网站冲| 久久精品国产亚洲7777| 久久午夜夜伦鲁鲁片免费无码影视| 亚洲精品无码专区| 亚洲AV第一页国产精品| 国产美女精品久久久久久久免费| 99久久国产精品免费一区二区| 亚洲丁香婷婷综合久久| 亚洲天堂久久精品| 免费jjzz在在线播放国产| 日本免费一区二区在线观看| 乱淫片免费影院观看| 久久久久精品国产亚洲AV无码| 国产成人综合亚洲AV第一页| 国产精品成人免费一区二区| 国产无遮挡裸体免费视频在线观看| 亚洲乱妇熟女爽到高潮的片| 亚洲国产成人久久综合一 | 久久亚洲欧洲国产综合| 国产va精品免费观看| 免费无码又爽又刺激高潮软件| 久久亚洲色WWW成人欧美| 亚洲自偷自拍另类图片二区| 久久精品亚洲福利| 美女被免费视频网站a国产| 狼群影院在线观看免费观看直播| 国产激情久久久久影院老熟女免费 | 国产AV无码专区亚洲AV漫画| 免费黄色app网站| 免费阿v网站在线观看g| 国产精品免费AV片在线观看| 性生大片视频免费观看一级| 亚洲AV无码资源在线观看| 亚洲免费视频播放| 亚洲精品国产啊女成拍色拍| 亚洲高清专区日韩精品| 在线亚洲精品福利网址导航|