国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

redisTemplate 使用 setIfAbsent 返回 null 問題原理及解決辦法

這篇具有很好參考價(jià)值的文章主要介紹了redisTemplate 使用 setIfAbsent 返回 null 問題原理及解決辦法。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

redisTemplate 使用 setIfAbsent 返回 null 問題原理及解決辦法

1.簡(jiǎn)介

有的時(shí)候我們使用 redisTemplate給鎖設(shè)置超時(shí)時(shí)間的方法,設(shè)置鎖并返回的 lock 有可能不是 true 或 false,而是null。

Boolean lock = redisTemplate.opsForValue().setIfAbsent("redisTemplateTest鎖住了", "value", 10, TimeUnit.SECONDS);

setifabsent,redis,java,spring boot,redis,redistemplate

setifabsent,redis,java,spring boot,redis,redistemplate
從上圖我們可以看出雖然生成了鎖,但是返回的 lock 卻是 null ,這就會(huì)影響我們下面的代碼運(yùn)行。
下面我先說一下可能的產(chǎn)生原因和解決辦法,之后再詳細(xì)說一下原理。

2.產(chǎn)生原因及解決辦法

最直接的產(chǎn)生原因就是項(xiàng)目啟動(dòng)后缺少了 RedisConnectionFactory 這個(gè)bean,導(dǎo)致這一情況的發(fā)生有可能是引用了以下的jar包:

 		<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.10.6</version>
        </dependency>

解決辦法很簡(jiǎn)單:

1)換個(gè)jar包使用,如使用:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

或者該jar包配合 redisson 包共同使用:

 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.10.6</version>
        </dependency>

2)手動(dòng)加入 RedisConnectionFactory 這個(gè)bean:

	@Bean
    public RedisConnectionFactory redisConnectionFactory(){
        return new LettuceConnectionFactory();
    }

3.產(chǎn)生的原理

首先我們要對(duì) springboot 自動(dòng)裝配有一定了解,SpringBoot 啟動(dòng)時(shí)會(huì)加載所有 META-INF 文件夾下的 spring.factories 文件,在其中找到要裝配的類。

setifabsent,redis,java,spring boot,redis,redistemplate

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

這只是眾多 spring.factories 的文件中的一個(gè) , 從上面我們可以看到 spring 自動(dòng)配置了 RedisAutoConfiguration 這個(gè)bean。下面我們展示一下 RedisAutoConfiguration 的源碼:

public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

從上面的源碼中我們可以得知,裝配 RedisAutoConfiguration 這個(gè)bean 的時(shí)候,同時(shí)也會(huì)裝載 redisTemplate 和 StringRedisTemplate 這兩個(gè) bean ,并且這兩個(gè)bean 都是基于 RedisConnectionFactory 去構(gòu)建的。

下面我們來看一下 RedisConnectionFactory 的結(jié)構(gòu) :

setifabsent,redis,java,spring boot,redis,redistemplate

從上圖我們可以看出 RedisConnectionFactory 作為一個(gè)接口,有 JedisConnectionFactory 和 LettuceConnectionFactory 這兩個(gè)實(shí)現(xiàn)類。

從上面的所有信息中我們可以得知,我們所使用的 redisTemplate 和 StringRedisTemplate 是通過 JedisConnectionFactory 和 LettuceConnectionFactory 這兩個(gè)實(shí)現(xiàn)類來構(gòu)建的。

下面我們驗(yàn)證一下該結(jié)論:

首先我們只引用 spring-boot-starter-data-redis jar包:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

setifabsent,redis,java,spring boot,redis,redistemplate

setifabsent,redis,java,spring boot,redis,redistemplate

從上圖可以看出確實(shí)是我們推論的 redisTemplate 和 StringRedisTemplate 是通過 LettuceConnectionFactory 來構(gòu)建的。

我們可以嘗試在啟動(dòng)項(xiàng)目的時(shí)候打印 spring 容器中的所有 bean 來看一下,以上 redis 的 bean 是否存在。

@SpringBootApplication
public class ApplicationStarter {

    public static void main(String[] args) {
        //1.返回我們IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(ApplicationStarter.class, args);

        //2.查看容器里面的組件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }

}

setifabsent,redis,java,spring boot,redis,redistemplate
從上圖可以看出理應(yīng)存在的 bean 全部都已經(jīng)生成完畢,致此,redisTemplate 正常的使用已經(jīng)說明完畢了。

那么接下來讓我們來演示一下為什么獲取到了鎖還會(huì)產(chǎn)生 lock = null 這種情況:
setifabsent,redis,java,spring boot,redis,redistemplate

下面我們使用一下 redisson-spring-boot-starter 這個(gè)jar包:

