最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

jedis的return行為源碼解析

 更新時(shí)間:2023年09月22日 10:16:56   作者:codecraft  
這篇文章主要為大家介紹了jedis的return行為源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下jedis的return行為

spring-data-redis

RedisTemplate

org/springframework/data/redis/core/RedisTemplate.java

@Nullable
    public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
        Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
        Assert.notNull(action, "Callback object must not be null");
        RedisConnectionFactory factory = getRequiredConnectionFactory();
        RedisConnection conn = RedisConnectionUtils.getConnection(factory, enableTransactionSupport);
        try {
            boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
            RedisConnection connToUse = preProcessConnection(conn, existingConnection);
            boolean pipelineStatus = connToUse.isPipelined();
            if (pipeline && !pipelineStatus) {
                connToUse.openPipeline();
            }
            RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
            T result = action.doInRedis(connToExpose);
            // close pipeline
            if (pipeline && !pipelineStatus) {
                connToUse.closePipeline();
            }
            return postProcessResult(result, connToUse, existingConnection);
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory, enableTransactionSupport);
        }
    }
RedisTemplate的execute方法先通過(guò)RedisConnectionUtils.getConnection獲取連接,最后通過(guò)RedisConnectionUtils.releaseConnection來(lái)歸還連接

RedisConnectionUtils

org/springframework/data/redis/core/RedisConnectionUtils.java

public static void releaseConnection(@Nullable RedisConnection conn, RedisConnectionFactory factory,
            boolean transactionSupport) {
        releaseConnection(conn, factory);
    }
    public static void releaseConnection(@Nullable RedisConnection conn, RedisConnectionFactory factory) {
        if (conn == null) {
            return;
        }
        RedisConnectionHolder conHolder = (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory);
        if (conHolder != null) {
            if (conHolder.isTransactionActive()) {
                if (connectionEquals(conHolder, conn)) {
                    if (log.isDebugEnabled()) {
                        log.debug("RedisConnection will be closed when transaction finished.");
                    }
                    // It's the transactional Connection: Don't close it.
                    conHolder.released();
                }
                return;
            }
            // release transactional/read-only and non-transactional/non-bound connections.
            // transactional connections for read-only transactions get no synchronizer registered
            unbindConnection(factory);
            return;
        }
        doCloseConnection(conn);
    }
    private static void doCloseConnection(@Nullable RedisConnection connection) {
        if (connection == null) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("Closing Redis Connection.");
        }
        try {
            connection.close();
        } catch (DataAccessException ex) {
            log.debug("Could not close Redis Connection", ex);
        } catch (Throwable ex) {
            log.debug("Unexpected exception on closing Redis Connection", ex);
        }
    }
releaseConnection方法主要是處理了事務(wù)相關(guān)的操作,最后執(zhí)行doCloseConnection,它最后執(zhí)行的是connection.close()

connection.close()

org/springframework/data/redis/connection/jedis/JedisConnection.java

@Override
    public void close() throws DataAccessException {
        super.close();
        JedisSubscription subscription = this.subscription;
        try {
            if (subscription != null) {
                subscription.close();
            }
        } catch (Exception ex) {
            LOGGER.debug("Cannot terminate subscription", ex);
        } finally {
            this.subscription = null;
        }
        // return the connection to the pool
        if (pool != null) {
            jedis.close();
            return;
        }
        // else close the connection normally (doing the try/catch dance)
        try {
            jedis.quit();
        } catch (Exception ex) {
            LOGGER.debug("Failed to QUIT during close", ex);
        }
        try {
            jedis.disconnect();
        } catch (Exception ex) {
            LOGGER.debug("Failed to disconnect during close", ex);
        }
    }
connection的close方法針對(duì)使用連接池的會(huì)執(zhí)行jedis.close,否則執(zhí)行jedis.quit

jedis.close()

redis/clients/jedis/Jedis.java

