Redis 学习笔记
redis基础认识与使用
redis初步认识
redis是一个非关系型数据库,NoSQL型,采用键值对的形式存储数据,是一种基于内存的高效数据库
既然已经有了mysql,postgresql等数据库,为什么还需要redis
redis基于内存的机制,以及优秀编码,其存取数据比mysql快很多,性能高,可以用于缓存用户数据,合理使用redis可以提升用户体验,极大缓解数据库压力
例如像验证码这类的临时数据,如果每发一次验证码都存入数据库,那么在高并发场景下,数据库的请求压力暴增,不利于用户体验和维护,这种情况下就必须借助redis这样的数据库,高效优雅的缓存处理
redis特点:
- 键值对(key-value)型数据库,value支持多种数据结构,功能强大
- 单线程:单个命令天然具备隔离性,但无法保证原子性事务回滚
- 高性能:基于内存,编码优秀,极致优化
- 无事务(ACID):原子性无法保证,无一致性,隔离性需要通过锁编码控制,可持久化数据但没有sql型数据库便捷
- 支持主从集群, 分片集群等多实例部署
| Atomicity原子性 | 事务提交是不可再分的,要么全部失败回滚,要么全部成功,不存在成功一半的情况 |
|---|---|
| Consistency一致性 | 事务执行前后的状态遵循数据结构定义的约束 |
| Isolation隔离性 | 多个线程并发时,事务具有隔离,通过锁或者多版本控制互斥,互不干扰 |
| Durability持久性 | 事务一旦提交成功,对数据库的修改时永久的,系统崩溃或者断电也不会丢失 |
安装并使用redis
redis服务下载地址:
- 访问redis非官方windows下载
- zip版本7.2带service的123网盘zip版本
redis图形化管理工具resp下载地址:
切换到安装目录下,以管理员身份终端执行以下命令运行和启动redis
1 | # 前台运行并将数据持久化保存到D:\RedisData |
redis或者mysql都可以,用compose可一次性配置多个服务,方便管理
创建docker-compose.yml文件,将以下代码复制进去,并切换到当前文件目录cmd执行 docker compose up -d
1 | # 注意:新版 Docker Compose 已不再需要 version 字段,直接以 services 开头即可 |
执行完毕后如图所示:

最终产生的文件目录:

- mysql-data:mysql的数据将会持久化的保存到这里
- redis-data:如果开启了rdb,或者aof持久化,数据将会保存到这里
redis实战运用
java准备工作
一般来说直接用spring官方分装好的StringRedisTemp,先引入依赖
1 | <!-- Spring Data Redis 依赖(核心) --> |
配置 Redis 连接(application.yml)
1 | spring: |
缓存数据
引入redis后,我们可以让用户查询数据库后把数据缓存到redis,下一次用户再次查询时,就先去redis查询缓存,如果命中缓存直接返回,这样能提高响应速度,降低数据库压力

从这个流程图可以看出几点问题:
- 如果一直都是往redis缓存数据而不删除数据,那么redis内存也会爆满,所以应该合理设置过期时间,redis会自动删除过期数据
- 设置了过期时间,如果每个key的过期时间一致,那么会导致大量数据需要到数据库更新,同样会导致大量请求打到数据库
- 请求数据库不存在的数据,请求会直接打到数据库,并且之后的请求依然会打到数据库
使用redis缓存数据,必须要考虑几个问题
- 缓存穿透:重复请求数据库中不存在的数据,每一次请求直接打到数据库
- 缓存击穿:热点key同时过期,导致大量数据请求更新,数据库高请求过多请求长时间等待,最终资源耗尽
- 缓存雪崩:由于缓存击穿导致的其他服务长时间等待,接连耗尽整体系统资源导致崩溃
缓存雪崩问题解决方案
缓存雪崩是大量的key同时失效,或者redis宕机,导致大量请求直达数据库,造成数据库压力过大
解决方法:
- 给不同的key设置TTL+随机值
- redis多实例部署,集群或者哨兵模式
- 添加降级限流策略
- 添加多级缓存,避免直达数据库
缓存穿透问题
既然缓存穿透是因为一直请求不存在的数据导致直接打到数据库,那么有两种方案,一种是源头上杜绝请求不存在的数据,一种是缓存空值并返回
- 布隆过滤器
- redis缓存空值
redis缓存空值:

布隆过滤器:后续再学习,未完待续…
缓存击穿问题
缓存击穿说的是热点key过期,导致大量更新请求数据库,最终造成数据库压力过大
解决方法:
互斥锁

逻辑过期

| 缓存击穿解决方案 | 优点 | 缺点 |
|---|---|---|
| 互斥锁 | 一致性 简单 内存占用小 | 单线程性能低 进程互相等待 容易发生死锁 |
| 逻辑过期 | 高可用性 进程无等待 性能好 | 数据可能不一致 缓存不过期占用内存大 实现复杂 |