缓存

本文涉及的产品
云数据库 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
目录
相关文章
|
3月前
|
缓存
你了解缓存吗?
你了解缓存吗?
你了解缓存吗?
|
10月前
|
存储 缓存 API
缓存 #23
缓存 #23
30 0
|
存储 缓存 前端开发
缓存的认识
缓存是架构设计中一个重要的手段。缓存的主要特点是技术比较简单,同时对性能提升的效果又很显著,所以缓存在很多业务场景中被使用到。
107 0
|
缓存 开发框架 NoSQL
7.4缓存
缓存是一个用来保存数据的区域,从缓存中读取数据要比从数据源读取数据的速度快很多。如果可以从缓存中获取要获取的数据则称之为“缓存命中”,多次请求命中的请求占全部请求的百分比叫做“命中率”,如果数据源中的数据保存到了缓存后,发生了变化则称之为“缓存数据不一致”
|
存储 缓存 NoSQL
聊聊缓存
拿破仑说:胜利属于坚持到最后的人。 而正巧,咱们今天就是要聊一个,关于怎么让系统在狂轰乱炸甚至泰山压顶的情况下,都屹立不倒并坚持到最后的话题:缓存。
141 0
|
存储 缓存 算法
聊聊缓存那些事
说到缓存,作为技术同学想必大家都不会陌生,平常工作中或多或少也用到过。但是要结构化的说清楚缓存到底是什么,怎么用,用了有问题怎么解,也不是一件简单的事。所以这篇文章也是站在服务端研发的视角,对自己过去经验的一些总结,希望对大家有哪怕一丁点的帮助,也就值得了。 本篇文章计划分为两个章节来写: ● 缓存基础篇:讲一下缓存的基本原理、特性等。 ● 缓存进阶篇:讲一下缓存的实战场景,疑难问题的解决方案等。
132 0
|
存储 缓存 运维
常用缓存技巧
在项目中,大家经常会遇到处理高并发的情况,缓存是应对高并发的有效手段之一。这篇文章简单介绍一下常用的缓存手段。
|
存储 缓存 JSON
缓存的注意点
设计缓存的考虑
|
缓存 中间件
你真的懂缓存使用么?
在业务开发中我们经常会使用缓存来减少服务的响应rt,提升服务性能。除了先读缓存-miss后读DB-再写缓存的套路外,其实还有其他很多套路,本文将从使用模式、对数据一致性要求等方面为大家解释其中的细节。一、缓存模式1.1 Cache-aside该模式就是上文中提到的,也是大家用的最多的模式1.业务先读缓存,如果命中直接返回      2如果未命中,业务加载db数据放入缓存,然后返回1.2 Read-
385 0
|
数据库 缓存 存储
如何正确使用缓存?
为了追求高性能,每个开发者最先使用的就是缓存。
2607 0