@Override
  public void close() {
    if (dataSource != null) {
      JedisPoolAbstract pool = this.dataSource;
      this.dataSource = null;
      if (isBroken()) {
        pool.returnBrokenResource(this);
      } else {
        pool.returnResource(this);
      }
    } else {
      super.close();
    }
  }
jedis的close方法會(huì)先判斷isBroken(取的redis.clients.jedis.Connection.broken屬性),如果是則執(zhí)行returnBrokenResource,否則執(zhí)行returnResource

pool

redis/clients/jedis/util/Pool.java

public void returnBrokenResource(final T resource) {
    if (resource != null) {
      returnBrokenResourceObject(resource);
    }
  }
  public void returnResource(final T resource) {
    if (resource != null) {
      returnResourceObject(resource);
    }
  }
  protected void returnBrokenResourceObject(final T resource) {
    try {
      internalPool.invalidateObject(resource);
    } catch (Exception e) {
      throw new JedisException("Could not return the broken resource to the pool", e);
    }
  }
  protected void returnResourceObject(final T resource) {
    try {
      internalPool.returnObject(resource);
    } catch (RuntimeException e) {
      throw new JedisException("Could not return the resource to the pool", e);
    }
  }
returnBrokenResource執(zhí)行的是internalPool.invalidateObject(resource),而returnResourceObject執(zhí)行的是internalPool.returnObject(resource)

invalidateObject

org/apache/commons/pool2/impl/GenericObjectPool.java

public void invalidateObject(final T obj, final DestroyMode destroyMode) throws Exception {
        final PooledObject<T> p = getPooledObject(obj);
        if (p == null) {
            if (isAbandonedConfig()) {
                return;
            }
            throw new IllegalStateException(
                    "Invalidated object not currently part of this pool");
        }
        synchronized (p) {
            if (p.getState() != PooledObjectState.INVALID) {
                destroy(p, destroyMode);
            }
        }
        ensureIdle(1, false);
    }
    private void destroy(final PooledObject<T> toDestroy, final DestroyMode destroyMode) throws Exception {
        toDestroy.invalidate();
        idleObjects.remove(toDestroy);
        allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
        try {
            factory.destroyObject(toDestroy, destroyMode);
        } finally {
            destroyedCount.incrementAndGet();
            createCount.decrementAndGet();
        }
    }
invalidateObject方法執(zhí)行的是destroy方法,該方法會(huì)回調(diào)factory.destroyObject

destroyObject

redis/clients/jedis/JedisFactory.java

public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception {
    final BinaryJedis jedis = pooledJedis.getObject();
    if (jedis.isConnected()) {
      try {
        // need a proper test, probably with mock
        if (!jedis.isBroken()) {
          jedis.quit();
        }
      } catch (RuntimeException e) {
        logger.warn("Error while QUIT", e);
      }
      try {
        jedis.close();
      } catch (RuntimeException e) {
        logger.warn("Error while close", e);
      }
    }
  }

destroyObject方法則執(zhí)行jedis.close()關(guān)閉client連接

returnObject

org/apache/commons/pool2/impl/GenericObjectPool.java

