英语老师解开裙子坐我腿中间,亚洲精品国产电影,曰本性l交片免费看,大胸美女视频

您的位置:首頁(yè) >寬帶 > 正文

[Redis]Spring Boot中Redis Template集群配置 頭條

來(lái)源:騰訊云 時(shí)間:2023-03-16 18:01:36

1、問(wèn)題背景

在一個(gè)Spring boot項(xiàng)目中,需要使用redis作為緩存,于是將使用spring-boot-starter-data-redis,具體依賴如下:

org.springframework.bootspring-boot-starter-data-redis2.0.4.RELEASE

在測(cè)試環(huán)境中,功能測(cè)試,壓力測(cè)試,都沒(méi)有發(fā)現(xiàn)問(wèn)題,原因是測(cè)試環(huán)境中redis自行搭建,沒(méi)有設(shè)置密碼,但是上線后,Redis使用的是A***的Pass服務(wù)的集群,并設(shè)置密碼,使用過(guò)程中發(fā)現(xiàn)如下問(wèn)題:


(相關(guān)資料圖)

redis負(fù)載高;redis異常,錯(cuò)誤信息: com.lambdaworks.redis.RedisException: java.lang.IllegalArgumentException: Connection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster viewjava.lang.IllegalArgumentException: Connection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster viewConnection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster view

2、問(wèn)題分析+解決方法

2.1、redis負(fù)載過(guò)高問(wèn)題

2.1.1、問(wèn)題原因

原本打算看一下是否是代碼邏輯問(wèn)題導(dǎo)致redis負(fù)載過(guò)高,于是登錄redis服務(wù)器使用monitor命令觀察命令執(zhí)行的頻率,發(fā)現(xiàn)每執(zhí)行一次命令都執(zhí)行一次Auth password命令,說(shuō)明連接池未正確使用導(dǎo)致執(zhí)行一次命令創(chuàng)建一次連接,導(dǎo)致負(fù)載高 ,并且代碼執(zhí)行效率低 。

2.1.2、解決方法

然后對(duì)比了使用JedisCluster的項(xiàng)目沒(méi)有此類問(wèn)題,因此懷疑是spring-boot-starter-data-redis的RedisTemplate的問(wèn)題,查看源碼后發(fā)現(xiàn)spring-data-redis的驅(qū)動(dòng)包在某個(gè)版本之后替換為 Lettuce,在啟用集群后jedis的連接池?zé)o效。錯(cuò)誤配置如下:

# 錯(cuò)誤配置# Redis配置spring.redis.cluster.nodes=127.0.0.1:6379### 連接超時(shí)時(shí)間(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)spring.redis.jedis.pool.max-active=8##連接池最大阻塞等待時(shí)間,若使用負(fù)值表示沒(méi)有限制spring.redis.jedis.pool.max-wait=-1##連接池中的最大空閑連接spring.redis.jedis.pool.max-idle=8# 連接池中的最小空閑連接spring.redis.jedis.pool.min-idle=0

需要改成正確的配置,修改之后無(wú)此現(xiàn)象,具體配置如下:

單機(jī)版:

# 單機(jī)版# Redis配置spring.redis.host=127.0.0.1spring.redis.port=6379### 連接超時(shí)時(shí)間(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)spring.redis.jedis.pool.max-active=8##連接池最大阻塞等待時(shí)間,若使用負(fù)值表示沒(méi)有限制spring.redis.jedis.pool.max-wait=-1##連接池中的最大空閑連接spring.redis.jedis.pool.max-idle=8# 連接池中的最小空閑連接spring.redis.jedis.pool.min-idle=0

集群版:

#集群版 # Redis配置spring.redis.cluster.nodes=127.0.0.1:6379### 連接超時(shí)時(shí)間(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)spring.redis.lettuce.pool.max-active=8##連接池最大阻塞等待時(shí)間,若使用負(fù)值表示沒(méi)有限制spring.redis.lettuce.pool.max-wait=-1##連接池中的最大空閑連接spring.redis.lettuce.pool.max-idle=8# 連接池中的最小空閑連接spring.redis.lettuce.pool.min-idle=0

注意:?jiǎn)⒂眉喊?,需要額外添加如下依賴

org.apache.commonscommons-pool22.8.0

2.2、redis異常 Connection to XXX.XX.XXX.XXX:15000 not allowed 問(wèn)題

2.2.1、問(wèn)題原因

網(wǎng)上搜索了一下,發(fā)現(xiàn)項(xiàng)目github上已有此問(wèn)題的反饋以及解決辦法github.com/lettuce-io/…,原因是由于Lettuce其中有個(gè)配置項(xiàng)validateClusterNodeMembership 默認(rèn)是true導(dǎo)致;

2.2.2、解決辦法

由于spring boot未能直接通過(guò)配置文件直接修改此配置,因此需要自定義Redis配置,具體代碼如下: MylettuceConnectionFactory.java

