缓存

(一) 缓存

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整合实现

缓存

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

    }

}

 

缓存 

上一篇:Java架构师之面试题


下一篇:Less-(26~28) preg_replace3