缓存

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 缓存
(一) 缓存

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 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
缓存
你了解缓存吗?
你了解缓存吗?
你了解缓存吗?
|
2月前
|
存储 缓存 NoSQL
|
5月前
|
存储 缓存 对象存储
合理地处理不需要的缓存
【6月更文挑战第8天】本文介绍了管理缓存数据过期的重要性,以避免内存浪费和过时信息的使用。缓存系统通常允许设置默认过期策略或为每个对象指定绝对或滑动过期时间。缓存服务常使用LRU策略进行逐出,但过度使用可能导致内存超出异常。
59 10
合理地处理不需要的缓存
|
5月前
|
存储 缓存 NoSQL
在应用中使用缓存服务
【6月更文挑战第24天】本文介绍redis缓存的基本知识和使用。Redis超越简单的键值存储,Redis查询直接针对键,不支持复杂查询,适合特定场景的高性能缓存。用于减少数据库交互,优化性能。并提供练习源码查阅。
89 1
|
存储 缓存 API
缓存 #23
缓存 #23
48 0
|
存储 缓存 NoSQL
聊聊缓存
拿破仑说:胜利属于坚持到最后的人。 而正巧,咱们今天就是要聊一个,关于怎么让系统在狂轰乱炸甚至泰山压顶的情况下,都屹立不倒并坚持到最后的话题:缓存。
179 0
|
存储 缓存 前端开发
缓存的认识
缓存是架构设计中一个重要的手段。缓存的主要特点是技术比较简单,同时对性能提升的效果又很显著,所以缓存在很多业务场景中被使用到。
130 0
|
缓存 开发框架 NoSQL
7.4缓存
缓存是一个用来保存数据的区域,从缓存中读取数据要比从数据源读取数据的速度快很多。如果可以从缓存中获取要获取的数据则称之为“缓存命中”,多次请求命中的请求占全部请求的百分比叫做“命中率”,如果数据源中的数据保存到了缓存后,发生了变化则称之为“缓存数据不一致”
|
存储 缓存 算法
聊聊缓存那些事
说到缓存,作为技术同学想必大家都不会陌生,平常工作中或多或少也用到过。但是要结构化的说清楚缓存到底是什么,怎么用,用了有问题怎么解,也不是一件简单的事。所以这篇文章也是站在服务端研发的视角,对自己过去经验的一些总结,希望对大家有哪怕一丁点的帮助,也就值得了。 本篇文章计划分为两个章节来写: ● 缓存基础篇:讲一下缓存的基本原理、特性等。 ● 缓存进阶篇:讲一下缓存的实战场景,疑难问题的解决方案等。
164 0
|
存储 缓存 运维
常用缓存技巧
在项目中,大家经常会遇到处理高并发的情况,缓存是应对高并发的有效手段之一。这篇文章简单介绍一下常用的缓存手段。