package com.quison.test.config;import io.lettuce.core.AbstractRedisClient;import io.lettuce.core.cluster.ClusterClientOptions;import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;import io.lettuce.core.cluster.RedisClusterClient;import org.springframework.beans.DirectFieldAccessor;import org.springframework.data.redis.connection.RedisClusterConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;import java.util.concurrent.TimeUnit;public class MyLettuceConnectionFactory extends LettuceConnectionFactory {    public MyLettuceConnectionFactory() { }    public MyLettuceConnectionFactory(RedisClusterConfiguration redisClusterConfiguration, LettuceClientConfiguration lettuceClientConfiguration) {        super(redisClusterConfiguration, lettuceClientConfiguration);    }    @Override    public void afterPropertiesSet() {        super.afterPropertiesSet();        DirectFieldAccessor accessor = new DirectFieldAccessor(this);        AbstractRedisClient client = (AbstractRedisClient) accessor.getPropertyValue("client");        if(client instanceof RedisClusterClient){            RedisClusterClient clusterClient = (RedisClusterClient) client;            ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()                    .enablePeriodicRefresh(10, TimeUnit.MINUTES)                    .enableAllAdaptiveRefreshTriggers()                    .build();            ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()                     // 注意此配置項(xiàng)設(shè)置為false                    .validateClusterNodeMembership(false)                    .topologyRefreshOptions(topologyRefreshOptions)                    .build();            clusterClient.setOptions(clusterClientOptions);        }    }}

由于配置后,連接池也需要自行設(shè)置,因此Redis的配置文件修改為如下設(shè)置 RedisConfig.java

package com.quison.test.config;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.data.redis.connection.*;import org.springframework.data.redis.connection.lettuce.DefaultLettucePool;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;import java.util.Arrays;import java.util.HashSet;import java.util.Set;@Configurationpublic class RedisConfig {    @Value("${spring.redis.cluster.nodes}")    private String clusterNodes;    @Value("${spring.redis.password}")    private String password;    @Value("${spring.redis.lettuce.pool.max-idle}")    private Integer maxIdle;    @Value("${spring.redis.lettuce.pool.max-active}")    private Integer maxActive;    @Value("${spring.redis.cluster.max-redirects}")    private Integer maxRedirects;    @Bean    public RedisConnectionFactory myRedisConnectionFactory() {        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();        String[] serverArray = clusterNodes.split(",");        Set nodes = new HashSet();        for (String ipPort : serverArray) {            String[] ipAndPort = ipPort.split(":");            nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));        }        redisClusterConfiguration.setPassword(RedisPassword.of(password));        redisClusterConfiguration.setClusterNodes(nodes);        redisClusterConfiguration.setMaxRedirects(maxRedirects);        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();        genericObjectPoolConfig.setMaxIdle(maxIdle);        genericObjectPoolConfig.setMinIdle(8);        genericObjectPoolConfig.setMaxTotal(maxActive);        genericObjectPoolConfig.setMaxWaitMillis(10000);        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()                .commandTimeout(Duration.ofMillis(10000))                .poolConfig(genericObjectPoolConfig)                .build();        return new MyLettuceConnectionFactory(redisClusterConfiguration, clientConfig);    }    /**     * redis模板,存儲(chǔ)關(guān)鍵字是字符串,值是Jdk序列化     *     * @param myRedisConnectionFactory     * @return     * @Description:     */    @Bean    @ConditionalOnMissingBean(name = "redisTemplate")    @Primary    public RedisTemplate redisTemplate(RedisConnectionFactory myRedisConnectionFactory) {        RedisTemplate redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(myRedisConnectionFactory);        //key序列化方式;但是如果方法上有Long等非String類型的話,會(huì)報(bào)類型轉(zhuǎn)換錯(cuò)誤;        RedisSerializer redisSerializer = new StringRedisSerializer();        redisTemplate.setKeySerializer(redisSerializer);        redisTemplate.setHashKeySerializer(redisSerializer);        //默認(rèn)使用JdkSerializationRedisSerializer序列化方式;會(huì)出現(xiàn)亂碼,改成StringRedisSerializer        StringRedisSerializer stringSerializer = new StringRedisSerializer();        redisTemplate.setKeySerializer(stringSerializer);        redisTemplate.setValueSerializer(stringSerializer);        redisTemplate.setHashKeySerializer(stringSerializer);        redisTemplate.setHashValueSerializer(stringSerializer);        return redisTemplate;    }}

3、總結(jié)

吃一塹、長(zhǎng)一智,總結(jié)如下:

開(kāi)發(fā)+測(cè)試環(huán)境盡量與線上一致,可提前發(fā)現(xiàn)問(wèn)題;使用新技術(shù)需要多多測(cè)試再投入生產(chǎn)使用;

標(biāo)簽:

相關(guān)閱讀

50厘米全进去xxxx猛交| 电梯里吸乳挺进我的身体视频| 亚洲va久久久噜噜噜久久狠狠| 亚洲无码一区二区三区| 性色AV一二三天美传媒| 日韩+国产| 1313久久国产午夜精品理论片| 美式忌讳1~4经典电影2| 男男调教后菊撑开扩张a片| 久久久国产一区二区三区四区小说| 老牛嫩草一区二区三区| 皇上当众进入太子np主受| 极品美女扒开粉嫩小泬| 熟妇人妻va精品中文字幕| 小受被老攻c到哭着求饶视频| 色戒汤唯未删减版的在线观看| 欧美av人人妻av人人爽苍井空| 纯肉大根巨无霸纯黑胡椒火腿肠| 草色噜噜噜av在线观看香蕉| 精品无码成人片一区二区98| 铁矿石期货实时行情| 一区二区三区在线 | 欧| av视频在线观看| 大战丰满人妻性色AV偷偷 | 无码精品日韩专区第一页| 狠狠噜天天噜日日噜| 少妇高潮一区二区三区99| 日本亚洲精品无码区国产电影| 亚洲熟妇色xxxxx欧美老妇 | 黑人大群XXXX| 浪荡艳妇爆乳jufd汗だく肉感| 久久久久亚洲AV成人片一区| 全肉变态重口调教高辣小说| 少妇被粗大猛进进出出| 无码一区二区三区免费| 女人高潮真实叫床声mp3| 久久精品国产亚洲av无码| 男男h黄漫画啪啪无遮挡| 亚洲无码一区二区三区| 亚洲午夜av久久久精品影院色戒| 又爆又大又粗又硬又黄的a片|