当前位置: 首页 > news >正文

《程序猿之Redis缓存实战(1) · 基础知识》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗

🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

    • 写在前面的话
    • Redis 技术简介
    • Redis 数据结构
    • Redis 客户端工具
    • Key 的专栏
      • Key 定义规范
      • Key 层级结构
    • SpringBoot 整合 Redis
    • 专栏预告
    • 总结陈词

写在前面的话

近期博客正在更新设计模式和微信小程序专栏,工作流引擎LiteFlow也才更新了一集。但由于工作繁忙起来,又忘记推迟更新进度了。

这天,刚好工作中遇到有新人提问Redis相关内容,顺势温习了之前的Redis知识,发现内容还不少,就先插播介绍一下。

荒废不多说,直接先从枯燥的基础部分来介绍。


Redis 技术简介

Redis是一个基于内存的 key-value 键值存储的、可持久化的数据库,并且提供了非常丰富的数据结构,同时还支持非常丰富的功能特性。

Redis官网:https://redis.io/

特征:

  • 键值(Key-Value)型,Value支持多种不同的数据结构,功能丰富
  • 单线程,每个命令具有原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端

Redis 数据结构

Redis是典型的key-value数据库,key一般是字符串,而value包含很多不同的数据类型。

先看一下五大基础数据结构:

● 字符串(Strings): 存储字符串类型的值。
● 哈希表(Hashes): 存储字段和对应值的映射。
● 列表(Lists): 存储有序的字符串列表。
● 集合(Sets): 存储不重复的字符串集合。
● 有序集合(Sorted Sets): 类似集合,但每个元素都关联一个分数,可以按分数排序。

再看看新增的高级数据结构:

  • 位图(Bitmap)
  • 超日志(HyperLogLog)
  • 地理空间(Geospatial)

注意事项:

学习不同的数据结构,除了掌握他们的基础命令外,应该明确各种类型分别运用在什么场景,才是最主要的。


Redis 客户端工具

【使用官方 Redis Insight】

RedisInsight 是一个强大的图形用户界面工具,旨在帮助用户更好地管理和监控 Redis 数据库。它提供了丰富的功能,包括数据浏览、性能监控、查询分析等。如果你在寻找 Redis 的可视化工具,RedisInsight 是一个非常不错的选择。你可以从 Redis 的官方网站下载并安装它。

Redis Insight 是 Redis 官方推荐的客户端工具,功能非常的齐全,不过不支持中文。

【使用第三方工具 Tiny】

强烈推荐大家使用 Tiny RDM,UI 很好看,支持中文和字体设置。

官网地址:https://redis.tinycraft.cc/zh/

下载地址:https://github.com/tiny-craft/tiny-rdm/tree/main


Key 的专栏

Key 定义规范

【背景说明】

在 Spring Boot 项目中,Redis Key 的定义需要遵循一定的规范,以确保代码的可读性、可维护性和可扩展性。

在团队开发中,制定并遵循 Redis key 的命名规范不仅能提高代码的可读性和可维护性,还能减少潜在的错误和冲突。因此,团队应该重视并共同遵循这些规范,以提高整体开发效率和代码质量。

【规范说明】

1、Key 命名规范

  • 使用前缀:为不同的业务模块或功能使用不同的前缀,以避免 key 冲突,例如:user:1001:session。
  • 使用冒号分隔:使用冒号(:)分隔 key 的各个部分,使其结构清晰,例如:app:module:submodule:key。
  • 避免使用特殊字符:尽量避免使用空格、斜杠等特殊字符,以防止在某些情况下出现解析错误。
  • 使用有意义的: Key 的名称应该清晰地描述存储的数据类型和用途,避免使用过于简短或模糊的名称。
  • 使用小写字母: 为了保持一致性,建议使用小写字母命名 Key。

2、Key 的长度

控制 key 的长度:尽量保持 key 的简短,避免过长的 key 影响性能。一般建议不超过 64 个字符。

3、使用常量类

在 Spring Boot 项目中,可以定义一个常量类来集中管理 Redis 的 key。

这样可以避免硬编码,提高代码的可读性和可维护性。

另外,如果项目中有多个模块,建议集中管理 Redis 的 key 定义,避免各个模块之间的 key 冲突。

public class RedisKeys {public static final String USER_SESSION_PREFIX = "user:";public static String getUserSessionKey(Long userId) {return USER_SESSION_PREFIX + userId + ":session";}
}

4、版本控制(可选)

在 key 中加入版本号,以便在需要时进行 key 的迁移或更新。例如:user:v1:1001:session。

5、使用 Hash 数据结构(按需)

使用 Hash:对于相关联的数据,可以使用 Redis 的 Hash 数据结构来存储,减少 key 的数量。

例如,存储用户信息时,可以使用 user:1001 作为 key,用户的各个属性作为 Hash 的字段。

6、设置过期时间(按需)

对于临时数据,设置合理的过期时间,避免 Redis 中存储过多无用数据。

7、监控和清理(可选)

监控使用情况,定期监控 Redis 的 key 使用情况,清理不再使用的 key。

8、文档化(可选)

文档化 key 的用途:为每个 key 的命名和用途编写文档,方便团队成员理解和使用。

9、避免使用用户输入(可选)

