天天看點

緩存

(一) 緩存

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-KQ

xJg

d) 分布式鎖 Redission

(一) 

https://mp.weixin.qq.com/s/CbnPRfvq4m1sqo2uKI6qQw

e) Springboot整合實作

緩存

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);

    }

    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;

}

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.JsonSerializer;

import com.fasterxml.jackson.databind.SerializerProvider;

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"));

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.format.DateTimeFormat;

import org.joda.time.format.DateTimeFormatter;

public class JodaDateTimeJsonDeserializer extends JsonDeserializer<DateTime> {

    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);

緩存