1.7 java面试题:Redis 基本篇

发布时间:2026/6/26 16:06:42
1.7 java面试题:Redis 基本篇 好的我按顺序逐题回答对高频重点配上能直接落地的 Java 代码案例让你面试时既能讲原理又能亮代码。1. 什么是 RedisRedis 是基于内存的高性能键值存储系统C 语言编写单机 QPS 可达 10 万。它不只是缓存更是一个数据结构服务器支持 String、Hash、List、Set、Sorted Set 等丰富类型并提供持久化、主从、集群、事务、Lua 脚本等高级功能。在银行核心系统中我们用它做热点数据缓存、分布式锁、实时排行榜和消息队列。2. Redis 的数据类型String缓存对象、计数器、分布式锁值。Hash存对象如客户信息可部分更新。List消息队列、最新 N 条记录。Set去重、标签、共同好友。Sorted Set排行榜、延迟队列。高级Bitmaps签到、HyperLogLogUV 统计、Geo附近的人、Stream5.0 消息队列。代码示例Hash 存对象 部分更新// 存入客户信息redisTemplate.opsForHash().put(customer:1001,name,张三);redisTemplate.opsForHash().put(customer:1001,balance,50000);// 只更新余额redisTemplate.opsForHash().increment(customer:1001,balance,-1000);3. 使用 Redis 有哪些好处极致性能内存读写微秒级缓解 DB 压力。数据结构丰富天然匹配缓存、队列、排行榜等业务。分布式能力分布式锁、Pub/Sub、Stream 支撑微服务。持久化RDB AOF 保证数据安全。原子操作Lua 脚本打包多个命令避免并发问题。高可用哨兵/集群模式故障转移水平扩展。4. Redis 相比 Memcached 有哪些优势数据结构Memcached 仅 StringRedis 支持多种复杂结构。持久化Redis 支持 RDB/AOFMemcached 不支持重启全丢。高可用Redis 原生支持哨兵、集群Memcached 需客户端一致性哈希。功能丰富Redis 支持事务、Lua 脚本、发布订阅、过期策略等。5. Memcache 与 Redis 的区别都有哪些维度RedisMemcached数据结构丰富仅 String持久化支持不支持线程模型单线程 (命令执行)多线程内存管理多种淘汰策略仅 LRU集群原生支持客户端实现功能事务、Lua、Pub/Sub简单6. Redis 是单进程单线程的命令执行是单线程的但 4.0 后引入多线程处理持久化、异步删除6.0 后支持多线程 I/O网络读写但命令执行依然是单线程。这种设计避免了锁竞争简化了数据一致性。7. 一个字符串类型的值能存储最大容量是多少512MB。但生产中建议单个 value 不超过 10KB大对象应拆分或使用 Hash 存储。8. Redis 的持久化机制是什么各自的优缺点RDB快照定时全量备份。优点恢复快文件小。缺点可能丢最后几分钟数据。AOF追加日志记录每个写命令。优点最多丢 1 秒appendfsync everysec。缺点文件大恢复慢。混合持久化4.0RDB 全量 AOF 增量推荐。银行场景开启 AOFeverysec。9. Redis 常见性能问题和解决方案慢查询用SLOWLOG GET 10分析优化大 key 或复杂命令。热 key加随机前缀打散或本地缓存Caffeine。大 keyredis-cli --bigkeys扫描拆分。内存打满设置合理的maxmemory-policy。RDB fork 阻塞控制实例内存大小避开高峰。10. Redis 过期键的删除策略惰性删除访问 key 时检查是否过期过期则删。定期删除每 100ms 随机抽取一部分 key 检查删除。内存淘汰内存达上限时按maxmemory-policy淘汰。11. Redis 的回收策略淘汰策略?noeviction不淘汰写操作报错适合金融记录。allkeys-lru所有 key 参与 LRU 淘汰推荐缓存场景。volatile-lru仅设置了过期时间的 key 参与。allkeys-random随机淘汰。volatile-ttl优先淘汰剩余 TTL 最短的 key。12. 为什么 Redis 需要把所有数据放到内存中为了达到微秒级延迟必须避免磁盘 I/O。内存读写比磁盘快 1000 倍以上。持久化只是数据安全的补充日常操作完全基于内存。13. Redis 的同步机制了解么主从复制从节点发送PSYNC主节点生成 RDB 快照 增量缓冲区。断线重连后根据replication backlog尝试增量同步否则全量同步。14. Pipeline 有什么好处为什么要用 pipeline将多个命令批量发送减少网络往返RTT。代码示例// 无 pipeline1000 次网络往返for(inti0;i1000;i){redisTemplate.opsForValue().set(key:i,valuei);}// 有 pipeline1 次网络往返redisTemplate.executePipelined(newSessionCallbackObject(){OverridepublicObjectexecute(RedisOperationsoperations){for(inti0;i1000;i){operations.opsForValue().set(key:i,valuei);}returnnull;}});批量导入时性能提升数十倍。15. 是否使用过 Redis 集群集群的原理是什么使用过。Redis Cluster采用虚拟哈希槽CRC16(key) % 16384映射到 16384 个 slot每个节点负责部分 slot。客户端直连节点若 key 不在该节点返回MOVED重定向。每个节点有主从保证高可用。代码示例Spring Boot Lettuce 连接集群spring:redis:cluster:nodes:10.0.1.1:6379,10.0.1.2:6379,10.0.1.3:6379max-redirects:316. Redis 集群方案什么情况下会导致整个集群不可用所有主节点宕机且从节点无法提升为主。slot 不完整某个 slot 所在的主从全部不可用如果配置cluster-require-full-coverage yes默认集群整体停止服务。17. Redis 支持的 Java 客户端都有哪些官方推荐用哪个Jedis同步、直连、简单。Lettuce基于 Netty异步、线程安全官方推荐。Redisson高级封装提供分布式锁、队列、对象等。官方推荐 LettuceSpring Boot 2.x 默认集成。18. Jedis 与 Redisson 对比有什么优缺点Jedis轻量直接操作 Redis 命令性能高但实例非线程安全需连接池。Redisson高层抽象像操作 Java 对象一样使用 Redis提供分布式锁、队列、读写锁等但额外序列化开销略高。银行项目一般用 Lettuce 做底层连接Redisson 做分布式锁。19. Redis 如何设置密码及验证密码服务端redis.confrequirepass your_password客户端连接spring:redis:password:your_password命令验证AUTH your_password20. 说说 Redis 哈希槽的概念Redis Cluster 将数据空间划分为16384 个 slot每个 key 通过CRC16(key) 16383计算 slot每个节点负责一部分 slot。移动 slot 即可实现数据迁移和扩缩容。21. Redis 集群的主从复制模型是怎样的每个主节点可以有多个从节点数据从主异步复制到从。主节点宕机从节点可被选举提升为新主保证可用性。22. Redis 集群会有写操作丢失吗为什么可能会。因为主从复制是异步的如果主节点宕机时数据还未同步到从新主节点将丢失这部分数据。可通过wait命令强制等待同步但会降低性能。银行项目中我们通过业务幂等和最终一致性兜底。23. Redis 集群之间是如何复制的从节点启动时发送PSYNC主节点发送快照和命令流。正常运行期间主节点将写命令异步发送给所有从节点。24. Redis 集群最大节点个数是多少理论上16384 个主节点但官方建议不超过 1000 个节点实际生产中一个集群几十个节点已经很大。25. Redis 集群如何选择数据库集群模式不支持多数据库只有一个 DB0。SELECT命令被禁用。26. 怎么测试 Redis 的连通性使用PING命令返回PONG即连通。StringresultredisTemplate.getConnectionFactory().getConnection().ping();System.out.println(result);// PONG27. 怎么理解 Redis 事务Redis 事务MULTI/EXEC保证命令一次性、顺序执行不会被打断但不保证原子性某条命令执行失败不会回滚其他命令。代码示例WATCH 乐观锁redisTemplate.watch(product:stock:1001);StringstockredisTemplate.opsForValue().get(product:stock:1001);if(Integer.parseInt(stock)0){redisTemplate.multi();redisTemplate.opsForValue().decrement(product:stock:1001);ListObjectresultredisTemplate.exec();if(result.isEmpty()){// 事务被取消重试}}28. Redis 事务相关的命令有哪几个MULTI开启事务EXEC执行事务DISCARD取消事务WATCH监视 key乐观锁UNWATCH取消监视29. Redis key 的过期时间和永久有效分别怎么设置过期时间EXPIRE key 60秒、SETEX key 60 value。永久有效不设置过期时间或PERSIST key移除已有过期时间。30. Redis 如何做内存优化使用短 key。使用压缩列表或紧凑编码默认。使用 Hash 存储对象比 String 存 JSON 节省内存。开启内存淘汰策略及时清理过期 key。对较大值使用 Stream 或分片存储。31. Redis 回收进程如何工作的当内存达到maxmemory时根据maxmemory-policy淘汰 key。淘汰过程阻塞命令执行直到释放出足够内存但通常很快。32. 都有哪些办法可以降低 Redis 的内存使用情况呢设置maxmemory-policy allkeys-lru。使用hash-max-ziplist-entries等参数开启紧凑编码。缩短 key 长度。将大对象拆分为多个小 key。使用volatile-ttl淘汰即将过期的 key。使用连接池减少连接开销。33. Redis 的内存用完了会发生什么如果maxmemory-policy不是noeviction会淘汰 key 释放空间。如果是noeviction所有写入操作返回错误读操作不受影响。34. 一个 Redis 实例最多能存放多少的 keysList、Set、Sorted Set 他们最多能存放多少元素单实例 key 数量上限2^32-1约 42 亿。List、Set、Sorted Set 每个集合内元素数量也是2^32-1。受限于内存大小实际远小于理论值。35. MySQL 里有 2000w 数据redis 中只存 20w 的数据如何保证 redis 中的数据都是热点数据配置maxmemory-policy allkeys-lru内存满时自动淘汰最少使用的数据保留热点数据。配合maxmemory设置合适的内存容量。36. Redis 最适合的场景缓存热点数据减少 DB 压力。分布式锁跨进程互斥。计数器INCR原子自增。排行榜Sorted Set。消息队列List 阻塞弹出、Stream。实时系统发布订阅。37. 假如 Redis 里面有 1 亿个 key其中有 10w 个 key 是以某个固定的已知的前缀开头的如果将它们全部找出来不能用KEYS prefix*会阻塞 Redis。使用SCAN cursor MATCH prefix* COUNT 1000游标迭代每次返回部分 key不阻塞主线程。// Spring 中使用 scanSetStringkeysredisTemplate.execute((RedisCallbackSetString)connection-{SetStringsetnewHashSet();Cursorbyte[]cursorconnection.scan(ScanOptions.scanOptions().match(prefix*).count(1000).build());while(cursor.hasNext()){set.add(newString(cursor.next()));}returnset;});38. 如果有大量的 key 需要设置同一时间过期一般需要注意什么需要避免同一时刻大量 key 同时过期引发缓存雪崩。解决方案在过期时间上加上一个随机值例如 5~15 分钟的随机浮动。39. 使用过 Redis 做异步队列么你是怎么用的使用过。基于List 的阻塞弹出实现// 生产者redisTemplate.opsForList().leftPush(task:queue,task);// 消费者阻塞等待while(true){ObjecttaskredisTemplate.opsForList().rightPop(task:queue,0,TimeUnit.SECONDS);// 处理任务}或使用Redis Stream更可靠支持消费者组// 发送消息MapString,ObjectmsgnewHashMap();msg.put(orderId,1001);redisTemplate.opsForStream().add(order:stream,msg);// 消费ListMapRecordString,Object,ObjectrecordsredisTemplate.opsForStream().read(Consumer.from(group,consumer1),StreamReadOptions.empty().count(1),StreamOffset.create(order:stream,ReadOffset.lastConsumed()));40. 使用过 Redis 分布式锁么它是什么回事使用过。分布式锁是保证多个服务实例在操作共享资源时互斥访问的一种机制。基于 Redis 的SETNX Lua或 Redisson 实现。原理利用 Redis 单线程命令SET key value NX EX 30原子加锁解锁时用 Lua 脚本校验持有者删除避免误删。Redisson 代码案例RLocklockredissonClient.getLock(lock:order:1001);try{if(lock.tryLock(10,30,TimeUnit.SECONDS)){// 处理业务看门狗自动续期}}finally{if(lock.isHeldByCurrentThread()){lock.unlock();}}注意事项锁超时问题要用看门狗或业务幂等兜底主从切换可能丢失锁需用红锁或幂等防线。以上 40 个问题环环相扣既有理论又有可落地的代码足以应对绝大多数 Redis 面试。