1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        SpringBoot 項目接入 Redis 集群

        共 20696字,需瀏覽 42分鐘

         ·

        2020-09-25 01:00

        每天早上七點三十,準(zhǔn)時推送干貨

        Hello 大家好,我是鴨血粉絲,Redis 想必大家一定不會陌生,平常工作中或多或少都會用到,不管是用來存儲登錄信息還是用來緩存熱點數(shù)據(jù),對我們來說都是很有幫助的。但是 Redis 的集群估計并不是每個人都會用到,因為很多業(yè)務(wù)場景或者系統(tǒng)都是一些簡單的管理系統(tǒng),并不會需要用到 Redis 的集群環(huán)境。

        阿粉之前也是這樣,項目中用的的 Redis 是個單機(jī)環(huán)境,但是最近隨著終端量的上升,慢慢的發(fā)現(xiàn)單機(jī)已經(jīng)快支撐不住的,所以思考再三決定將 Redis 的環(huán)境升級成集群。下面阿粉給大家介紹一下在升級的過程中項目中需要調(diào)整的地方,這篇文章不涉及集群的搭建和配置,感興趣的同學(xué)自行搜索。

        配置參數(shù)

        因為這篇文章不介紹 Redis 集群的搭建,這里我們假設(shè)已經(jīng)有了一個 Redis 的集群環(huán)境,我們項目中需要調(diào)整以下幾個部分

        1. 修改配置參數(shù),集群的節(jié)點和密碼配置;
        2. 確保引入的 Jedis 版本支持設(shè)置密碼,spring-data-redis 1.8 以上,SpringBoot 1.5 以上才支持設(shè)置密碼;
        3. 注入 RedisTemplate
        4. 編寫工具類;

        修改配置參數(shù)

        ############### Redis 集群配置 #########################
        spring.custome.redis.cluster.nodes=172.20.0.1:7001,172.20.0.2:7002,172.20.0.3:7003
        spring.custome.redis.cluster.max-redirects=3
        spring.custome.redis.cluster.max-active=500
        spring.custome.redis.cluster.max-wait=-1
        spring.custome.redis.cluster.max-idle=500
        spring.custome.redis.cluster.min-idle=20
        spring.custome.redis.cluster.timeout=3000
        spring.custome.redis.cluster.password=redis.cluster.password

        引入依賴(如果需要)

        確保 SpringBoot 的版本大于 1.4.x 如果不是的話,采用如下配置,先排除 SpringBoot 中舊版本 Jedis 和 spring-data-redis,再依賴高版本的 Jedis 和 spring-data-redis。

               
              
               
                    org.springframework.boot
                    spring-boot-starter-data-redis
                   
                   
                       
                            redis.clients
                            jedis
                       

                       
                            org.springframework.data
                            spring-data-redis
                       

                   

               

               
               
                    redis.clients
                    jedis
                    2.9.0
               

               
                    org.springframework.data
                    spring-data-redis
                    1.8.0.RELEASE
               

        注入 RedisTemplate

        注入 RedisTemplate 我們需要三個組件,分別是JedisConnectionFactory 、RedisClusterConfigurationJedisPoolConfig,下面是注入RedisTempalte 的代碼。先根據(jù)配置創(chuàng)建 JedisConnectFactory 同時需要配置 RedisClusterConfiguration、JedisPoolConfig,最后將JedisConnectionFactory 返回用于創(chuàng)建RedisTemplate


        import com.fasterxml.jackson.annotation.JsonAutoDetect;
        import com.fasterxml.jackson.annotation.PropertyAccessor;
        import com.fasterxml.jackson.databind.ObjectMapper;
        import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
        import org.springframework.beans.factory.annotation.Value;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Primary;
        import org.springframework.data.redis.connection.RedisClusterConfiguration;
        import org.springframework.data.redis.connection.RedisNode;
        import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
        import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
        import org.springframework.data.redis.core.RedisTemplate;
        import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
        import org.springframework.data.redis.serializer.StringRedisSerializer;

        import java.time.Duration;
        import java.util.ArrayList;
        import java.util.List;

        public class RedisClusterConfig {

            @Bean(name = "redisTemplate")
            @Primary
            public RedisTemplate redisClusterTemplate(@Value("${spring.custome.redis.cluster.nodes}") String host,
                                             @Value("${spring.custome.redis.cluster.password}") String password,
                                             @Value("${spring.custome.redis.cluster.timeout}") long timeout,
                                             @Value("${spring.custome.redis.cluster.max-redirects}") int maxRedirect,
                                             @Value("${spring.custome.redis.cluster.max-active}") int maxActive,
                                             @Value("${spring.custome.redis.cluster.max-wait}") int maxWait,
                                             @Value("${spring.custome.redis.cluster.max-idle}") int maxIdle,
                                             @Value("${spring.custome.redis.cluster.min-idle}") int minIdle) 
        {

                JedisConnectionFactory connectionFactory =  jedisClusterConnectionFactory(host, password,
                        timeout, maxRedirect, maxActive, maxWait, maxIdle, minIdle);
                return createRedisClusterTemplate(connectionFactory);
            }

            private JedisConnectionFactory jedisClusterConnectionFactory(String host, String password,
                                                                           long timeout, int maxRedirect, int maxActive, int maxWait, int maxIdle, int minIdle)
         
        {
                RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
                List  nodeList =  new ArrayList<>();
                String[] cNodes = host.split( ",");
                 //分割出集群節(jié)點
                 for (String node : cNodes) {
                    String[] hp = node.split( ":");
                    nodeList.add( new RedisNode(hp[ 0], Integer.parseInt(hp[ 1])));
                }
                redisClusterConfiguration.setClusterNodes(nodeList);
                redisClusterConfiguration.setPassword(password);
                redisClusterConfiguration.setMaxRedirects(maxRedirect);

                 // 連接池通用配置
                GenericObjectPoolConfig genericObjectPoolConfig =  new GenericObjectPoolConfig();
                genericObjectPoolConfig.setMaxIdle(maxIdle);
                genericObjectPoolConfig.setMaxTotal(maxActive);
                genericObjectPoolConfig.setMinIdle(minIdle);
                genericObjectPoolConfig.setMaxWaitMillis(maxWait);
                genericObjectPoolConfig.setTestWhileIdle( true);
                genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis( 300000);

                JedisClientConfiguration.DefaultJedisClientConfigurationBuilder builder = (JedisClientConfiguration.DefaultJedisClientConfigurationBuilder) JedisClientConfiguration
                        .builder();
                builder.connectTimeout(Duration.ofSeconds(timeout));
                builder.usePooling();
                builder.poolConfig(genericObjectPoolConfig);
                JedisConnectionFactory connectionFactory =  new JedisConnectionFactory(redisClusterConfiguration, builder.build());
                 // 連接池初始化
                connectionFactory.afterPropertiesSet();

                 return connectionFactory;
            }

             private RedisTemplate createRedisClusterTemplate(JedisConnectionFactory redisConnectionFactory) {
                RedisTemplate  redisTemplate =  new RedisTemplate<>();
                redisTemplate.setConnectionFactory(redisConnectionFactory);

                Jackson2JsonRedisSerializer  jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
                ObjectMapper om = new ObjectMapper();
                om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
                om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
                jackson2JsonRedisSerializer.setObjectMapper(om);

                StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
                // key采用String的序列化方式
                redisTemplate.setKeySerializer(stringRedisSerializer);
                // hash的key也采用String的序列化方式
                redisTemplate.setHashKeySerializer(stringRedisSerializer);
                // value序列化方式采用jackson
                redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
                // hash的value序列化方式采用jackson
                redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
                redisTemplate.afterPropertiesSet();

                return redisTemplate;
            }
        }

        相關(guān)代碼已經(jīng)提交到GitHub,公眾號回復(fù)【源碼倉庫】即可獲取。這里一定要注意 Jedis 的 Spring-data-redis 的版本支持設(shè)置密碼,畢竟生產(chǎn)環(huán)境是一定要配置密碼的。

        編寫工具類

        其實到這里基本上已經(jīng)完成了,我們可以看到 SpringBoot 項目接入 Redis 集群還是比較簡單的,而且如果之前單機(jī)環(huán)境就是采用RedisTemplate 的話,現(xiàn)在也就不需要編寫工具類,之前的操作依舊有效。不過作為貼心的阿粉,我還是給大家準(zhǔn)備了一個工具類,代碼太長,我只貼部分,需要完成代碼的可以到公眾號回復(fù)【源碼倉庫】獲取。

        /**
             *  刪除KEY
             * @param key
             * @return
             */

            public boolean delete(String key) {
                try {
                    return getTemplate().delete(key);
                } catch (Exception e) {
                    log.error("redis hasKey() is error");
                    return false;
                }
            }

            /**
             * 普通緩存獲取
             *
             * @param key 鍵
             * @return 值
             */

            public Object get(String key) {

                return key == null ? null : getTemplate().opsForValue().get(key);
            }

            /**
             * 普通緩存放入
             *
             * @param key   鍵
             * @param value 值
             * @return true成功 false失敗
             */

            public boolean set(String key, Object value) {

                try {
                    getTemplate().opsForValue().set(key, value);
                    return true;
                } catch (Exception e) {
                    log.error("redis set() is error");
                    return false;
                }

            }

            /**
             * 普通緩存放入并設(shè)置時間
             *
             * @param key   鍵
             * @param value 值
             * @param time  時間(秒) time要大于0 如果time小于等于0 將設(shè)置無限期
             * @return true成功 false 失敗
             */

            public boolean set(String key, Object value, long time) {
                try {
                    if (time > 0) {
                        getTemplate().opsForValue().set(key, value, time, TimeUnit.SECONDS);
                    } else {
                        set(key, value);
                    }
                    return true;
                } catch (Exception e) {
                    log.error("redis set() is error");
                    return false;
                }
            }

            /**
             * 計數(shù)器
             *
             * @param key 鍵
             * @return 值
             */

            public Long incr(String key) {

                return getTemplate().opsForValue().increment(key);
            }

            public Long incrBy(String key, long step) {

                return getTemplate().opsForValue().increment(key, step);
            }

            /**
             * HashGet
             *
             * @param key  鍵 不能為null
             * @param item 項 不能為null
             * @return 值
             */

            public Object hget(String key, String item) {

                return getTemplate().opsForHash().get(key, item);
            }

            /**
             * 獲取hashKey對應(yīng)的所有鍵值
             *
             * @param key 鍵
             * @return 對應(yīng)的多個鍵值
             */

            public Map   hmget (String key)  {

                return getTemplate().opsForHash().entries(key);
            }

            /**
             * 獲取hashKey對應(yīng)的批量鍵值
             * @param key
             * @param values
             * @return
             */

            public List hmget(String key, List  values)  {

                return getTemplate().opsForHash().multiGet(key, values);
            }

        上面隨機(jī)列了幾個方法,更多方案等待你的探索。

        總結(jié)

        今天阿粉給大家介紹了一下 SpringBoot 項目如何接入 Redis 集群,需要的朋友可以參考一下,不過阿粉還是要說一下,系統(tǒng)的設(shè)計不能過于冗余,如果短期內(nèi)還能支撐業(yè)務(wù)的發(fā)展,那就暫時不要考慮太復(fù)雜,畢竟系統(tǒng)的架構(gòu)是需要不斷的完善的,不可能剛開始的時候就設(shè)計出一套很完善的系統(tǒng)框架。隨著業(yè)務(wù)的不斷發(fā)展,當(dāng)真正發(fā)現(xiàn)單機(jī)Redis 已經(jīng)無法滿足業(yè)務(wù)需求的時候再接入也不遲!

        瀏覽 46
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            水多多在线成人免费视频 | 国产精品成人免费久久黄AV片 | 做爱视频网址 | 久久久女女女女999久久 | 蜜桃免费视频 | 扒开小舞狂揉难受 | 操女人黄片 | 亚洲va国产va天堂va久久 | 亚洲精品久久久久久久久久久久久 | 亚洲一区二区三区无码在线观看 |