Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据)

这篇具有很好参考价值的文章主要介绍了Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、Spring Data Redis

1.1、缓存功能

1.1.1、分析

1.1.2、案例实现

1.1.3、效果演示

1.2、计数功能(Redis + RabbitMQ)

1.2.1、分析

1.2.2、案例实现


一、Spring Data Redis


1.1、缓存功能

1.1.1、分析

使用 redis 作为缓存, MySQL 作为数据库组成的架构

Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据),Redis深度学习,缓存,spring,redis

整体思路:

应用服务器访问数据的时候,先查询 Redis,如果 Redis 上存在该数据,就从 Redis 中取数据直接交给应用服务器,不用继续访问数据库了;如果 Redis 上不存在该数据,就会去 MySQL 中把读到的结构返回给应用服务器,同时,把这个数据也写入到 Redis 中.

由于 Redis 这样的缓存经常用来存储 “热点数据”,也就是高频使用的数据,那什么样的数据算高频呢?这里暗含了一层假设,某个数据一旦被用到了,那么可能在最近这段时间就可能被反复用到.

随着时间推移,越来越多的 key 在 redis 上访问不到,那 redis 的数据不是越来越多么?

  1. 把数据写给 redis 的同时,会给这个 key 设置一个过期时间.
  2. Redis 也有内存不足的时候,因此提供了 淘汰策略(之前的文章展开讲过).

1.1.2、案例实现

例如论坛网站,有些帖子的访问评论很高,就需要设置成热点文章,缓存起来(比起去 MySQL 数据库中查询文章要快的多). 

实现思路:

        根据上面理论,暗含假设当前使用的文章就是热点文章,也就是说,如果在缓存中有该文章,就直接返回,如果没有,就去数据库中查,然后再缓存起来,同时设置 30min(不同场景合理分配) 的过期时间.

帖子实体类.

@Data
public class Article {

    private String title;
    private String content;

}

文章 mapper.

@Mapper
public interface ArticleMapper {

    /**
     * 根据 id 查询文章
     * @param id
     * @return
     */
    Article selectArticleById(@Param("id") Integer id);

}
    <select id="selectArticleById" resultType="com.example.cyk.cache.Article">
        select * from article where id = #{id};
    </select>

帖子 controller

@RestController
@RequestMapping("/article")
public class ArticleController {


    @Autowired
    private IArticleService articleService;

    @GetMapping("/get")
    public HashMap<String, Object> get(@NonNull Integer id) {
        //1.获取文章服务
        Article article = articleService.getArticleInfo(id);
        //2.返回响应
        return HandlerResponse(1000, "操作成功", article);
    }

    /**
     * 处理返回格式
     * @param code
     * @param msg
     * @param data
     * @return
     */
    private HashMap<String, Object> HandlerResponse(Integer code, String msg, Object data) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("msg", msg);
        result.put("data", data);
        return result;
    }

}

帖子 service .

@Slf4j
@Service
public class ArticleService implements IArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Article getArticleInfo(Integer id) {
        //1.非空校验
        if(id == null) {
            log.warn("文章 id 为空");
            throw new RuntimeException("文章 id 为空");
        }
        //2.先去 redis 上看有没有文章对应的这个id
        //我这里约定 redis 上存储格式:
        //key: art:id
        //value: $title$content  ($ 是分隔符)
        //例如 key: art:1    value: $决定$今天要好好学习
        String articleInfo = redisTemplate.opsForValue().get("art:" + id);
        if(articleInfo != null) {
            //存在直接返回
            log.info("从 redis 中获取到文章数据");
            //1) 解析格式
            Article article = analysisArticle(articleInfo);
            //2) 返回数据
            return article;
        }
        //3.redis 上没有数据,因此需要从 mysql 中取
        Article article = articleMapper.selectArticleById(id);
        if(article == null) {
            log.warn("文章不存在");
            throw new RuntimeException("文章不存在!");
        }
        //4.将文章存到 redis 中
        //1) 合成 redis 所需格式的文章
        articleInfo = synthesisArticle(article);
        //2) 设置 5 分钟过期时间(为了演示效果)
        redisTemplate.opsForValue().set("art:" + id, articleInfo, 5, TimeUnit.SECONDS);
        log.info("从 mysql 中获取到文章数据");
        return article;
    }

    /**
     * 合成 redis 需要的格式(提前约定好的)
     * @param article
     * @return
     */
    private String synthesisArticle(Article article) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("$");
        stringBuilder.append(article.getTitle());
        stringBuilder.append("$");
        stringBuilder.append(article.getContent());
        return stringBuilder.toString();
    }

    /**
     * 解析文章格式
     * @param articleInfo
     * @return
     */
    private Article analysisArticle(String articleInfo) {
        Article article = new Article();
        String title = articleInfo.split("\\$")[1];
        String content = articleInfo.split("\\$")[2];
        article.setTitle(title);
        article.setContent(content);
        return article;
    }

}

