日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Jedis使用教程完整版

發布時間:2025/7/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Jedis使用教程完整版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

  • 摘要:概述Jedis是Redis官方推薦的Java連接開發工具。要在Java開發中使用好Redis中間件,必須對Jedis熟悉才能寫成漂亮的代碼。這篇文章不描述怎么安裝Redis和Reids的命令,只對Jedis的使用進行對介紹。1.基本使用Jedis的基本使用非常簡單,只需要創建Jedis對象的時候指定host,port,password即可。當然,Jedis對象又很多構造方法,都大同小異,只是對應和Redis連接的socket的參數不一樣而已。Jedisjedis=newJed
  • 概述?

    Jedis是Redis官方推薦的Java連接開發工具。要在Java開發中使用好Redis中間件,必須對Jedis熟悉才能寫成漂亮的代碼。這篇文章不描述怎么安裝Redis和Reids的命令,只對Jedis的使用進行對介紹。

    ?


    1. 基本使用?

    Jedis的基本使用非常簡單,只需要創建Jedis對象的時候指定host,port, password即可。當然,Jedis對象又很多構造方法,都大同小異,只是對應和Redis連接的socket的參數不一樣而已。


    Jedis jedis = new Jedis("localhost", 6379);//指定Redis服務Host和port?
    jedis.auth("xxxx"); //如果Redis服務連接需要密碼,制定密碼?
    String value = jedis.get("key"); //訪問Redis服務?
    jedis.close(); //使用完關閉連接?

    Jedis基本使用十分簡單,在每次使用時,構建Jedis對象即可。在Jedis對象構建好之后,Jedis底層會打開一條Socket通道和Redis服務進行連接。所以在使用完Jedis對象之后,需要調用Jedis.close()方法把連接關閉,不如會占用系統資源。當然,如果應用非常平凡的創建和銷毀Jedis對象,對應用的性能是很大影響的,因為構建Socket的通道是很耗時的(類似數據庫連接)。我們應該使用連接池來減少Socket對象的創建和銷毀過程。


    2. 連接池使用?

    Jedis連接池是基于apache-commons pool2實現的。在構建連接池對象的時候,需要提供池對象的配置對象,及JedisPoolConfig(繼承自GenericObjectPoolConfig)。我們可以通過這個配置對象對連接池進行相關參數的配置(如最大連接數,最大空數等)。


    JedisPoolConfig config = new JedisPoolConfig();?
    config.setMaxIdle(8);?
    config.setMaxTotal(18);?
    JedisPool pool = new JedisPool(config, "127.0.0.1", 6379, 2000, "password");?
    Jedis jedis = pool.getResource();?
    String value = jedis.get("key");?
    ......?
    jedis.close();?
    pool.close();?

    使用Jedis連接池之后,在每次用完連接對象后一定要記得把連接歸還給連接池。Jedis對close方法進行了改造,如果是連接池中的連接對象,調用Close方法將會是把連接對象返回到對象池,若不是則關閉連接。可以查看如下代碼


    @Override?
    public void close() { //Jedis的close方法?
    if (dataSource != null) {?
    if (client.isBroken()) {?
    this.dataSource.returnBrokenResource(this);?
    } else {?
    this.dataSource.returnResource(this);?
    }?
    } else {?
    client.close();?
    }?
    }?
    //另外從對象池中獲取Jedis鏈接時,將會對dataSource進行設置?
    // JedisPool.getResource()方法?
    public Jedis getResource() {?
    Jedis jedis = super.getResource();?
    jedis.setDataSource(this);?
    return jedis;?
    }?
    3. 高可用連接?

    我們知道,連接池可以大大提高應用訪問Reids服務的性能,減去大量的Socket的創建和銷毀過程。但是Redis為了保障高可用,服務一般都是Sentinel部署方式(可以查看我的文章詳細了解)。當Redis服務中的主服務掛掉之后,會仲裁出另外一臺Slaves服務充當Master。這個時候,我們的應用即使使用了Jedis連接池,Master服務掛了,我們的應用獎還是無法連接新的Master服務。為了解決這個問題,Jedis也提供了相應的Sentinel實現,能夠在Redis Sentinel主從切換時候,通知我們的應用,把我們的應用連接到新的 Master服務。先看下怎么使用。

    ?

    注意:Jedis版本必須2.4.2或更新版本


    Set?sentinels = new HashSet<>();?
    sentinels.add("172.18.18.207:26379");?
    sentinels.add("172.18.18.208:26379");?
    JedisPoolConfig config = new JedisPoolConfig();?
    config.setMaxIdle(5);?
    config.setMaxTotal(20);?
    JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, config);?
    Jedis jedis = pool.getResource();?
    jedis.set("jedis", "jedis");?
    ......?
    jedis.close();?
    pool.close();?

    Jedis Sentinel的使用也是十分簡單的,只是在JedisPool中添加了Sentinel和MasterName參數。Jedis Sentinel底層基于Redis訂閱實現Redis主從服務的切換通知。當Reids發生主從切換時,Sentinel會發送通知主動通知Jedis進行連接的切換。JedisSentinelPool在每次從連接池中獲取鏈接對象的時候,都要對連接對象進行檢測,如果此鏈接和Sentinel的Master服務連接參數不一致,則會關閉此連接,重新獲取新的Jedis連接對象。


    public Jedis getResource() {?
    while (true) {?
    Jedis jedis = super.getResource();?
    jedis.setDataSource(this);?
    // get a reference because it can change concurrently?
    final HostAndPort master = currentHostMaster;?
    final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient().getPort());?
    if (master.equals(connection)) {?
    // connected to the correct master?
    return jedis;?
    } else {?
    returnBrokenResource(jedis);?
    }?
    }?
    }?

    當然,JedisSentinelPool對象要時時監控RedisSentinel的主從切換。在其內部通過Reids的訂閱實現。具體的實現看JedisSentinelPool的兩個方法就很清晰


    private HostAndPort initSentinels(Set?sentinels, final String masterName) {?
    HostAndPort master = null;?
    boolean sentinelAvailable = false;?
    log.info("Trying to find master from available Sentinels...");?
    for (String sentinel : sentinels) {?
    final HostAndPort hap = HostAndPort.parseString(sentinel);?
    log.fine("Connecting to Sentinel " + hap);?
    Jedis jedis = null;?
    try {?
    jedis = new Jedis(hap.getHost(), hap.getPort());?
    //從RedisSentinel中獲取Master信息?
    List?masterAddr = jedis.sentinelGetMasterAddrByName(masterName);?
    sentinelAvailable = true; // connected to sentinel...?
    if (masterAddr == null || masterAddr.size() != 2) {?
    log.warning("Can not get master addr, master name: " + masterName + ". Sentinel: " + hap + ".");?
    continue;?
    }?
    master = toHostAndPort(masterAddr);?
    log.fine("Found Redis master at " + master);?
    break;?
    } catch (JedisException e) {?
    // it should handle JedisException there's another chance of raising JedisDataException?
    log.warning("Cannot get master address from sentinel running @ " + hap + ". Reason: " + e + ". Trying next one.");?
    } finally {?
    if (jedis != null) {?
    jedis.close();?
    }?
    }?
    }?
    if (master == null) {?
    if (sentinelAvailable) {?
    // can connect to sentinel, but master name seems to not monitored?
    throw new JedisException("Can connect to sentinel, but " + masterName + " seems to be not monitored...");?
    } else {?
    throw new JedisConnectionException("All sentinels down, cannot determine where is " + masterName + " master is running...");?
    }?
    }?
    log.info("Redis master running at " + master + ", starting Sentinel listeners...");?
    //啟動后臺線程監控RedisSentinal的主從切換通知?
    for (String sentinel : sentinels) {?
    final HostAndPort hap = HostAndPort.parseString(sentinel);?
    MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());?
    // whether MasterListener threads are alive or not, process can be stopped?
    masterListener.setDaemon(true);?
    masterListeners.add(masterListener);?
    masterListener.start();?
    }?
    return master;?
    }private void initPool(HostAndPort master) {?
    if (!master.equals(currentHostMaster)) {?
    currentHostMaster = master;?
    if (factory == null) {?
    factory = new JedisFactory(master.getHost(), master.getPort(), connectionTimeout, soTimeout, password, database, clientName, false, null, null, null);?
    initPool(poolConfig, factory);?
    } else {?
    factory.setHostAndPort(currentHostMaster);?
    // although we clear the pool, we still have to check the returned object?
    // in getResource, this call only clears idle instances, not?
    // borrowed instances?
    internalPool.clear();?
    }?
    log.info("Created JedisPool to master at " + master);?
    }?
    }?

    可以看到,JedisSentinel的監控時使用MasterListener這個對象來實現的。看對應源碼可以發現是基于Redis的訂閱實現的,其訂閱頻道為"+switch-master"。當MasterListener接收到switch-master消息時候,會使用新的Host和port進行initPool。這樣對連接池中的連接對象清除,重新創建新的連接指向新的Master服務。


    4. 客戶端分片?

    對于大應用來說,單臺Redis服務器肯定滿足不了應用的需求。在Redis3.0之前,是不支持集群的。如果要使用多臺Reids服務器,必須采用其他方式。很多公司使用了代理方式來解決Redis集群。對于Jedis,也提供了客戶端分片的模式來連接“Redis集群”。其內部是采用Key的一致性hash算法來區分key存儲在哪個Redis實例上的。


    JedisPoolConfig config = new JedisPoolConfig();?
    config.setMaxTotal(500);?
    config.setTestOnBorrow(true);?
    List?jdsInfoList = new ArrayList<>(2);?
    jdsInfoList.add(new JedisShardInfo("192.168.2.128", 6379));?
    jdsInfoList.add(new JedisShardInfo("192.168.2.108", 6379));?
    pool = new ShardedJedisPool(config, jdsInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);?
    jds.set(key, value);?
    ......?
    jds.close();?
    pool.close();?

    當然,采用這種方式也存在兩個問題

    擴容問題: 因為使用了一致性哈稀進行分片,那么不同的key分布到不同的Redis-Server上,當我們需要擴容時,需要增加機器到分片列表中,這時候會使得同樣的key算出來落到跟原來不同的機器上,這樣如果要取某一個值,會出現取不到的情況。?
    單點故障問題: 當集群中的某一臺服務掛掉之后,客戶端在根據一致性hash無法從這臺服務器取數據。

    對于擴容問題,Redis的作者提出了一種名為Pre-Sharding的方式。即事先部署足夠多的Redis服務。 對于單點故障問題,我們可以使用Redis的HA高可用來實現。利用Redis-Sentinal來通知主從服務的切換。當然,Jedis沒有實現這塊。我將會在下一篇文章進行介紹。


    5. 小結?

    對于Jedis的基本使用還是很簡單的。要根據不用的應用場景選擇對于的使用方式。 另外,Spring也提供了Spring-data-redis包來整合Jedis的操作,另外Spring也單獨分裝了Jedis(我將會在另外一篇文章介紹)。

    ?

    作者:曹金桂 鏈接:http://www.jianshu.com/p/a1038eed6d44 來源:簡書

  • 以上是Jedis使用教程完整版的內容,更多?整版?使用?教程?jedis?的內容,請您使用右上方搜索功能獲取相關信息。

轉載于:https://my.oschina.net/airship/blog/2875170

總結

以上是生活随笔為你收集整理的Jedis使用教程完整版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。