0f68a64829
Deploy Examination / deploy (push) Successful in 10s
Subtopics: - distributed-microservice: 45 questions (分布式微服务架构) - message-queue: 45 questions (消息队列) - k8s-observability: 45 questions (K8s与可观测性) - go-java-concurrency: 45 questions (Go/Java并发模型) - database-advanced: 35 questions (数据库进阶) - ai-engineering: 35 questions (AI工程实践) Question types: single_choice, true_false, fill_blank, short_answer, code_reading
170 lines
23 KiB
JSON
170 lines
23 KiB
JSON
{
|
||
"topic": "database-advanced",
|
||
"type": "short_answer",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-09T00:00:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "sa-001",
|
||
"type": "short_answer",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"mysql",
|
||
"bplus-tree",
|
||
"index",
|
||
"composite-index",
|
||
"covering-index"
|
||
],
|
||
"question": "请解释 InnoDB 中聚簇索引与非聚簇索引的区别,并说明联合索引的最左前缀原则和覆盖索引的含义。针对表 orders(user_id, order_id, amount, status),若需要高效执行以下三种查询,分别应如何设计索引?\n1. SELECT * FROM orders WHERE user_id = 100 AND order_id = 'A001'\n2. SELECT user_id, order_id FROM orders WHERE user_id = 100\n3. SELECT amount FROM orders WHERE order_id = 'A001'",
|
||
"answer": "一、聚簇索引与非聚簇索引的区别:\n聚簇索引:InnoDB 中数据行按主键顺序物理存储,每个 InnoDB 表有且仅有一个聚簇索引。主键即聚簇索引;若无主键,选择第一个唯一非空索引;都没有则生成隐藏的 row_id 作为聚簇索引。叶子节点存储完整行数据。\n非聚簇索引(二级索引):叶子节点存储的是主键值而非完整行数据。通过非聚簇索引查询非索引列时,需要根据主键回表(回表查询),即通过主键再到聚簇索引中查找完整行。\n\n二、最左前缀原则:\n联合索引 (a, b, c) 按从左到右的顺序匹配。查询条件必须从最左列开始才能命中索引。可以跳过中间列吗?不能。例如 (a, b, c) 索引,WHERE a=1 AND c=3 只能用到 a 列,c 列无法使用索引。\n\n三、覆盖索引:\n当查询所需的所有列都包含在某个索引中时,无需回表,称为覆盖索引。EXPLAIN 中 Extra 列显示 Using index 表示使用了覆盖索引。\n\n针对三种查询的索引设计:\n1. WHERE user_id=100 AND order_id='A001':建联合索引 (user_id, order_id),两列均在索引中,可精确定位。\n2. SELECT user_id, order_id WHERE user_id=100:建联合索引 (user_id, order_id),user_id 用于过滤,user_id 和 order_id 均在索引中,构成覆盖索引,无需回表。\n3. SELECT amount WHERE order_id='A001':应单独建 order_id 索引,因为 amount 不在联合索引中(即使有联合索引也无法避免回表取 amount)。如果查询频繁,可考虑建覆盖索引 (order_id, amount) 来避免回表。",
|
||
"keywords": [
|
||
"聚簇索引",
|
||
"非聚簇索引",
|
||
"二级索引",
|
||
"回表",
|
||
"主键",
|
||
"叶子节点",
|
||
"最左前缀",
|
||
"覆盖索引",
|
||
"Using index",
|
||
"联合索引"
|
||
],
|
||
"scoring_rubric": "满分10分:1)正确描述聚簇索引与非聚簇索引的区别(含叶子节点存储内容差异)得3分;2)正确解释最左前缀原则得2分;3)正确解释覆盖索引得2分;4)三道查询的索引设计各1分。缺少回表概念扣1分,缺少覆盖索引与Using index关联扣1分。",
|
||
"explanation": "聚簇索引的核心特征是「数据即索引」——叶子节点直接存储完整行数据,因此一个表只能有一个聚簇索引。非聚簇索引(二级索引)的叶子节点只存主键值,查询非索引列时需要「回表」到聚簇索引再查一次。最左前缀原则是联合索引的匹配规则,本质是 B+ 树从左到右逐列排序的结构决定的。覆盖索引是一种优化手段:如果索引已经包含了查询需要的所有列,就完全不需要回表,大幅减少 I/O。这三者共同构成了 MySQL 索引优化的基础框架。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-002",
|
||
"type": "short_answer",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"explain",
|
||
"slow-query"
|
||
],
|
||
"question": "请解释 MySQL EXPLAIN 执行计划中 type 列和 Extra 列的常见值及其含义。针对以下慢查询,请分析 EXPLAIN 输出并给出优化建议:\n\nSELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id WHERE o.created_at > '2025-01-01' AND u.status = 1 GROUP BY u.name ORDER BY o.total DESC LIMIT 10;\n\n假设 EXPLAIN 输出为:type=ALL, rows=500000, Extra=Using temporary; Using filesort。",
|
||
"answer": "一、type 列常见值(从好到差):\n1. system:表只有一行,系统表,最优。\n2. const:通过主键或唯一索引单行查找,最多匹配一行,如 WHERE id=1。\n3. eq_ref:关联查询中,被驱动表通过主键或唯一索引进行等值匹配,每次关联只匹配一行。\n4. ref:通过普通索引进行等值匹配,可能返回多行。\n5. range:索引范围扫描,如 WHERE id > 10、WHERE id IN (1,2,3)。\n6. index:全索引扫描,遍历整个索引树(不回表)。\n7. ALL:全表扫描,最差,应尽量避免。\n\n二、Extra 列常见值:\n1. Using index:覆盖索引,无需回表,好。\n2. Using where:Server 层进行了额外过滤,不完全在存储引擎层完成。\n3. Using temporary:使用了临时表,常见于 GROUP BY / DISTINCT 等操作,需关注性能。\n4. Using filesort:需要额外排序操作,未利用索引排序,可能是性能瓶颈。\n5. Using join buffer:连接查询中被驱动表无可用索引,使用了 Join Buffer。\n6. Select tables optimized away:优化器直接从索引或统计信息中获取结果,无需扫描表。\n\n三、针对给定查询的优化建议:\n当前 type=ALL 表示全表扫描 orders 表(或 users 表),rows=500000 说明扫描了大量行。Extra 中 Using temporary 和 Using filesort 说明 GROUP BY 和 ORDER BY 都无法利用索引。\n\n优化措施:\n1. 为 orders 表建索引 (created_at, user_id, total)——created_at 用于 WHERE 过滤,user_id 用于 JOIN,total 用于覆盖排序和 SELECT。\n2. 为 users 表建索引 (status, id, name)——status 过滤,id 关联,name 覆盖 GROUP BY。\n3. 如分页不深,可考虑延迟关联优化:先查子查询获取 id 列表,再关联取完整数据。\n4. 使用 SHOW WARNINGS 查看优化器重写后的 SQL,确认查询是否被正确优化。",
|
||
"keywords": [
|
||
"EXPLAIN",
|
||
"type",
|
||
"ALL",
|
||
"const",
|
||
"eq_ref",
|
||
"ref",
|
||
"range",
|
||
"Extra",
|
||
"Using temporary",
|
||
"Using filesort",
|
||
"Using index",
|
||
"慢查询",
|
||
"全表扫描",
|
||
"索引设计"
|
||
],
|
||
"scoring_rubric": "满分10分:1)正确解释 type 列至少4个常见值(含全表扫描ALL)得3分;2)正确解释 Extra 列至少3个常见值(含Using temporary和Using filesort)得3分;3)针对给定查询给出至少2条合理优化建议得2分;4)能正确识别 type=ALL 和 Extra=Using temporary; Using filesort 的问题并关联到具体表得2分。",
|
||
"explanation": "EXPLAIN 是 MySQL 慢查询分析的核心工具。type 列反映了存储引擎查找数据的方式,ALL 是最差的全表扫描,const/eq_ref 是最优的单行查找。Extra 列揭示了额外执行信息:Using temporary 表示需要创建临时表来完成 GROUP BY,Using filesort 表示需要额外的排序操作,这两者在大数据量下是严重的性能隐患。在本例中,type=ALL + Using temporary + Using filesort 组合表明查询完全没有利用到索引,需要通过添加合适的联合索引来同时覆盖过滤、连接和排序需求。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-003",
|
||
"type": "short_answer",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"redis",
|
||
"cluster",
|
||
"slot",
|
||
"consistent-hashing"
|
||
],
|
||
"question": "Redis Cluster 使用 16384 个 slot 对数据进行分片。请回答:\n1. slot 的编号范围和分配方式是什么?\n2. 当客户端发送一个 GET key 命令时,Redis Cluster 如何确定该 key 应该由哪个节点处理?\n3. 在线扩容(增加一个新节点)的完整流程是什么?缩容时需要注意什么?\n4. 如果在扩容过程中,客户端访问了一个正在迁移中的 slot,会发生什么?",
|
||
"answer": "1. Slot 编号与分配:\n编号范围为 0-16383(共 16384 个 slot)。每个 Redis Cluster 节点负责一部分 slot。分配方式由 cluster.conf 中的 cluster-config-file 记录,默认均匀分配。例如 3 节点集群,节点 A 负责 0-5460,节点 B 负责 5461-10922,节点 C 负责 10923-16383。\n\n2. Key 到节点的路由:\n计算公式:slot = CRC16(key) % 16384。CRC16 是循环冗余校验算法。客户端(如 redis-cli)在发送命令前先计算 slot,然后根据集群元数据(slot 到节点的映射关系)将请求发送到对应的 master 节点。如果请求发到了错误节点,该节点会返回 MOVED 重定向响应,客户端更新路由缓存后重发。Redis 3.2+ 还支持 ASK 临时重定向(用于 slot 迁移中)。\n\n3. 在线扩容流程:\na) 启动新节点并加入集群:redis-cli --cluster add-node <new_node> <existing_node>\nb) 分配 slot:redis-cli --cluster reshard <node>,指定要迁移的 slot 数量和目标节点。系统会自动选择源节点。\nc) 迁移过程:对每个要迁移的 slot,源节点执行 MIGRATE 命令将 slot 中的所有 key 迁移到目标节点。迁移期间源节点对迁移中的 key 的写操作会触发 ASK 重定向。\nd) 确认完成:redis-cli --cluster check 验证集群状态。\n\n缩容注意事项:\na) 先将要下线节点的 slot 迁移到其他节点(reshard)。\nb) 确认该节点上的所有 slot 已迁移完毕(cluster nodes 中该节点不再负责任何 slot)。\nc) 删除节点:redis-cli --cluster del-node。\nd) 注意:如果要下线的是 master 节点,需要先处理其 slave 节点(先 del slave,再 del master,或者先将 slave 绑定到其他 master)。\n\n4. 访问迁移中 slot 的行为:\nRedis Cluster 在 slot 迁移过程中支持 ASK 重定向。具体流程:\n- 客户端发送命令到源节点。\n- 源节点发现该 slot 正在迁移到目标节点(IMPORTING 状态),如果 key 还在源节点则正常处理;如果 key 已迁走,返回 ASK 重定向到目标节点。\n- 客户端收到 ASK 后,向目标节点发送 ASKING + 原命令。注意 ASK 是单次重定向,不会更新客户端的 slot 路由缓存(与 MOVED 不同)。\n- 迁移完成后,源节点发送 MOVED,客户端永久更新路由。",
|
||
"keywords": [
|
||
"16384",
|
||
"CRC16",
|
||
"slot",
|
||
"MOVED",
|
||
"ASK",
|
||
"reshard",
|
||
"MIGRATE",
|
||
"cluster",
|
||
"分片",
|
||
"扩容",
|
||
"缩容",
|
||
"重定向"
|
||
],
|
||
"scoring_rubric": "满分10分:1)正确描述 slot 编号范围和 CRC16 路由机制得3分;2)正确解释 MOVED 和 ASK 重定向的区别得2分;3)正确描述扩容完整流程(add-node + reshard + MIGRATE)得3分;4)正确说明缩容注意事项(先迁移 slot 再删除节点)得2分。缺少 CRC16 公式扣1分,混淆 MOVED 和 ASK 扣1分。",
|
||
"explanation": "Redis Cluster 使用哈希槽(hash slot)实现数据分片,是典型的分布式哈希方案。16384 这个数字的选择是权衡了节点数量上限(约 1000 个)和每个节点需要维护的 slot 位图大小(16384/8=2048 字节)后的结果。CRC16%16384 保证了数据在节点间的均匀分布。MOVED 和 ASK 的设计体现了分布式系统中「强一致路由」与「临时过渡路由」的分离,ASK 仅在迁移期间使用且不更新客户端缓存,避免了全局路由信息的不一致。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-004",
|
||
"type": "short_answer",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"mysql",
|
||
"lock",
|
||
"deadlock"
|
||
],
|
||
"question": "请详细解释 MySQL InnoDB 中以下三种锁的区别和应用场景:\n1. 行锁(Record Lock)\n2. 间隙锁(Gap Lock)\n3. 临键锁(Next-Key Lock)\n\n并回答以下问题:\n- 在可重复读(RR)隔离级别下,以下 SQL 会产生什么类型的锁?\n SELECT * FROM accounts WHERE balance BETWEEN 1000 AND 5000 FOR UPDATE;\n (假设 balance 列有索引,值分布为 500, 2000, 8000)\n- 什么是死锁?MySQL 如何检测死锁?如何预防死锁?",
|
||
"answer": "一、三种锁的区别:\n1. 行锁(Record Lock):锁定索引记录本身。只锁住该行,其他事务可以修改同一范围的其他行。是最细粒度的锁。\n\n2. 间隙锁(Gap Lock):锁定索引记录之间的间隙(即两个索引值之间的范围),不锁定记录本身。目的是防止其他事务在间隙中插入新记录,用于解决幻读问题。例如索引值为 5 和 10,则间隙锁可能锁住 (5, 10) 这个范围。\n\n3. 临键锁(Next-Key Lock):行锁 + 间隙锁的组合,锁定一个索引记录及其前面的间隙。即锁定 [gap, record]。InnoDB 在 RR 隔离级别下的默认加锁方式。例如索引值为 5, 10, 15,临键锁可能锁住 (5, 10] 这个区间。\n\n二、针对给定 SQL 的锁分析:\nSELECT * FROM accounts WHERE balance BETWEEN 1000 AND 5000 FOR UPDATE;\n索引值分布为 500, 2000, 8000。\n\n在 RR 隔离级别下:\n- balance 在 1000-5000 范围内的索引值只有 2000,所以会对 balance=2000 这行加行锁。\n- 由于 BETWEEN 1000 AND 5000 的范围,还会在两侧间隙加间隙锁:(500, 1000) 和 (2000, 5000)——实际是左闭右开的区间。\n- 综合起来:临键锁覆盖 (500, 2000] + (2000, 5000),即防止在此范围内插入新值(如 balance=3000 的记录),同时锁住已存在的 2000 这行。\n\n三、死锁相关:\n1. 死锁定义:两个或多个事务互相持有对方需要的锁,形成循环等待,永远无法继续执行。\n\n2. MySQL 检测机制:InnoDB 使用「等待图」(wait-for graph)检测死锁。维护一个事务依赖关系图,如果图中出现环路,则存在死锁。InnoDB 有一个 innodb_deadlock_detect 参数控制是否开启检测(默认开启)。还可以通过 innodb_lock_wait_timeout 设置锁等待超时。\n\n3. 死锁处理:检测到死锁后,InnoDB 选择一个「代价最小」的事务进行回滚(通常是更新最少行的事务),并向该事务返回错误 ERROR 1213 (40001): Deadlock found。\n\n4. 死锁预防措施:\na) 保持事务尽量短小,减少持锁时间。\nb) 事务中的 SQL 按固定顺序访问表和行,避免交叉加锁。\nc) 合理设计索引,使 SQL 能精确锁定需要的行,避免大范围加锁(如使用覆盖索引减少锁范围)。\nd) 在业务允许的情况下降低隔离级别为 READ COMMITTED(RC),RC 下没有间隙锁,大大降低死锁概率。\ne) 使用 SELECT ... FOR UPDATE NOWAIT 或 SKIP LOCKED 避免锁等待。",
|
||
"keywords": [
|
||
"行锁",
|
||
"Record Lock",
|
||
"间隙锁",
|
||
"Gap Lock",
|
||
"临键锁",
|
||
"Next-Key Lock",
|
||
"死锁",
|
||
"等待图",
|
||
"innodb_deadlock_detect",
|
||
"幻读",
|
||
"RR隔离级别",
|
||
"FOR UPDATE"
|
||
],
|
||
"scoring_rubric": "满分10分:1)正确区分三种锁的定义和区别得3分;2)正确分析给定 SQL 产生的锁类型及范围得3分;3)正确解释死锁定义和检测机制得2分;4)给出至少3条有效的死锁预防措施得2分。间隙锁范围分析错误扣1分,未提及 RC 隔离级别降低死锁扣1分。",
|
||
"explanation": "InnoDB 的锁机制围绕解决幻读问题而设计。在 RR 隔离级别下,临键锁(Next-Key Lock)是默认加锁方式,它结合了行锁和间隙锁的优点:既锁住已有记录防止被修改,又锁住间隙防止新记录插入。理解锁的范围对于死锁预防至关重要——很多死锁正是因为事务锁定了过大的范围(如范围查询无精确索引导致锁全表间隙),使两个事务的锁范围产生交叉。降低隔离级别到 RC 是一种激进但有效的策略,因为 RC 下只有行锁没有间隙锁,但代价是可能出现不可重复读。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sa-005",
|
||
"type": "short_answer",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"redis",
|
||
"sentinel",
|
||
"hybrid-persistence",
|
||
"slow-query"
|
||
],
|
||
"question": "请分别回答以下三部分内容:\n\n一、Redis 哨兵(Sentinel)模式:\n1. 哨兵节点之间如何选举 leader?采用什么算法?\n2. 故障转移(failover)的完整流程是什么?\n\n二、Redis 混合持久化(Hybrid Persistence):\n1. RDB 和 AOF 各自的优缺点是什么?\n2. 混合持久化是如何结合 RDB 和 AOF 的?AOF rewrite 的具体流程是什么?\n3. 故障恢复时,混合持久化的恢复流程是怎样的?\n\n三、Redis 内存优化:\n1. 如何排查 Redis 中的大 key 问题?大 key 有哪些危害?\n2. Redis 的内存淘汰策略有哪些?各自适用什么场景?",
|
||
"answer": "一、Redis 哨兵:\n1. Leader 选举采用 Raft 算法:\n- 每个 Sentinel 节点每秒向其他节点发送 PING。\n- 当某个 Sentinel 发现 master 在 down-after-milliseconds 时间内无响应,标记为 SDOWN(主观下线)。\n- 当 quorum(法定人数)个 Sentinel 都标记为 SDOWN 时,master 被标记为 ODOWN(客观下线)。\n- Sentinel 发起 leader 选举:每个 Sentinel 向其他 Sentinel 发送 Sentinel is-master-down-by-addr 命令请求投票。\n- 每个 Sentinel 在一个配置纪元(epoch)中只能投一票,先到先得。\n- 获得 quorum+1 票(即超过半数)的 Sentinel 成为 leader,执行故障转移。\n\n2. 故障转移流程:\na) Leader Sentinel 从 slave 列表中筛选新 master:\n - 排除已下线的、断线时间过长的(超过 down-after-milliseconds * 10)、slave-priority=0 的节点。\n - 优先选择 offset 最大(数据最新)的 slave。\nb) 对选中的 slave 执行 SLAVEOF NO ONE,使其成为 master。\nc) 向其他 slave 发送 SLAVEOF <new_master_ip> <port>,使它们复制新 master。\nd) 更新 sentinel.conf 中的 master 地址,通知客户端新的 master。\n\n二、Redis 混合持久化:\n1. RDB 优缺点:\n优点:文件紧凑,恢复速度快,适合备份和灾难恢复。\n缺点:两次快照之间的数据可能丢失(取决于 RDB 间隔);fork 子进程时可能占用较多内存。\n\nAOF 优缺点:\n优点:数据安全性高(everysec 策略最多丢1秒数据),可读性强。\n缺点:文件体积大,恢复速度慢(需重放所有写命令)。\n\n2. 混合持久化(Redis 4.0+,aof-use-rdb-preamble yes):\n在 AOF rewrite 时,不再是纯命令重放,而是:\na) 先以 RDB 格式将当前全量数据写入 AOF 文件头部(RDB preamble)。\nb) rewrite 期间的增量写命令追加在 RDB 数据之后(AOF 格式)。\nc) 最终 AOF 文件 = RDB 格式的全量数据 + AOF 格式的增量数据。\n\nAOF rewrite 流程:\n1) Redis 创建子进程执行 rewrite(类似 RDB 的 fork)。\n2) 子进程遍历内存数据,生成新的 AOF 文件(混合模式下先写 RDB 格式全量数据,再写增量命令)。\n3) rewrite 期间的写命令同时写入旧 AOF 文件的缓冲区和新 AOF 文件尾部。\n4) 子进程完成后,主进程将缓冲区中的增量数据追加到新 AOF 文件。\n5) 原子替换旧 AOF 文件为新 AOF 文件。\n\n3. 故障恢复流程:\na) 检查是否开启混合持久化(aof-use-rdb-preamble)。\nb) 如果开启:先以 RDB 方式恢复全量数据(快速),然后重放 RDB 之后的 AOF 命令恢复增量数据。\nc) 如果未开启纯 AOF 模式:重放所有 AOF 命令(较慢)。\nd) 如果只有 RDB:直接加载 RDB 文件(最快,但可能丢失最近数据)。\ne) 恢复优先级:AOF > RDB(如果两者都存在)。\n\n三、Redis 内存优化:\n1. 大 key 排查方法:\na) redis-cli --bigkeys:扫描集群,找出每个数据类型中最大的 key。\nb) redis-cli --memkeys:按内存使用量排序。\nc) SCAN + MEMORY USAGE:遍历所有 key,用 MEMORY USAGE 命令逐个检查。\nd) 使用 RDB 工具(如 rdb)离线分析 dump.rdb 文件。\ne) 在 Redis 6.0+ 使用 OBJECT HELP 和 DEBUG 检查。\n\n大 key 危害:\na) 操作延迟高:DEL 大 key 可能阻塞主线程(Redis 4.0+ 已改为异步删除)。\nb) 网络带宽占用:读写大 key 消耗大量网络资源。\nc) 内存不均:在 Cluster 中可能导致某个节点内存远大于其他节点。\nd) 持久化受影响:fork 时大 key 增加写时复制(COW)的内存开销。\ne) 过期删除开销:大 key 过期时可能造成短暂的性能抖动。\n\n2. 内存淘汰策略(8种):\na) noeviction(默认):内存满时拒绝写入,返回错误。适合不允许数据丢失的场景。\nb) allkeys-lru:所有 key 中淘汰最近最少使用的。适合热点数据明显的通用场景。\nc) volatile-lru:只在设置了过期时间的 key 中淘汰 LRU。适合有明确过期策略的缓存。\nd) allkeys-lfu:所有 key 中淘汰最不经常使用的(Redis 4.0+)。适合访问频率差异大的场景。\ne) volatile-lfu:只在有过期时间的 key 中淘汰 LFU。\nf) allkeys-random:所有 key 中随机淘汰。适合各 key 访问概率相近的场景。\ng) volatile-random:只在有过期时间的 key 中随机淘汰。\nh) volatile-ttl:只在有过期时间的 key 中淘汰 TTL 最小(即将过期)的。适合按时效性管理数据。\n\n选择建议:缓存场景首选 allkeys-lru;有明确过期需求用 volatile-lru 或 volatile-ttl;对数据准确性要求高用 noeviction。",
|
||
"keywords": [
|
||
"Sentinel",
|
||
"Raft",
|
||
"leader选举",
|
||
"SDOWN",
|
||
"ODOWN",
|
||
"quorum",
|
||
"failover",
|
||
"混合持久化",
|
||
"RDB",
|
||
"AOF",
|
||
"rewrite",
|
||
"fork",
|
||
"aof-use-rdb-preamble",
|
||
"大key",
|
||
"bigkeys",
|
||
"MEMORY USAGE",
|
||
"noeviction",
|
||
"allkeys-lru",
|
||
"allkeys-lfu",
|
||
"volatile-ttl"
|
||
],
|
||
"scoring_rubric": "满分15分:哨兵部分5分(leader选举算法2分 + 故障转移流程3分);混合持久化部分5分(RDB/AOF优缺点1分 + 混合原理2分 + 恢复流程2分);内存优化部分5分(大key排查2分 + 危害1分 + 淘汰策略2分)。每个部分答出核心要点即可得分,细节不完整酌情扣分。",
|
||
"explanation": "Redis 的高可用方案经历了主从→哨兵→Cluster 的演进。哨兵通过 Raft 算法选举 leader 来协调故障转移,避免了脑裂问题。混合持久化是 Redis 4.0 的重要改进,它结合了 RDB 的快速恢复和 AOF 的数据安全性,通过「RDB头 + AOF尾」的文件格式,使故障恢复既快又全。内存优化方面,大 key 是 Redis 运维中最常见的性能杀手之一,而内存淘汰策略的选择需要根据业务场景的数据重要性、访问模式和时效性来综合判断。这三部分共同构成了 Redis 生产环境运维的核心知识体系。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |