61. 在项目中使用Redis

由于Redis的存取效率非常高,在开发实践中,通常会将一些数据从关系型数据库(例如MySQL)中读取出来,并写入到Redis中,后续,当需要访问相关数据时,将优先从Redis中读取所需的数据,以此,可以提高数据的读取效率,并且,对一定程度的保护关系型数据库。

一旦使用Redis后,相关的数据就会同时存在于关系型数据和Redis中,即同一个数据有2份或更多(如果你使用了更多的Redis服务或其它数据处理技术),则可能出现数据不同步的问题!例如,当修改了或删除了关系型数据库中的数据,那Redis中的数据应该如何处理?同时更新?还是无视数据的变化?如果最终出现了关系型数据库和Redis中的数据不同的问题,则称之为“数据一致性问题”。

关于数据可能存在不一致的问题,首先,你必须知道,并不是所有的数据都必须同步,也就是说,当关系型数据库中的数据变化后,如果Redis中的数据没有同步发生变化,则Redis中的数据可以视为是“不准确的”,这个问题在许多应用场景中是可以接受的!例如热门话题的排行榜,或车票的余票数量、商品的库存余量等。

通常,应该Redis的前提应该是:

  • 高频率访问的数据

    • 例如热门榜单
  • 修改频率非常低的数据
    • 例如电商平台中商品的类别
  • 对数据的“准确性”(一致性)要求不高的
    • 例如商品的库存余量

62. 应用Redis

在项目中应用Redis主要需要实现:

  • 将数据从MySQL中读出

    • 已经由Mapper实现
  • 【XX时】向Redis中写入
  • 当需要读取数据时,将原本的从MySQL中读取数据改为从Redis中读取

推荐创建专门用于读写Redis的组件,则在项目的根包下创建repo.IBrandRedisRepository接口:

public interface IBrandRedisRepository {}

并在项目的根包下创建repo.impl.BrandRedisRepositoryImpl类,实现以上接口,并在类上添加@Repository注解:

@Repository
public class BrandRedisRepositoryImpl implements IBrandRedisRepository {}

然后,在IBrandRedisRepository接口中添加抽象方法:

package cn.tedu.csmall.product.repo;import cn.tedu.csmall.product.pojo.vo.BrandListItemVO;
import cn.tedu.csmall.product.pojo.vo.BrandStandardVO;import java.util.List;/*** 处理品牌缓存的数据访问接口** @author java@tedu.cn* @version 0.0.1*/
public interface IBrandRedisRepository {/*** 品牌数据项在Redis中的Key前缀*/String BRAND_ITEM_KEY_PREFIX = "brand:item:";/*** 品牌列表在Redis中的Key*/String BRAND_LIST_KEY = "brand:list";/*** 向Redis中写入品牌数据** @param brandStandardVO 品牌数据*/void save(BrandStandardVO brandStandardVO);/*** 向Redis中写入品牌列表** @param brands 品牌列表*/void save(List<BrandListItemVO> brands);/*** 从Redis中读取品牌数据** @param id 品牌id* @return 匹配的品牌数据,如果没有匹配的数据,则返回null*/BrandStandardVO get(Long id);/*** 从Redis中读取品牌列表** @return 品牌列表*/List<BrandListItemVO> list();/*** 从Redis中读取品牌列表** @param start 读取数据的起始下标* @param end   读取数据的截止下标* @return 品牌列表*/List<BrandListItemVO> list(long start, long end);}

并在BrandRedisRepositoryImpl中实现以上方法:

package cn.tedu.csmall.product.repo.impl;import cn.tedu.csmall.product.pojo.vo.BrandListItemVO;
import cn.tedu.csmall.product.pojo.vo.BrandStandardVO;
import cn.tedu.csmall.product.repo.IBrandRedisRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;/*** 处理品牌缓存的数据访问实现类** @author java@tedu.cn* @version 0.0.1*/
@Slf4j
@Repository
public class BrandRedisRepositoryImpl implements IBrandRedisRepository {@AutowiredRedisTemplate<String, Serializable> redisTemplate;public BrandRedisRepositoryImpl() {log.debug("创建处理缓存的数据访问对象:BrandRedisRepositoryImpl");}@Overridepublic void save(BrandStandardVO brandStandardVO) {log.debug("准备向Redis中写入数据:{}", brandStandardVO);String key = getItemKey(brandStandardVO.getId());redisTemplate.opsForValue().set(key, brandStandardVO);}@Overridepublic void save(List<BrandListItemVO> brands) {String key = getListKey();ListOperations<String, Serializable> ops = redisTemplate.opsForList();for (BrandListItemVO brand : brands) {ops.rightPush(key, brand);}}@Overridepublic BrandStandardVO get(Long id) {String key = getItemKey(id);Serializable serializable = redisTemplate.opsForValue().get(key);if (serializable != null) {if (serializable instanceof BrandStandardVO) {return (BrandStandardVO) serializable;}}return null;}@Overridepublic List<BrandListItemVO> list() {long start = 0;long end = -1;return list(start, end);}@Overridepublic List<BrandListItemVO> list(long start, long end) {String key = getListKey();ListOperations<String, Serializable> ops = redisTemplate.opsForList();List<Serializable> list = ops.range(key, start, end);List<BrandListItemVO> brands = new ArrayList<>();for (Serializable item : list) {brands.add((BrandListItemVO) item);}return brands;}private String getItemKey(Long id) {return BRAND_ITEM_KEY_PREFIX + id;}private String getListKey() {return BRAND_LIST_KEY;}}

完成后,在src/test/java的根包下创建repo.BrandRedisRepositoryTests测试类,编写并执行测试:

package cn.tedu.csmall.product.repo;import cn.tedu.csmall.product.pojo.entity.Brand;
import cn.tedu.csmall.product.pojo.vo.BrandListItemVO;
import cn.tedu.csmall.product.pojo.vo.BrandStandardVO;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.ArrayList;
import java.util.List;@Slf4j
@SpringBootTest
public class BrandRedisRepositoryTests {@AutowiredIBrandRedisRepository repository;@Testvoid testSave() {BrandStandardVO brand = new BrandStandardVO();brand.setId(1L);brand.setName("华为");repository.save(brand);log.debug("向Redis中写入数据完成!");}@Testvoid testSaveList() {List<BrandListItemVO> brands = new ArrayList<>();for (int i = 1; i <= 8; i++) {BrandListItemVO brand = new BrandListItemVO();brand.setId(i + 0L);brand.setName("测试品牌" + i);brands.add(brand);}repository.save(brands);log.debug("向Redis中写入列表数据完成!");}@Testvoid testGet() {Long id = 10000L;Object result = repository.get(id);log.debug("从Redis中读取【id={}】的数据,结果:{}", id, result);}@Testvoid testList() {List<?> list = repository.list();log.debug("从Redis中读取列表,列表中的数据的数量:{}", list.size());for (Object item : list) {log.debug("{}", item);}}@Testvoid testListRange() {long start = 2;long end = 5;List<?> list = repository.list(start, end);log.debug("从Redis中读取列表,列表中的数据的数量:{}", list.size());for (Object item : list) {log.debug("{}", item);}}}

关于在项目中应用Redis,首先考虑何时将MySQL中的数据读取出来并写入到Redis中!常见的策略有:

  • 直接尝试从Redis中读取数据,如果Redis中无此数据,则从MySQL中读取并写入到Redis

    • 从运行机制上,类似单例模式中的懒汉式
  • 当项目启动时,就直接从MySQL中读取数据并写入到Redis
    • 从运行机制上,类似单例模式中的饿汉式
    • 这种做法通常称之为“缓存预热”

当使用缓存预热的处理机制时,需要使得某段代码是项目启动时就自动执行的,可以自定义组件类实现AppliacationRunner接口,重写其中的run()方法,此方法将在项目启动完成之后自动调用。

