java-redis面试题

一、什么是redis?有哪些数据类型?

1.redis介绍

本质上是一个Key-Value类型的内存数据库,单个Value的最大限制是1GB。

其具有内存存储、单线程模式、持久化支持、分布式部署、高性能、高可用等特点。

2.数据类型

String、List、Hash、Set、ZSet(有序集合sorted set,每个元素关联一个分数score,适用于排行榜等)

二、redis提供了哪几种持久化方式

1.RDF
定义:

将Redis的内存中的数据定期保存到磁盘上,以防止数据在Redis进程异常退出或服务器断电等情况下丢失。

优点:

快照文件小、恢复速度快

缺点:

定期更新可能会丢数据

2.AOF
定义:

将Redis的所有写操作追加到AOF文件的未尾,从而记录了Redis服务器运行期间所有修改操作的详细记录。当Redis重新启动时,可以通过AOF文件来恢复数据。(如果redis刚执行了写操作,但还未写入AOF文件就宕机了,那可能导致该操作内容丢失)

优点:

相对RDF而言更可靠、粒度更细

缺点:

文件大、恢复速度较慢、且每次写操作都需要写磁盘导致负载较高

3.混合持久化
定义:

redis4.0之后,推出了RDF-AOF混合版本,AOF 重写时会把 Redis 的持久化数据以 RDB 的格式写入到 AOF 文件的开头,之后的数据再以 AOF 的格式追加的文件的未尾。

优点:

更可靠

缺点:

AOF文件可读性差、版本兼容问题

三、redis为什么快

1.完全基于内存

2.数据结构简单

3.采用单线程,避免了不必要的上下文切换和锁问题

4.使用多路I/O复用模型

5.使用底层模型不同,重构了VM 机制

四、redis为什么采用单线程

1.完全基于内存

2.CPU不是redis的瓶颈,机器内存和网络才是,所以采用单现场,也可以避免上下文切换和锁问题。

五、redis怎么保证原子性的

通过单线程保证原子性

批量操作通过事务保证原子性

多个命令在并发中也是原子性的吗?

不一定,通过事务、Redis+Lua等方式实现

六、redis服务器的内存是多大

可自行设置,默认是(32位 - 3G、64位 - 不受限制),一般推荐设置为最大物理内存的四分之三

七、redis是否支持事务

支持,用于保证批量操作的原子性,用MULTI(事务的开始)和EXEC(事务的结束)命令控制。

redis事务不支持回滚

八、使用redis作为缓存,如何保证redis和mysql数据库的数据一致性

本质就是通过删除缓存 ,来避免因为并发等操作导致缓存和数据库数据不一致的问题,比如线程A更新了数据库数据,但线程B查询到的还是更新前的旧数据 并存储到了 redis。

1.延时双删策略

删除缓存 -> 写入数据库 -> 休眠 X ms -> 删除缓存

延时休眠是为了保证 其他线程的请求 + 主从同步 已经结束

2.设置过期时间
3.兜底方案

延时双删策略仍存在风险 ,比如缓存删除失败等。而过期时间虽然可以兜底,但是可能存在较长时间差,所以最好建立一个兜底方案。

缓存删除失败的话,通过消息队列对相关key再次进行删除。

4.最终方案(延时双删 + 过期时间 + binlog【用于降低业务代码入侵,新启服务订阅binlog】 + 消息队列)

删除缓存 -> 写入数据库 -> 写一个订阅服务,拉取binlog,获取相关信息和key -> 删除缓存 -> 删除时候的话,发送消息队列 -> 再次删除缓存

九、缓存击穿、缓存穿透、缓存雪崩的原因和解决方案

1.缓存击穿
原因:

查询一个不存在的数据,缓存无法命中,将去数据库查询,数据库也查不到,也没有在redis中存入null,这导致不存在的数据每次都要去存储层去查询,如果有人用不存在的数据恶意攻击,可能导致数据库cpu飙升、数据库挂掉等情况。

解决:

1.对空结果也进行缓存计入,value存入null即可

2.使用redisson的布隆过滤器

2.缓存穿透
原因:

对于"热点"数据,当其即将要被大批量并发访问时 失效了,就会导致这些大量的请求打入数据库。

解决:

分布式环境下,使用分布式锁来限制数据库的请求量(redis锁或者zookeeper锁)

3.缓存雪崩
原因:

高并发情况下,大量缓存失效时间重复,导致同一时间大量请求进入数据库,数据库压力过大雪崩

解决:

过期时间在业务接受的时效内采用随机数

十、什么是哨兵模式?工作原理是什么?

1.哨兵模式