1.1.3、效果演示

Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据),Redis深度学习,缓存,spring,redis

1.2、计数功能(Redis + RabbitMQ)

1.2.1、分析

许多都会使应用用 Redis 作为计数的基础⼯具,它可以实现快速计数、查询缓存的功能,例如网站视频的播放量,点赞数量......

Ps:这些都是相比较 MySQL 数据库而言的,Redis 可以通过简单的键值对操作完成计数任务并且实在内存中完成的,而 MySQL 就需要先查询数据库,然后 +1,然后再存入数据库,是在需要进行硬盘存储的

Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据),Redis深度学习,缓存,spring,redis

1.2.2、案例实现

实现思路:

        假设,用户点击某个帖子,此时需要进行访问量 + 1 的操作,这时候应用服务器就会直接去操作 Redis ,执行 incr 命令,然后将返回的数据反馈给用户,最后 Redis 会以异步的方式(RabbitMQ 实现异步)将播放量同步到 MySQL 数据库中(异步就表示:这里并不是每一个播放请求,都需要立即写入数据~ 至于什么时候写入,需要根据实际的业务需求场景而定),将数据持久化.

Ps:实际中要开发⼀个成熟、稳定的真实计数系统,要⾯临的挑战远不⽌如此简单:防作弊、按 照不同维度计数、避免单点问题、数据持久化到底层数据源等。

文章实体类

@Data
public class Article implements Serializable {

    private Integer id;
    private String title;
    private String content;
    private Long visits; //访问量

}

rabbit 交换机、队列、绑定配置.

public class MqFinal {

    //处理文章的直接交换机
    public static final String UPDATE_DIRECT = "article.update.direct";
    //用于修改文章数据的队列
    public static final String UPDATE_QUEUE = "article.update.queue";
    //bindingKey
    public static final String UPDATE_KEY = "article.update.key";

}
@Configuration
public class MqConfig {

    /**
     * 消息转化器
     * @return
     */
    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public DirectExchange ArticleDirectExchange() {
        return new DirectExchange(MqFinal.UPDATE_DIRECT, true, false);
    }

    @Bean
    public Queue ArticleUpdateQueue() {
        return new Queue(MqFinal.UPDATE_QUEUE, true);
    }

    @Bean
    public Binding ArticleUpdateBinding() {
        return BindingBuilder.bind(ArticleUpdateQueue()).to(ArticleDirectExchange()).with(MqFinal.UPDATE_KEY);
    }

}

mq 监听配置

@Slf4j
@Component
public class MqListenerArticle {

    @Autowired
    private ArticleMapper articleMapper;

    /**
     * 同步数据库
     */
    @RabbitListener(queues = MqFinal.UPDATE_QUEUE)
    public void syncVisits(HashMap<String, Object> data) {
        Integer id = (Integer) data.get("id");
        // Rabbitmq 这里有一个问题,Map<String, Object> 中 Object 传入为 Long 类型,需要用 Integer 来接受,否则报错
        // 因此发送消息之前,体现将 Long 类型转化为 String,接收到消息之后只需要将 String 转化为 Long 即可
        String visits = (String) data.get("visits");
        articleMapper.updateArticleVisits(id, Long.valueOf(visits));
        log.info("访问量数据同步完成!");
    }

}

访问量增加服务(这里为了可读性,只展示了本业务的核心逻辑)

    @Override
    public Article getArticleInfo(Integer id) {
        //1.非空校验
        if(id == null) {
            log.warn("文章 id 为空");
            throw new RuntimeException("文章 id 为空");
        }

        //2.访问量 +1
        //注意:incr 这个命令执行时,即使 key 不存在,也会自动生成 key,然后自增
        Long visits = redisTemplate.opsForValue().increment("v_art:" + id);
        //3.rabbitmq 实现异步数据同步(发送一个消息即可)
        HashMap<String, Object> visitsInfo = new HashMap<>();
        visitsInfo.put("id", id);
        visitsInfo.put("visits", visits.toString()); //转化原因前面解释过了
        rabbitTemplate.convertAndSend(MqFinal.UPDATE_DIRECT, MqFinal.UPDATE_KEY, visitsInfo);

        //4.获取文章数据
        //业务逻辑(这里为了可读性,就先不展示这里了)......

        //5.放入文章
        Article article = new Article();
        article.setVisits(visits);
        article.setId(id);
        return article;
    }

Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据),Redis深度学习,缓存,spring,redis文章来源地址https://www.toymoban.com/news/detail-744862.html