项目实战(Redis数据库应用)相关推荐

  1. (Windows Maven项目)Redis数据库的安装和操作实现

    Redis是一个内存数据库,他会把你写入其中的数据缓存到内存中,之后会周期性的往磁盘中写入,这篇文章中介绍的是在Windows环境下利用Maven工具编译运行Java文件实现Redis数据库的操作. ...

  2. django项目实战(2)-数据库配置

    2019独角兽企业重金招聘Python工程师标准>>> 项目创建完成后,我们需要配置数据库了,虽然我们在创建项目的时候选择了mysql数据库,但是我们还要安装MySQL_python ...

  3. 微人事项目实战的数据库脚本_EMP微前端实战之cocos2d线上项目

    团队原文: efoxTeam/emp​github.com 一.背景 目前cocos2d游戏最主要的开发方式是通过官方提供的GUI图形界面工具--creator,通过 creator 开发者无需关注构 ...

  4. 微服务springCloud 项目实战 创建数据库表规约及建表语句

    # 创建数据库表规约及建表语句 1.建表规约 **[强制]**表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是tinyint(1) ( 1表示是,0表示否). 说明:任何字段如果为非负 ...

  5. 【Spring Boot 实战】数据库千万级分库分表和读写分离实战

    一. 前言 前几天时间写了如何使用Sharding-JDBC进行分库分表和读写分离的例子,相信能够感受到Sharding-JDBC的强大了,而且使用配置都非常干净.官方支持的功能还很多功能分布式主键. ...

  6. 最新后盾网Laravel框架重入门到实战 Laravel博客项目实战 陈华主讲 包含课件源码

    老师介绍 陈华,PHP明星讲师,大学生演讲网创始人,2010年开始开发整站项目,精通Laravel,Yii框架. 简 介 本套课程是一套以项目实战为主的Laravel5.2实战开发教程,是真正意义上的 ...

  7. STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

    STS创建Spring Boot项目实战(Rest接口.数据库.用户认证.分布式Token JWT.Redis操作.日志和统一异常处理) 1.项目创建 1.新建工程 2.选择打包方式,这边可以选择为打 ...

  8. Flask项目实战——7—(Redis数据库存储验证码信息、验证登录界面的表单信息、注册功能实现、登录实现)

    推荐一个API平台:聚合数据 1.Redis数据库存储验证码信息 保存手机验证码到Redis数据库 公有视图文件:apps/common/views.py # -*- encoding: utf-8 ...

  9. 企业级nosql数据库应用与实战-redis

    企业级nosql数据库应用与实战-redis 项目场景: 随着互联网2.0时代的发展,越来越多的公司更加注重用户体验和互动,这些公司的平台上会出现越来越多方便用户操作和选择的新功能,如优惠券发放.抢红 ...

  10. 【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置(2)

    [.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) 原文:[.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) [.NET Core项目实战- ...

最新文章

  1. 玩转springboot:默认静态资源和自定义静态资源实战
  2. linux如果一个目录具有执行,Linux操作系统部分复习题答案
  3. SQLServer之创建非聚集索引 1
  4. JS根据文本框内容匹配并高亮显示
  5. 网页web前端学习技巧
  6. Spring cloud eureka 入门使用及指导说明(单机篇)
  7. oracle/PL/SQL编程(4)
  8. 第一段冲刺 站立会议 5.5
  9. win2008怎么配置php环境,Win2008 PHP 配置环境搭建 教程_PHP教程
  10. 线上只执行一次的脚本编写注意事项
  11. 正则表达式收集(转)
  12. 高德地图偏移android,关于JS接高德地图API,以及坐标偏移坐标转换(示例代码)
  13. eplan 2.7安装过程中multikey黄色感叹号解决办法
  14. 使用Python绘制淘宝商品评论词云图
  15. 现代控制理论(一)控制系统的状态空间描述
  16. Java 机器学习库Smile实战(一)SVM
  17. 「产品社群」话题讨论精华·第2期
  18. 【色彩管理】HSV色彩模式详解
  19. 如何治理VOCs有机废气的方法——吸附
  20. 静电计算机故障的原因,主板因静电造成的故障现象与解决方法 -电脑资料

热门文章

  1. 汽车线束测试仪怎么保养的
  2. VS2010中VC9.0Runtime与VC10.0Runtime在win7上装不上提示error code 1603
  3. 月薪30k-50k、面试通过率90%,这个职位到底是在做什么?
  4. DASCTF X CBCTF 2022九月挑战赛 appetizer
  5. 亚马逊云科技 Build On 2022 - 参加一场动手实验是怎样一种体验?
  6. python导入标准库的关键字是,导入整个Python标准库
  7. 《医学遗传学(基础医学)》
  8. table如何实现多样表头—前端html
  9. win10改win7后usb键盘鼠标都不能用
  10. 不断拾金——导出为EXCEL