Redis 的自动故障转移系统,当 Master异常时进行的Master-Slave切换

2.工作原理

哨兵节点发送ping命令 -> 单节点确认主观下线状态 -> 其他节点核查状态,无误则标记为客观下线状态 -> 选领头哨兵(Raft算法) -> 选新节点并进行切换 -> 旧主恢复后切回

1.哨兵节点(Sentinel)以每秒一次 的频率向所有主从节点发送 PING 命令

2.如果节点在规定时间内(down-after-milliseconds )未回复,哨兵主观认为该节点主管下线

3.当有一个master被标记为主观下线后,监视这个master的所有哨兵节点都以每秒一次的频率进行确认

4.当足够数量的哨兵节点确认成功后,master被标记为客观下线

5.哨兵节点每秒向被客观下线的master的所有slave发送info命令,确认状态信息(一般清苦10秒发送一次info命令)

6.通过Raft算法选出领头哨兵

7.领头哨兵选出新主节点并执行切换

8.旧主节点恢复后切换回来(若没有足够的哨兵节点同意master下线,则移除其客观下线状态、若master重新回复ping命令,则移除其主观下线状态)

十一、如何确保redis里的数据都是"热点"数据【内存淘汰策略】

1.noeviction:不会淘汰任何键值对,而是直接返回错误信息。

2.allkeys-lru:从所有 key 中选择最近最少使用的那个 key 并删除:【redis作为缓存时推荐使用】

3.volatile-lru:从设置了过期时间的 key 中选择最近最少使用的那个 key 并删除。【redis作为半缓存半持久化时推荐使用】

4.allkeys-random:从所有 key 中随机选择一个 key 并删除。

5.volatile-random:从设置了过期时间的 key 中随机选择一个 key 并删除。

6.volatile-ttl:从设置了过期时间的 key 中选择剩余时间最短的 key 并删除。

7.volatile-lfu:淘汰的对象是带有过期时间的键值对中,访问频率最低的那个。

8.allkeys-lfu:淘汰的对象则是所有键值对中,访问频率最低的那个。

十二、redis自带的集群模式有哪些

主从、哨兵、Cluster

十三、redis集群方案有哪些

1.twemproxy

代理方式 ,twemproxy以代理的身份接收请求并使用一致性hash算法,将请求转接到redis,redis再将结果返回给twemproxy。(实际使用只需要修改连接端口即可)

存在【节点数量改变时 数据无法自动转移到新节点】的问题

2.codis【目前最常用】

twemproxy的基础上解决了数据自动转移问题,旧节点数据可恢复到新节点

3.redis cluster3.0自带集群【最新】

不再采用一致性hash,而是hash槽

4.自主实现

自己在业务代码层通过创建redis实例、对key进行hash计算去实现

十四、什么是redis的哈希槽

Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

十五、项目中redis的使用

1.缓存,存储热点数据,减少数据库交互,提高效率

2.分布式锁,比如解决缓存击穿问题

3.消息队列,基于redis的发布-订阅功能

4.放并发

5.限流

6.排行榜

7.计数器

9.会话缓存

10.全页缓存

十六、redis常见的性能问题和解决方案

1.Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

2.如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

3.为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

4.尽量避免在压力很大的主库上增加从库

5.主从复制不要用图状结构,用单向链表结构更为稳定,便于替换,即:Master <- Slave1 <- Slave2 <- Slave3...

相关推荐
猿小羽2 小时前
AI 学习与实战系列:Spring AI + MCP 深度实战——构建标准化、可扩展的智能 Agent 系统
java·spring boot·llm·agent·spring ai·mcp·model context protocol
木井巳2 小时前
【递归算法】快速幂解决 pow(x,n)
java·算法·leetcode·深度优先
程序员_大白2 小时前
区块链部署与运维,零基础入门到精通,收藏这篇就够了
运维·c语言·开发语言·区块链
qq_229058012 小时前
python-Dgango项目收集静态文件、构建前端、安装依赖
开发语言·python
测试人社区—66792 小时前
2025区块链分层防御指南:AI驱动的安全测试实战策略
开发语言·驱动开发·python·appium·pytest
风景的人生2 小时前
mybatis映射时候的注意点
java·mybatis
m0_748248652 小时前
C++使用HTTP库和框架轻松发送HTTP请求
开发语言·c++·http
墨夶2 小时前
Java冷热钱包:不是所有钱包都叫“双保险“!用户资产安全的终极守护者
java·安全·区块链
Yorlen_Zhang3 小时前
Python @property 装饰器详解:优雅控制属性访问的魔法
开发语言·python