到了这里,关于Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 8.10 用redis实现缓存功能和Spring Cache

    8.10 用redis实现缓存功能和Spring Cache

    什么是缓存? 缓存(Cache), 就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。 通过Redis来缓存数据,减少数据库查询操作; 逻辑 每个分类的菜品保存一份缓存数据 数据库菜品数据有变更时清理缓存数据 如何将商品数据缓存起来。 控

    2024年02月13日
    浏览(20)
  • redis中List<String>缓存处理

    放入redis 从redis取出

    2024年02月16日
    浏览(9)
  • 整理redis写入string类型的缓存的方法

    第一种存储方式:JSON方法 可以使用Redis的序列化方法将数组转换为字符串,然后将其写入Redis中的String类型缓存。常见的序列化方法有JSON和PHP自带的序列化函数serialize和unserialize。 以下是一个示例代码,将一个数组写入Redis中: 读取缓存时,需要将字符串反序列化为原始的数

    2024年02月07日
    浏览(10)
  • 基于 Docker 的 Spring Boot 项目部署演示,其中使用了 Redis、MySQL 和 RabbitMQ 中间件

    这是一个基于 Docker 的 Spring Boot 项目部署演示,其中使用了 Redis、MySQL 和 RabbitMQ 中间件。 拉取 MySQL 镜像: 创建 MySQL 容器: 将 密码 、 数据库名 、 用户名 和 密码 替换为您自己的值。 拉取 Redis 镜像: 创建 Redis 容器: 拉取 RabbitMQ 镜像: 创建 RabbitMQ 容器: 构建和运行

    2024年02月06日
    浏览(13)
  • Spring Data Redis操作Redis

    Spring Data Redis操作Redis

    在Spring Boot项目中,可以使用Spring Data Redis来简化Redis操作,maven的依赖坐标: 8.3.3、操作Redis的步骤 (1)创建一个Spring Boot工程; (2)在pom.xml文件中导入以上Spring Data Redis的依赖坐标; (3)配置application.yml文件: (4)配置序列化配置类: (5)测试各数据类型的数据 首先在测试类上进行如下修

    2024年02月15日
    浏览(31)
  • 基于spring gateway 的静态资源缓存实现

    由于子项目比较多,子项目都是通过嵌套的方式实现的。就会导致子页面加载比较慢,影响客户体验 实现思路(AI搜的--!): 1、通过spring boot缓存实现静态资源缓存 2、在gateway过滤器,对静态资源进行缓存 直接上代码:

    2024年02月03日
    浏览(8)
  • 解决Spring Data JPA查询存在缓存问题及解决方案

    解决Spring Data JPA查询存在缓存问题及解决方案

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月16日
    浏览(8)
  • Spring Data Redis的使用

    Spring Data Redis的使用

    解决方法为在Redis-x64-3.2.100目录下打开两个cmd窗口,分别输入 命令redis-server.exe redis.windows.conf 和 命令redis-cli ,即可成功连接。   首先在maven的pom文件中引入 Spring Data Redis 模块,代码如下。 然后,在springboot的配置文件中写入redis配置,代码如下。 然后,处理keys的序列化问题

    2024年02月09日
    浏览(12)
  • Spring Data Redis 在Java中操作Redis

    目录 1. 添加依赖   2. 配置连接信息 3. 配置 RedisConnectionFactory 和 RedisTemplate 4.在Java中操作Redis 4.1. String 类型操作 4.2 List 类型操作 4.3 Set 类型操作 4.4 Hash类型操作 4.5 sorted set类型操作     Spring Data Redis 是 Spring Data 项目的一部分,它为 Java 应用程序提供了在 Spring 环境中与

    2024年01月18日
    浏览(10)
  • Spring Data Redis:在Java中操作Redis

    目录 一、Spring Data Redis使用方式 1.1 介绍        1.2 配置  1.3 RedisTemplate 二、环境搭建  2.1 导入Spring Data Redis的maven坐标 2.2 配置Redis数据源   2.3 编写配置类,创建RedisTemplate对象   三、操作常见类型数据 3.1 操作字符串类型数据 3.2 操作哈希类型数据   3.3 操作列表类型

    2024年02月14日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包