public void returnObject(final T obj) {
        final PooledObject<T> p = getPooledObject(obj);
        if (p == null) {
            if (!isAbandonedConfig()) {
                throw new IllegalStateException(
                        "Returned object not currently part of this pool");
            }
            return; // Object was abandoned and removed
        }
        markReturningState(p);
        final Duration activeTime = p.getActiveDuration();
        if (getTestOnReturn() && !factory.validateObject(p)) {
            try {
                destroy(p, DestroyMode.NORMAL);
            } catch (final Exception e) {
                swallowException(e);
            }
            try {
                ensureIdle(1, false);
            } catch (final Exception e) {
                swallowException(e);
            }
            updateStatsReturn(activeTime);
            return;
        }
        try {
            factory.passivateObject(p);
        } catch (final Exception e1) {
            swallowException(e1);
            try {
                destroy(p, DestroyMode.NORMAL);
            } catch (final Exception e) {
                swallowException(e);
            }
            try {
                ensureIdle(1, false);
            } catch (final Exception e) {
                swallowException(e);
            }
            updateStatsReturn(activeTime);
            return;
        }
        if (!p.deallocate()) {
            throw new IllegalStateException(
                    "Object has already been returned to this pool or is invalid");
        }
        final int maxIdleSave = getMaxIdle();
        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
            try {
                destroy(p, DestroyMode.NORMAL);
            } catch (final Exception e) {
                swallowException(e);
            }
            try {
                ensureIdle(1, false);
            } catch (final Exception e) {
                swallowException(e);
            }
        } else {
            if (getLifo()) {
                idleObjects.addFirst(p);
            } else {
                idleObjects.addLast(p);
            }
            if (isClosed()) {
                // Pool closed while object was being added to idle objects.
                // Make sure the returned object is destroyed rather than left
                // in the idle object pool (which would effectively be a leak)
                clear();
            }
        }
        updateStatsReturn(activeTime);
    }

returnObject針對(duì)testOnReturn的會(huì)執(zhí)行validateObject方法,之后執(zhí)行factory.passivateObject(p),最后根據(jù)maxIdle的參數(shù)來(lái)判斷,超出的則執(zhí)行destroy,否則根據(jù)是否Lifo放回到連接池(idleObjects)中

小結(jié)

spring-data-redis的return主要是執(zhí)行connection的close方法,對(duì)應(yīng)到j(luò)edis就是jedis.close(),它會(huì)先判斷isBroken(取的redis.clients.jedis.Connection.broken屬性),如果是則執(zhí)行returnBrokenResource,否則執(zhí)行returnResource。

  • returnBrokenResource執(zhí)行的是internalPool.invalidateObject(resource),invalidateObject方法執(zhí)行的是destroy方法,該方法會(huì)回調(diào)factory.destroyObject方法,即執(zhí)行jedis.close()關(guān)閉client連接
  • returnObject針對(duì)testOnReturn的會(huì)執(zhí)行validateObject方法,之后執(zhí)行factory.passivateObject(p),最后根據(jù)maxIdle的參數(shù)來(lái)判斷,超出的則執(zhí)行destroy,否則根據(jù)是否Lifo放回到連接池(idleObjects)中
  • 也就說(shuō)假設(shè)獲取連接之后,執(zhí)行的時(shí)候redis掛了,redis.clients.jedis.Connection會(huì)標(biāo)記broken為true,同時(shí)拋出JedisConnectionException;而RedisTemplate是在finally中進(jìn)行releaseConnection,因而歸還的時(shí)候會(huì)觸發(fā)returnBrokenResource從而關(guān)閉壞掉的連接,間接實(shí)現(xiàn)testOnReturn的效果
  • 如果在獲取連接的時(shí)候,redis掛了,但是連接池仍然有連接,若沒(méi)有testOnBorrow則返回然后使用,但是使用的時(shí)候會(huì)報(bào)錯(cuò),即redis.clients.jedis.Connection會(huì)標(biāo)記broken為true,同時(shí)拋出JedisConnectionException,歸還的時(shí)候直接銷毀;若有testOnBorrow則validate的時(shí)候能驗(yàn)證出來(lái)連接有問(wèn)題,則會(huì)執(zhí)行destory然后繼續(xù)循環(huán)獲取連接池的連接,直到連接池連接沒(méi)有了;若獲取連接的時(shí)候連接池沒(méi)有空閑連接了,則走create的邏輯,這個(gè)時(shí)候create直接拋出redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket.