 		<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.10.6</version>
        </dependency>

setifabsent,redis,java,spring boot,redis,redistemplate
從上圖我們可以看到該jar包配置了 RedissonAutoConfiguration 這個(gè)新的 bean 。那么讓我們看一下 RedissonAutoConfiguration 的源碼:

public class RedissonAutoConfiguration {
    @Autowired
    private RedissonProperties redissonProperties;
    @Autowired
    private RedisProperties redisProperties;
    @Autowired
    private ApplicationContext ctx;

    public RedissonAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean({StringRedisTemplate.class})
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean({RedisConnectionFactory.class})
    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
        return new RedissonConnectionFactory(redisson);
    }

    @Bean(
        destroyMethod = "shutdown"
    )
    @ConditionalOnMissingBean({RedissonClient.class})
    public RedissonClient redisson() throws IOException {
        Config config = null;
        Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");
        Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");
        Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, this.redisProperties);
        int timeout;
        Method nodesMethod;
        if (null == timeoutValue) {
            timeout = 0;
        } else if (!(timeoutValue instanceof Integer)) {
            nodesMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis");
            timeout = ((Long)ReflectionUtils.invokeMethod(nodesMethod, timeoutValue)).intValue();
        } else {
            timeout = (Integer)timeoutValue;
        }

        if (this.redissonProperties.getConfig() != null) {
            try {
                InputStream is = this.getConfigStream();
                config = Config.fromJSON(is);
            } catch (IOException var11) {
                try {
                    InputStream is = this.getConfigStream();
                    config = Config.fromYAML(is);
                } catch (IOException var10) {
                    throw new IllegalArgumentException("Can't parse config", var10);
                }
            }
        } else if (this.redisProperties.getSentinel() != null) {
            nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes");
            Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, this.redisProperties.getSentinel());
            String[] nodes;
            if (nodesValue instanceof String) {
                nodes = this.convert(Arrays.asList(((String)nodesValue).split(",")));
            } else {
                nodes = this.convert((List)nodesValue);
            }

            config = new Config();
            ((SentinelServersConfig)config.useSentinelServers().setMasterName(this.redisProperties.getSentinel().getMaster()).addSentinelAddress(nodes).setDatabase(this.redisProperties.getDatabase()).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
        } else {
            Method method;
            if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties) != null) {
                Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties);
                method = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");
                List<String> nodesObject = (List)ReflectionUtils.invokeMethod(method, clusterObject);
                String[] nodes = this.convert(nodesObject);
                config = new Config();
                ((ClusterServersConfig)config.useClusterServers().addNodeAddress(nodes).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
            } else {
                config = new Config();
                String prefix = "redis://";
                method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl");
                if (method != null && (Boolean)ReflectionUtils.invokeMethod(method, this.redisProperties)) {
                    prefix = "rediss://";
                }

                ((SingleServerConfig)config.useSingleServer().setAddress(prefix + this.redisProperties.getHost() + ":" + this.redisProperties.getPort()).setConnectTimeout(timeout)).setDatabase(this.redisProperties.getDatabase()).setPassword(this.redisProperties.getPassword());
            }
        }

        return Redisson.create(config);
    }

    private String[] convert(List<String> nodesObject) {
        List<String> nodes = new ArrayList(nodesObject.size());
        Iterator var3 = nodesObject.iterator();

        while(true) {
            while(var3.hasNext()) {
                String node = (String)var3.next();
                if (!node.startsWith("redis://") && !node.startsWith("rediss://")) {
                    nodes.add("redis://" + node);
                } else {
                    nodes.add(node);
                }
            }

            return (String[])nodes.toArray(new String[nodes.size()]);
        }
    }

    private InputStream getConfigStream() throws IOException {
        Resource resource = this.ctx.getResource(this.redissonProperties.getConfig());
        InputStream is = resource.getInputStream();
        return is;
    }
}

從以上代碼可以看出 RedissonAutoConfiguration 是先構(gòu)建 RedissonClient ,之后通過 RedissonClient 構(gòu)建 RedissonConnectionFactory ,然后通過 RedissonConnectionFactory 構(gòu)建 redisTemplate 和 StringRedisTemplate 。和之前構(gòu)建 redisTemplate 的不同主要在于使用了不同的 RedisConnectionFactory 實(shí)現(xiàn)類:

setifabsent,redis,java,spring boot,redis,redistemplate
我們同樣打印一下 spring 容器中的 bean 看一下:

