文章目录
- 1. 什么是 Redis?
- 2. Redis 的优缺点
- 3. Redis 与 Memcached 的优势比较
- 4. Redis 支持的数据类型
- 5. Redis 主要消耗的物理资源
- 6. Redis 的数据淘汰策略
- 7. Redis 官方为什么不提供 Windows 版本?
- 8. 一个字符串类型的值能存储最大容量是多少?
- 9. 为什么 Redis 需要把所有数据放到内存中?
- 10. Redis 集群方案应该怎么做?都有哪些方案?
- 11. Redis 集群方案什么情况下会导致整个集群不可用?
- 12. MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?
- 13. Redis 支持的 Java 客户端
- 14. Redis 和 Redisson 的关系
- 15. Jedis 和 Redisson 对比
- 16. Redis 哈希槽的概念
- 17. Redis 集群的主从复制模型
- 18. Redis 集群的写操作丢失情况
- 19. Redis 集群之间的复制方式
- 20. Redis 集群最大节点个数
- 21. Redis 集群如何选择数据库
- 22. Redis 中的管道的作用
- 23. 理解 Redis 事务
- 24. Redis 事务相关命令
- 25. Redis key 的过期时间和永久有效设置方式
- 26. Redis 内存优化
- 27. Redis 回收进程工作原理
- 28. Redis 适合的场景
- 29.Redis 如何实现延时队列
- 30.主从数据库不一致的解决方案
- 28.缓存与数据库不一致的处理方案
- 29.选择缓存时,什么时候选择 redis,什么时候选择 memcached
- 选择 Redis 的情况:
- 选择 Memcached 的情况:
- 30.缓存穿透、缓存击穿、缓存雪崩解决方案?
- 缓存穿透:
- 缓存击穿:
- 缓存雪崩:
1. 什么是 Redis?
Redis(Remote Dictionary Server)是一个内存数据库,类似于 memcached,采用键值对存储数据,但它的数据库全部加载在内存中进行操作,并定期通过异步操作将数据刷新到硬盘上进行持久化保存。Redis以其出色的性能而闻名,每秒可以处理超过 10 万次读写操作,是已知性能最快的键值型数据库之一。除了性能,Redis还支持保存多种数据结构,并且单个 value 的最大限制是 1GB,这使得它可以实现多种有用的功能,比如实现消息队列、高性能的 tag 系统等。
2. Redis 的优缺点
优点:
- 出色的性能,每秒处理超过 10 万次读写操作。
- 支持多种数据结构,如 String、List、Set、Sorted Set、Hashes。
- 单个 value 最大限制为 1GB。
- 支持数据持久化,可以将数据保存到硬盘上。
- 可以设置过期时间,用作缓存。
缺点:
- 数据库容量受物理内存限制,不适合海量数据的高性能读写。
- 内存消耗较大。
- 不支持复杂的查询语句。
3. Redis 与 Memcached 的优势比较
- 数据类型支持:Redis 支持丰富的数据类型,如 String、List、Set、Sorted Set、Hashes,而 Memcached 的值都是简单的字符串。
- 速度:Redis 比 Memcached 快很多。
- 数据持久化:Redis 可以持久化其数据,而 Memcached 不支持持久化。
4. Redis 支持的数据类型
Redis 支持以下数据类型:
- String(字符串)
- List(列表)
- Set(集合)
- Sorted Set(有序集合)
- Hashes(哈希表)
5. Redis 主要消耗的物理资源
Redis 主要消耗内存资源,因为它的数据库全部加载在内存中进行操作。
6. Redis 的数据淘汰策略
Redis 支持以下几种数据淘汰策略:
- noeviction:当内存限制达到时,拒绝执行可能会增加内存使用的命令。
- allkeys-lru:尝试回收最近最少使用的键(LRU),以便新的数据有空间存放。
- volatile-lru:尝试回收最近最少使用的键(LRU),但仅限于过期集合的键,以便新的数据有空间存放。
- allkeys-random:随机回收键,以便新的数据有空间存放。
- volatile-random:随机回收键,但仅限于过期集合的键,以便新的数据有空间存放。
- volatile-ttl:回收在过期集合的键,并优先回收存活时间(TTL)较短的键,以便新的数据有空间存放。
7. Redis 官方为什么不提供 Windows 版本?
Redis 官方不提供 Windows 版本的主要原因是因为目前 Linux 版本已经相当稳定,并且拥有庞大的用户群体,不需要额外开发和维护 Windows 版本。开发和维护 Windows 版本会增加兼容性等问题,而且 Linux 版本已经能够满足大多数用户的需求。
8. 一个字符串类型的值能存储最大容量是多少?
一个字符串类型的值最大容量是 512MB。
9. 为什么 Redis 需要把所有数据放到内存中?
Redis 将数据放到内存中主要是为了达到最快的读写速度,并通过异步的方式将数据写入磁盘以实现持久化。如果不将数据放在内存中,磁盘 I/O 速度将严重影响 Redis 的性能。随着内存价格的不断下降,Redis 在内存中存储数据已成为一种常见且高效的做法。但需要注意的是,如果设置了最大使用的内存,当数据量达到内存限制时就不能继续插入新值。
10. Redis 集群方案应该怎么做?都有哪些方案?
Redis 集群方案有几种不同的实现方式:
- Codis: Codis 是一个比较常见的集群方案,与 Twemproxy 类似,但支持在节点数量改变时进行数据迁移。
- Redis Cluster: Redis 3.0 开始自带的集群方案,采用哈希槽的分布式算法,支持节点设置从节点。
- 业务代码层实现: 通过在业务代码层实现哈希计算,将数据存储在不同的 Redis 实例中。这种方式需要在代码层处理节点失效、数据迁移等问题,对哈希层代码要求较高。
11. Redis 集群方案什么情况下会导致整个集群不可用?
在没有复制模型的情况下,如果集群中某个节点失效,而且数据没有被复制到其他节点,整个集群可能会认为缺少某些哈希槽的数据而变得不可用。这种情况下,需要进行数据迁移或者重新配置集群。
12. MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?
Redis 内存数据集大小上升到一定大小时会施行数据淘汰策略,可以通过合理设置淘汰策略和数据过期时间,以及根据业务需求将热点数据放入 Redis 中,来保证 Redis 中的数据都是热点数据。
13. Redis 支持的 Java 客户端
Redis 支持的 Java 客户端包括 Redisson、Jedis、Lettuce 等,其中官方推荐使用 Redisson。
14. Redis 和 Redisson 的关系
Redisson 是 Redis 的高级分布式协调客户端,帮助用户在分布式环境中轻松实现各种 Java 对象。它是 Redis 的一个 Java 客户端的实现。
15. Jedis 和 Redisson 对比
Jedis:
- 提供了全面的 Redis 命令支持。
- 功能较为丰富,支持字符串操作、排序、事务、管道、分区等 Redis 特性。
Redisson:
- 实现了分布式和可扩展的 Java 数据结构。
- 功能相对简单,不支持字符串操作等,但更专注于分布式环境下的对象操作。
16. Redis 哈希槽的概念
Redis 集群引入了哈希槽的概念,共有 16384 个哈希槽,每个键通过 CRC16 校验后对 16384 取模来决定放置哪个槽。每个节点负责管理一部分哈希槽。
17. Redis 集群的主从复制模型
Redis 集群采用主从复制模型,每个节点都有 N-1 个复制品,确保在部分节点失败或大部分节点无法通信的情况下集群仍然可用。
18. Redis 集群的写操作丢失情况
Redis 无法保证数据的强一致性,因此在特定条件下,集群可能会丢失写操作。
19. Redis 集群之间的复制方式
Redis 集群之间的复制方式为异步复制,即主节点将数据变更发送给从节点,但不等待从节点完成确认。
20. Redis 集群最大节点个数
Redis 集群最大节点个数是 16384 个。
21. Redis 集群如何选择数据库
Redis 集群目前无法选择数据库,默认使用 0 号数据库。
22. Redis 中的管道的作用
Redis 中的管道(pipelining)可以将多个命令一次性发送给服务器,而无需等待每个命令的回复。这样可以大大提高命令的执行效率,尤其在需要频繁通信的场景下,如批量写入或读取操作。
23. 理解 Redis 事务
Redis 事务是一组命令的集合,它们被序列化并按顺序执行。事务中的命令要么全部执行,要么全部不执行,具有原子性。事务在执行期间不会受到其他客户端命令的干扰。
24. Redis 事务相关命令
Redis 事务相关的命令包括:
- MULTI:标记事务的开始。
- EXEC:执行事务中的所有命令。
- DISCARD:取消事务,放弃事务中的所有命令。
- WATCH:监视一个或多个键,如果在事务执行前这些键被其他客户端修改,则事务将被打断。
25. Redis key 的过期时间和永久有效设置方式
- 过期时间:使用 EXPIRE 命令设置键的过期时间,例如
EXPIRE key seconds
。 - 永久有效:使用 PERSIST 命令移除键的过期时间,使其永久有效,例如
PERSIST key
。
26. Redis 内存优化
尽可能使用散列表(hashes)存储数据,将相关信息存储在同一个散列表中,而不是单独设置多个键。这样可以减少内存占用,提高内存利用率。
27. Redis 回收进程工作原理
Redis 回收进程工作方式如下:
- 当一个客户端执行新的命令并添加了新的数据时,Redis 检查内存使用情况。
- 如果内存使用量超过了 maxmemory 的限制,则根据设定好的策略进行回收。
- 在执行新命令的过程中,不断地穿越内存限制的边界,通过回收来保持内存使用在限制范围内。
这样可以确保 Redis 在不断变化的内存使用情况下仍能保持稳定运行。
28. Redis 适合的场景
- 会话缓存(Session Cache):用于缓存会话信息,Redis 提供持久化,确保数据不丢失。
- 全页缓存(FPC):Redis 提供简便的全页缓存平台,可用于加速页面加载速度。
- 队列:利用 Redis 的 list 和 set 操作实现消息队列,适用于各种队列需求。
- 排行榜/计数器:Redis 提供良好的递增/递减操作,适用于实时排行榜等场景。
- 发布/订阅:Redis 的发布/订阅功能适用于社交网络连接、脚本触发器、聊天系统等。
29.Redis 如何实现延时队列
使用 sortedset,使用时间戳做 score, 消息内容作为 key,调用 zadd 来生产消息,消费者使用 zrangbyscore 获取 n 秒之前的数据做轮询处理。
30.主从数据库不一致的解决方案
当主从数据库更新同步存在时差时,可以采取以下解决方案:
-
忽略数据不一致:
- 对于数据一致性要求不高的业务,可以选择忽略主从库数据不一致的情况。
- 这种方案适用于不需要实时一致性的场景,可以接受一定程度的数据延迟。
-
强制读取主库:
- 使用一个高可用的主库,将数据库的读写操作都集中在主库进行。
- 添加一个缓存层,用于提升数据读取的性能。
- 通过强制读取主库,可以避免因为主从同步延迟而导致的数据不一致问题。
-
选择性读取主库:
- 添加一个缓存层,用来记录必须从主库读取的数据。
- 将哪个库、哪个表、哪个主键作为缓存的键。
- 设置缓存的失效时间为主从库同步的时间间隔。
- 当需要读取数据时,首先检查缓存中是否存在该数据,如果缓存中存在,则直接从主库读取;如果缓存中不存在,则从对应的从库中读取。
- 这种方式可以在保证一定的实时性的同时,降低对主库的访问压力,提高系统的整体性能。
28.缓存与数据库不一致的处理方案
在采用主从分离、读写分离的数据库架构中,当缓存与数据库不一致时,可以考虑以下处理方案:
-
问题描述:
- 线程A删除了缓存数据,然后将数据写入主库,但主从同步尚未完成。
- 线程B从缓存中读取数据失败,从从库中读取到旧数据,并更新至缓存,导致缓存中的数据是旧的。
-
处理思路:
- 在从库有数据更新之后,立即更新缓存中的数据,保持数据的一致性。
-
具体实现:
- 当从库发生数据更新时,立即通知缓存更新相应的数据。
- 可以通过在从库上设置触发器或使用消息队列等机制,监听数据更新事件。
- 一旦从库发生数据更新,立即通知缓存进行相应的数据更新操作,保持缓存和数据库的一致性。
- 这样可以避免由于主从同步延迟而导致的缓存数据不一致的问题。
-
综合考虑:
- 综合考虑业务场景和系统性能,可以选择合适的缓存更新策略。
- 如果对数据一致性要求较高,可以采用实时更新缓存的策略;如果可以容忍一定的延迟,可以采用定时或延迟更新缓存的策略。
29.选择缓存时,什么时候选择 redis,什么时候选择 memcached
选择 Redis 的情况:
-
复杂数据结构需求:
- 当需要存储复杂数据结构,如哈希、列表、集合、有序集合等时,选择 Redis 更为合适。因为 Redis 支持丰富的数据结构,而 Memcached 仅支持简单的键值对存储。
-
数据持久化需求:
- 如果需要数据持久化功能,但又不希望将 Redis 作为主要的数据库使用,可以选择 Redis。Redis 提供持久化功能,并能够快速恢复热数据,避免将压力瞬间压在数据库上。
-
高可用需求:
- 当需要高可用性、集群支持、主动复制和读写分离等功能时,Redis 更为适合。Redis 提供了集群支持和主从复制功能,可以实现高可用架构。
-
存储内容较大:
- 如果需要存储的内容较大,超过了 Memcached 的存储限制(最大为1MB),则选择 Redis 更为合适。
选择 Memcached 的情况:
-
纯 KV 存储需求:
- 当仅需简单的键值对存储,并且数据量非常大时,选择 Memcached 更为适合。
-
高吞吐量需求:
- 如果需要处理高吞吐量的业务,由于 Memcached 的内存分配和网络模型优化,可能更适合处理大规模数据请求。
-
多核利用需求:
- Memcached 使用多线程模型,适用于多核利用,尽管可能存在锁冲突,但对于处理大规模数据请求时可能更有效。
-
对 CPU 计算需求不高:
- 如果业务不涉及复杂的 CPU 计算、排序、聚合功能等,Memcached 的网络模型和线程模型可能更适合处理简单的键值对存储请求。
30.缓存穿透、缓存击穿、缓存雪崩解决方案?
缓存穿透:
问题描述: 查询一个一定不存在的数据,导致每次请求都要到数据库查询,可能导致数据库压力过大甚至宕机。
解决方案:
- 查询返回的数据为空时,仍将空结果进行缓存,但设置较短的过期时间。
- 使用布隆过滤器:将可能存在的数据哈希到一个足够大的位图中,一定不存在的数据会被拦截掉,避免对数据库的查询。
缓存击穿:
问题描述: 缓存中的数据在某个时间点同时失效,导致大量请求直接访问数据库,可能导致数据库压力过大甚至宕机。
解决方案:
- 使用互斥锁:缓存失效时先使用互斥锁设置锁,成功后再进行加载数据库的操作,并回设缓存;否则重试获取缓存的操作。
- 永不过期:物理上不设置过期时间,但在逻辑上设置过期时间,后台异步线程负责定时刷新缓存。
缓存雪崩:
问题描述: 大量缓存在同一时刻同时失效,导致大量请求直接访问数据库,可能导致数据库压力过大甚至宕机。
解决方案:
- 将缓存失效时间分散开,可在原有失效时间基础上增加一个随机值,如1-5分钟的随机时间,降低缓存失效的集中度,减少雪崩风险。