避免直接使用用户输入:在生成 key 时,避免直接使用用户输入的内容,以防止注入攻击或意外的 key 冲突。


Key 层级结构

【问题背景】

Redis 没有类似数据库表空间和表的概念,那么我们该如何区分不同业务类型的Key呢?

如果都根据id直接作为Key,那如果用户ID和订单ID重复的话,岂不是乱套了?

答案是,我们可以通过给key添加前缀加以区分,不过这个前缀不是随便加的,有一定的规范。

【层级结构】

  • key允许有多个单词形成层级结构,多个单词之间用:隔开,格式:项目名:业务名:id
  • 以项目名称是portal,业务是user,以此缓存为例,可以是portal:user:001
  • 注意如果业务是通用的,也可以省去项目层级,直接使用user:001
  • 在Redis的客户端工具中,也会以相同前缀作为层次结构,让数据看起来层次分明,关系清晰。

SpringBoot 整合 Redis

【知识介绍】

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

官网地址:https://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

【具体步骤】

Step1、引入依赖

<!-- 整合Redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- JSON处理 -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version>
</dependency>

Step2、添加配置

spring:data:redis:host: 192.168.75.129    # Redis服务器地址port: 6379              # Redis服务器连接端口password: lyd           # Redis服务器连接密码(默认为空)database: 0              # Redis数据库索引(默认为0)# 建议不要采用url的方式# url: redis://192.168.75.129:6379     # Redis服务器的连接URL,在Spring中相当于是password+ip+port,格式为:redis://[password@]host:port[/database]timeout: 60s             # 连接空闲超过N(s秒、ms毫秒,不加单位时使用毫秒)后关闭,0为禁用,这里配置值和tcp-keepalive值一致# Lettuce连接池配置lettuce:pool:max-active: 10       # 允许最大连接数,默认8(负值表示没有限制),推荐值:大于cpu * 2,通常为(cpu * 2) + 2max-idle: 8          # 最大空闲连接数,默认8,推荐值:cpu * 2min-idle: 0          # 最小空闲连接数,默认0max-wait: 5s         # 连接用完时,新的请求等待时间(s秒、ms毫秒),超过该时间抛出异常,默认-1(负值表示没有限制)

Step3、添加自定义RedisTemplate

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// 设置键序列化器为 StringRedisSerializer,所有的键都会被序列化为字符串redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);// 设置值序列化器为 GenericJackson2JsonRedisSerializer,所有的值都会被序列化为 JSON 格式GenericFastJsonRedisSerializer serializer = new GenericFastJsonRedisSerializer();redisTemplate.setValueSerializer(serializer);redisTemplate.setHashValueSerializer(serializer);redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.afterPropertiesSet();return redisTemplate;}
}

Step4、测试效果

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringBaseTest {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void test() {redisTemplate.opsForValue().set("K1", "战神");System.out.println(redisTemplate.opsForValue().get("K1"));System.out.println(stringRedisTemplate.opsForValue().get("K1"));}
}

专栏预告

本篇仅仅是为了知识连贯性,先介绍一篇基础部分的,后续会针对Redis各项专栏进行实战讲解。

包含但不限于:

1、五大基础结构以及三大高级结构;

2、发布订阅模式;

3、流处理模式;

4、延迟队列;

5、分布式锁;

6、各类部署方案;

7、缓存数据库一致性;

8、持久化策略;

9、缓存三大问题;

10、其他专栏,比如序列化、事务等等。。。


总结陈词

本篇算是Redis系列文章的开篇,仅简单介绍了Redis的基础知识。后续会逐个将前面提到的知识领域在实战中的用法,全部展示出来。

💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

相关文章:

  • 有问题未解决(9.28)
  • Redis设计与实现 学习笔记 第一章 引言
  • 机器学习:opencv--特征检测
  • 切换笔记本键盘的启用与禁用状态
  • Java基础(Arrays工具类)(asList()方法)(详细)
  • 鸿蒙开发(NEXT/API 12)【硬件(接入手写套件)】手写功能开发
  • 《深度学习》卷积神经网络 数据增强、保存最优模型 原理解析及实例实现
  • 【自动驾驶】对2D框的四条边同时缩进
  • 【07】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-Swiper轮播组件与样式结构重用
  • Linux下C开发使用小技巧
  • TIM定时中断
  • 17 vue3之tsx手写vite tsx插件
  • 每天学习一个技术栈 ——【Django Channels】篇(1)
  • Kafka与RabbitMQ:深入理解两者之间的区别
  • MySQL基础--表的增删改查
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • android图片蒙层
  • Angular6错误 Service: No provider for Renderer2
  • angular学习第一篇-----环境搭建
  • PhantomJS 安装
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • swift基础之_对象 实例方法 对象方法。
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • vue脚手架vue-cli
  • Vultr 教程目录
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 线性表及其算法(java实现)
  • 最近的计划
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • # 计算机视觉入门
  • #宝哥教你#查看jquery绑定的事件函数
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (10)ATF MMU转换表
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (3)nginx 配置(nginx.conf)
  • (C#)获取字符编码的类
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (leetcode学习)236. 二叉树的最近公共祖先
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (SERIES12)DM性能优化
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (八)Flink Join 连接
  • (二十三)Flask之高频面试点
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (三)终结任务