一面
警报怎么做的, 统一接入监控项怎么做
配置中心项目, 实时配置推送怎么做?为什么所有组件依赖放在配置中心中控制
限流功能,怎么做? 做成分布式的,怎么做?
令牌桶维护到 Redis 里,每个实例起一个线程抢锁,抢到锁的负责定时放令牌
怎么抢锁? 怎么释放?
Redis setnx
抢到锁后设置过期时间,线程本身退出时主动释放锁,假如线程卡住了,锁过期那么其它线程可以继续抢占
加了超时之后有没有可能在没有释放的情况下, 被人抢走锁
有可能,单次处理时间过长,锁泄露怎么解决?
换 zk,用心跳解决
不用 zk 的心跳, 可以怎么解决这个问题呢?
每次更新过期时间时,Redis 用 MULTI 做 check-and-set 检查更新时间是否被其他线程修改了,假如被修改了,说明锁已经被抢走,放弃这把锁
假如这个限流希望做成可配置的, 需要有一个后台管理系统随意对某个 api 配置全局流量, 怎么做?
在 Redis 里存储每个 API 的令牌桶 key,假如存在这个 key,则需要按上述逻辑进行限流
二面
拉链法中链表过长时变形为红黑树有什么优缺点?
优点:O(LogN) 的读取速度更快;缺点:插入时有 Overhead,O(LogN) 插入,旋转维护平衡
扩容时, 对读写操作有什么特殊处理?
Java 中 CAS 是怎么实现的?
Compare and Swap,一种乐观锁的实现,可以称为"无锁"(lock-free),CAS 由于要保证原子性无法由 JVM 本身实现,需要调用对应 OS 的指令(这块其实我不了解细节)
假如要查 A in () AND B in (), 怎么建索引?
只给选择性高的一列建索引,两个都是范围查询所以另一个是走不到索引的(这里答的不好,其实也可以建联合索引然后用 (A,B) in ((1,2),(3,4)) 的方式去查)
查询 A in (), MySQL 是针对 N 个值分别查一次索引, 还是有更好的操作?
Redis 的 ZSET 怎么实现的?
跳表
Kafka 的消费者如何做消息去重?
MySQL 去重、Redis 去重、假如场景量极大且允许误判,布隆过滤器也可以
介绍一下 Kafka 的 ConsumerGroup
时序型数据库的存储结构是怎么样的?
讲了 prometheus 1.x 和 2.x 的存储结构
LSM 树了解吗? 是一种什么存储结构?
Log-Structured Merge Tree,牺牲读性能换取性能,RocksDB、HBase、Cassandra 都在用,结构有点忘了,只说了先写 memtable 再刷盘成 sstable
全都热门面试题。即使准备过,多扣细节也看出来真理解还是仅看资料。
三面
热门文章就有几百万的评论, 设计后端服务, 实现评论的时序展示与分页
我: 需不需要支持页码直接跳转?
面试官: 支持和不支持两种场景都考虑一下
我: 不需要支持页码翻页就传评论 id 用 offset 翻页
假如用 id 翻页的方式, 数据库表如何设计? 索引如何设计?
(文章id, 评论id) 建联合索引,评论 id 需递增
假如量很大, 你觉得需要分库分表吗? 怎么分?
需要分,分表有个权衡,按文章 id 分表,读逻辑简单,但写有热点问题;按评论 id 分表,读逻辑复杂,但写压力就平均了。写是要首先保证的,而读总是有缓存等方案来折中,因此按平均 id 分表好。
分库分表后怎么查询分页?
每张表查 N 条数据由 client 或 proxy merge
分库分表后怎么保证主键仍然是递增的?
TDDL :有一张专门用于分配主键的表,每次用乐观锁的方式尝试去取一批主键过来分配,假如乐观锁失败就重试
现在需要支持深分页, 页码直接跳转, 怎么实现?
不能做精准深分页,否则压力太大,找产品进行妥协,在50或100页后数据分页是否可以不完全精确,假如可以,那么缓存深页码的起始评论 id
瞬时写入量很大可能会打挂存储, 怎么保护?
断路器,用 ringbuffer
断路器会造成写入失败, 假如我们不允许写入失败呢?
先写进消息队列,削峰填谷异步落库