大數據

緩存

(一) 緩存

1、 內存緩存的利與弊

可以使用google guava cache或則caffie,作為內存緩存性能之王。但是隻能基於內存,不具備分佈式的能力,並且想讓內存緩存失效再外部控制比較難實現。如果需要實現,則通過接口或則其他方式進行內存緩存的失效管理。例如通過MQ等消息中間件,維護開發較難。

2、 分佈式緩存redis

a) 單機

b) 集群模式

(一) Redis 6.X Sentinel 哨兵集群搭建https://mp.weixin.qq.com/s/iy2y135EirDig87NZ-Xeqw

c) 客戶端

(一) 可視化工具AnotherRedisDesktopManager

https://mp.weixin.qq.com/s/_YgvMn1GKCwrJkB9-KQxJg

d) 分佈式鎖 Redission

(一) https://mp.weixin.qq.com/s/CbnPRfvq4m1sqo2uKI6qQw

e) Springboot整合實現

image.png

package com.manlitech.cloudboot.basebootconfig.redis;

 

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import com.fasterxml.jackson.annotation.PropertyAccessor;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.module.SimpleModule;

import com.manlitech.cloudboot.common.enums.ResultEnums;

import com.manlitech.cloudboot.basebootconfig.exception.MyException;

import io.lettuce.core.ReadFrom;

import io.lettuce.core.cluster.ClusterClientOptions;

import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;

import org.joda.time.DateTime;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.autoconfigure.data.redis.RedisProperties;

import org.springframework.cache.annotation.CachingConfigurerSupport;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.connection.RedisClusterConfiguration;

import org.springframework.data.redis.connection.RedisStandaloneConfiguration;

import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;

import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

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;

 

/**

 * redis集群配置

 * @author shensg

 * @date 2019/3/21

 *

 * 增加

 *  @EnableCaching

 *  extends CachingConfigurerSupport

 *  兩處即可實現@Cacheable @CachePut @CacheEvict 使用

 */

@Configuration

public class RedisConfiguration {

 

    @Autowired

    private RedisProperties redisProperties;

 

    @Value("${redis.maxRedirects:3}")

    private int maxRedirects;

 

    @Value("${redis.refreshTime:5}")

    private int refreshTime;

 

    @Bean

    public LettuceConnectionFactory redisConnectionFactory() {

       //單機版

       if(redisProperties.getCluster() == null) {

          RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();

          redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());

          redisStandaloneConfiguration.setHostName(redisProperties.getHost());

          redisStandaloneConfiguration.setPassword(redisProperties.getPassword());

          redisStandaloneConfiguration.setPort(redisProperties.getPort());

          return new LettuceConnectionFactory(redisStandaloneConfiguration);

       }

       //集群版本

       if(redisProperties.getCluster() != null) {

          RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());

          redisClusterConfiguration.setMaxRedirects(maxRedirects);

          //支持自適應集群拓撲刷新和靜態刷新源

            ClusterTopologyRefreshOptions clusterTopologyRefreshOptions =  ClusterTopologyRefreshOptions.builder()

                    .enablePeriodicRefresh()

                    .enableAllAdaptiveRefreshTriggers()

                    .refreshPeriod(Duration.ofSeconds(refreshTime))

                    .build();

            ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()

                    .topologyRefreshOptions(clusterTopologyRefreshOptions).build();

          //從優先,讀寫分離,讀從可能存在不一致,最終一致性CP

            LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()

                    .readFrom(ReadFrom.SLAVE_PREFERRED)

                    .clientOptions(clusterClientOptions).build();

            

            return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);

       }

       throw new MyException(ResultEnums.UNKONW_REDIS_TYPE);

        

    }

 

 

 

    @Bean

    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {

        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);       

        ObjectMapper om = new ObjectMapper();

        

        SimpleModule simpleModule = new SimpleModule();

        simpleModule.addSerializer(DateTime.class,new JodaDateTimeJsonSerializer());

        simpleModule.addDeserializer(DateTime.class,new JodaDateTimeJsonDeserializer());

        om.registerModule(simpleModule);

        om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);

        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(om);

        

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setKeySerializer(new StringRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;

    }

 

}

 

 

package com.manlitech.cloudboot.basebootconfig.redis;

 

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.JsonSerializer;

import com.fasterxml.jackson.databind.SerializerProvider;

import org.joda.time.DateTime;

 

import java.io.IOException;

 

public class JodaDateTimeJsonSerializer extends JsonSerializer<DateTime> {

    @Override

    public void serialize(DateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeString(dateTime.toString("yyyy-MM-dd HH:mm:ss"));

    }

}

 

package com.manlitech.cloudboot.basebootconfig.redis;

 

import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.JsonDeserializer;

import org.joda.time.DateTime;

import org.joda.time.format.DateTimeFormat;

import org.joda.time.format.DateTimeFormatter;

 

import java.io.IOException;

 

public class JodaDateTimeJsonDeserializer extends JsonDeserializer<DateTime> {

    @Override

    public DateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        String dateString =jsonParser.readValueAs(String.class);

        DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

 

        return DateTime.parse(dateString,formatter);

    }

}

 

image.png 

Leave a Reply

Your email address will not be published. Required fields are marked *