setifabsent,redis,java,spring boot,redis,redistemplate
從上文兩種jar包的對(duì)比,我們可以得知兩種方式獲取 redisTemplate 的區(qū)別正是在于 RedisConnectionFactory 的實(shí)現(xiàn)類不同,而這也是導(dǎo)致 lock = null 的原因所在。 redisson 底層調(diào)用了大量的 netty 包,該jar包自帶的 RedissonConnectionFactory 影響了之前的返回邏輯,下面我們簡(jiǎn)單驗(yàn)證一下推論:

setifabsent,redis,java,spring boot,redis,redistemplate
setifabsent,redis,java,spring boot,redis,redistemplate
從上圖可以看出該jar包確實(shí)是通過 RedissonConnectionFactory 構(gòu)建 redisTemplate ,并且返回的 lock 為 null 。

下面我們手動(dòng)加入 RedisConnectionFactory 這個(gè)bean進(jìn)行對(duì)照看下:

	@Bean
    public RedisConnectionFactory redisConnectionFactory(){
        return new LettuceConnectionFactory();
    }

setifabsent,redis,java,spring boot,redis,redistemplate

setifabsent,redis,java,spring boot,redis,redistemplate
從上面的對(duì)比可以看出我們的推論完全是正確的, redisson-spring-boot-starter 這個(gè)jar包的 RedissonConnectionFactory 影響了原本的判斷,導(dǎo)致返回 lock=null 這種現(xiàn)象。

由于 Redisson 里面運(yùn)用了大量的回調(diào)方法、匿名表達(dá)式、異步操作等難以debug的方法,所以我這里只在表層進(jìn)行了問題的排查與解決,如果有哪位大佬具體排查出在代碼運(yùn)行中具體是什么原因?qū)е铝耸褂?RedissonConnectionFactory 返回 lock=null 這種現(xiàn)象。使用它與使用 LettuceConnectionFactory 的返回差異具體體現(xiàn)在哪里的話麻煩告知一聲。文章來源地址http://www.zghlxwxcb.cn/news/detail-754689.html