以上就是jedis的return行為源碼解析的詳細(xì)內(nèi)容,更多關(guān)于jedis return行為的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java判斷String類型是否能轉(zhuǎn)換為int的方法

    java判斷String類型是否能轉(zhuǎn)換為int的方法

    今天小編就為大家分享一篇java判斷String類型是否能轉(zhuǎn)換為int的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)

    SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了如何使用Vue、SpringBoot和EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-05-05
  • Java定時(shí)器Timer的源碼分析

    Java定時(shí)器Timer的源碼分析

    通過(guò)源碼分析,我們可以更深入的了解其底層原理。本文將通過(guò)Timer的源碼,帶大家深入了解Java?Timer的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • java二叉樹(shù)的幾種遍歷遞歸與非遞歸實(shí)現(xiàn)代碼

    java二叉樹(shù)的幾種遍歷遞歸與非遞歸實(shí)現(xiàn)代碼

    這篇文章主要介紹了java二叉樹(shù)的幾種遍歷遞歸與非遞歸實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2020-12-12
  • idea切換Git分支時(shí)保存未提交的文件方式

    idea切換Git分支時(shí)保存未提交的文件方式

    當(dāng)在開(kāi)發(fā)分支上修改了部分文件,但功能未完成且需要修復(fù)其他分支的bug時(shí),可以使用ShelveChanges或StashChanges暫存未提交的修改,之后在其他分支上進(jìn)行修復(fù),修復(fù)完畢后,再恢復(fù)暫存的修改
    2026-04-04
  • Java實(shí)現(xiàn)不同的類的屬性之間相互賦值

    Java實(shí)現(xiàn)不同的類的屬性之間相互賦值

    今天小編就為大家分享一篇關(guān)于Java實(shí)現(xiàn)不同的類的屬性之間相互賦值,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • SpringSecurity登錄使用JSON格式數(shù)據(jù)的方法

    SpringSecurity登錄使用JSON格式數(shù)據(jù)的方法

    這篇文章主要介紹了SpringSecurity登錄使用JSON格式數(shù)據(jù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • JAVA實(shí)現(xiàn)的CrazyArcade泡泡堂游戲

    JAVA實(shí)現(xiàn)的CrazyArcade泡泡堂游戲

    CrazyArcade泡泡堂游戲,一款用Java編寫的JavaSwing游戲程序。 使用了MVC模式,分離了模型、視圖和控制器,使得項(xiàng)目結(jié)構(gòu)清晰易于擴(kuò)展,使用配置文件來(lái)設(shè)置游戲基本配置,擴(kuò)展地圖人物道具等。同時(shí),該程序編寫期間用了單例模式、工廠模式、模板模式等設(shè)計(jì)模式。
    2021-04-04
  • Spring中FactoryBean的高級(jí)用法實(shí)戰(zhàn)教程

    Spring中FactoryBean的高級(jí)用法實(shí)戰(zhàn)教程

    FactoryBean是Spring框架的高級(jí)特性,允許自定義對(duì)象的創(chuàng)建過(guò)程,適用于復(fù)雜初始化邏輯,本文給大家介紹Spring中FactoryBean的高級(jí)用法實(shí)戰(zhàn),感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • Java格式化小數(shù)并保留兩位小數(shù)的四種方法

    Java格式化小數(shù)并保留兩位小數(shù)的四種方法

    Java中格式化小數(shù)并保留兩位小數(shù)的四種方法:使用DecimalFormat、String.format()、BigDecimal和NumberFormat,每種方法都有其適用場(chǎng)景和特點(diǎn),文章通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03

最新評(píng)論

同仁县| 枣阳市| 长白| 广汉市| 克山县| 白银市| 湖南省| 稷山县| 休宁县| 乌什县| 华安县| 永善县| 宁河县| 名山县| 正镶白旗| 上林县| 延庆县| 黄浦区| 沽源县| 丹阳市| 胶州市| 成都市| 安阳县| 孝感市| 海原县| 开封市| 绵竹市| 达孜县| 斗六市| 苍山县| 三台县| 保山市| 沧源| 唐海县| 乐陵市| 曲水县| 肃宁县| 扶绥县| 衡山县| 德令哈市| 肃宁县|