到了這里,關(guān)于redisTemplate 使用 setIfAbsent 返回 null 問題原理及解決辦法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • SurfaceControl.screenshot()用法 | SurfaceControl.screenshot()使用后返回null的解決方案

    SurfaceControl.screenshot() 是系統(tǒng)的截屏方法,屬于系統(tǒng)API,對(duì)用戶不開放,因此要使用的話需要系統(tǒng)的簽名( platform.keystore 文件)才能調(diào)用到。 在高版本的android上(例如 android 11 ),如果沒有系統(tǒng)簽名,即使用反射也會(huì)報(bào)找不到方法的異常,但是有系統(tǒng)簽名的話,直接調(diào)用就行。 網(wǎng)

    2024年02月10日
    瀏覽(33)
  • 解決SUM函數(shù)返回為NULL

    SUM函數(shù)的作用:計(jì)算某一字段中所有行的數(shù)值和, 使用SUM函數(shù)進(jìn)行對(duì)符合條件的結(jié)果行數(shù)進(jìn)行求和。 sum 求和時(shí)會(huì)對(duì) null 進(jìn)行過濾,不計(jì)算,但如果沒有返回結(jié)果,則sum 函數(shù)的返回值為 null,不是 0: 1. IFNULL 使用IFNULL函數(shù)進(jìn)行查詢,判斷第一個(gè)參數(shù)是否為null,如果是 則返回

    2024年02月08日
    瀏覽(14)
  • reids自定義RedisTemplate以及亂碼問題解決

    ? ? ? ? 1,使用 ObjectMapper().writeValueAsString(*); ???????? ? ? ? ? 2,所有pojo實(shí)現(xiàn)?Serializable接口 ? ? ? ? 3,自定義序列化,企業(yè)開發(fā)中可以直接使用 ???????? 我要保證使用到了我們自定義的RedisTemplate 使用添加注解 當(dāng)可以點(diǎn)進(jìn)去 即為成功! 使用RedisTemplate需要頻繁調(diào)用

    2024年04月09日
    瀏覽(21)
  • Android11 相機(jī)拍照權(quán)限,以及解決resolveActivity返回null

    Android11 相機(jī)拍照權(quán)限,以及解決resolveActivity返回null

    一、配置拍照和讀寫權(quán)限 二、手動(dòng)申請(qǐng)權(quán)限 ????????implementation \\\'com.permissionx.guolindev:permissionx:1.4.0\\\' ??????? 1、手動(dòng)申請(qǐng)讀寫,拍照權(quán)限 ??????? 2、手動(dòng)申請(qǐng)文件管理權(quán)限 三、Manifest中配置queries(解決resolveActivity為null) 四、Manifest中配置provider 五、配置file_paths文件

    2024年02月15日
    瀏覽(30)
  • 【解決問題思路分析】記錄hutool默認(rèn)使用服務(wù)端上次返回cookie的問題解決思路

    【解決問題思路分析】記錄hutool默認(rèn)使用服務(wù)端上次返回cookie的問題解決思路

    本服務(wù)需要調(diào)用第三方接口獲取數(shù)據(jù),首先調(diào)用public-key接口獲取公鑰,然后用公鑰加密密碼,將用戶名和密碼傳入/ticket接口,獲取Cookie和response body中的token。 由于是調(diào)用第三方接口出現(xiàn)問題,第一步先拉通第三方對(duì)接人查看后臺(tái)日志,對(duì)方使用apisix作為api網(wǎng)關(guān),初步判斷是

    2024年02月07日
    瀏覽(22)
  • uniapp微信小程序 頁(yè)面返回使用navigateBack,返回后頁(yè)面不刷新問題解決方案

    嘗試了眾多方法,比如vuex,本地緩存,都不行 1,如果是頁(yè)面之間的跳轉(zhuǎn) 可以使用onShow生命周期請(qǐng)求數(shù)據(jù) 2,組件之間的跳轉(zhuǎn),使用redirectTo,通過關(guān)閉當(dāng)前頁(yè)面,跳轉(zhuǎn)到指定頁(yè)面再加載,這種適合二級(jí)頁(yè)面到三級(jí)頁(yè)面數(shù)據(jù)不更新問題 3,當(dāng)一級(jí)頁(yè)面使用了某個(gè)組件,組件內(nèi)跳轉(zhuǎn)

    2024年02月15日
    瀏覽(93)
  • 微信小程序使用自定義tabbar 想要獲取tabbar的高度,返回的結(jié)果是null,該如何獲取?

    在使用自定義tabbar時(shí),你可能會(huì)需要獲取tabbar的高度,但是按照網(wǎng)上的方法卻得不到正確的結(jié)果,這讓你十分頭疼。那么該怎么辦呢?小編為大家整理了以下幾個(gè)方法,希望能夠幫到大家。 1?? 使用wx.getSystemInfoSync()方法獲取系統(tǒng)信息,然后通過計(jì)算得出tabbar的高度。 示例

    2024年02月11日
    瀏覽(41)
  • mybatis-plus 查詢數(shù)據(jù)為null問題解決

    mybatis-plus 查詢數(shù)據(jù)為null問題解決

    首先數(shù)據(jù)庫(kù)能查詢到數(shù)據(jù), 不過查詢到的字段都是 null 值, 因?yàn)闃I(yè)務(wù)上就用到這3個(gè)字段 代碼中使用 mybatis-plus 精確字段查詢, select方法可以精確查詢字段 之后debug看到 orderMain 對(duì)象為 null, 因?yàn)?這 3 個(gè)字段在數(shù)據(jù)庫(kù)表中都是 null 解決方式是把 select方法需要查詢一個(gè)數(shù)據(jù)庫(kù)中不為

    2024年02月11日
    瀏覽(24)
  • json_decode返回NULL

    json_decode返回NULL

    最近在調(diào)用某公司的API時(shí),將對(duì)方返回的數(shù)據(jù),使用PHP的json_decode函數(shù)解析,但是返回NULL,最終排查為對(duì)方傳送來的json格式有誤 打印$_REQUEST,數(shù)據(jù)結(jié)構(gòu)大致如下: 1 2 3 4 5 6 7 8 9 10 array ? ( ?? \\\'TeleRec\\\' ? = \\\'{ ?? Tel:\\\'17090114281\\\', ?? Type:2, ?? StartTime:\\\'2016/9/19 10:19:29\\\', ?? EnteTime

    2024年02月10日
    瀏覽(17)
  • Mybatis 批量新增 只返回第一主鍵ID 其他返回null

    出現(xiàn) 問題 是加 on duplicate key update 受了影響, 去掉 on duplicate key update代碼 ON DUPLICATE key update是根據(jù)索引字段是否重復(fù)來判斷是否執(zhí)行,如果重復(fù)則執(zhí)行update,否則則執(zhí)行insert。 優(yōu)先級(jí)主鍵唯一索引 當(dāng)主鍵重復(fù)時(shí)則執(zhí)行update 當(dāng)主鍵不重復(fù),唯一索引重復(fù)時(shí)也執(zhí)行update 當(dāng)主鍵

    2024年02月16日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包