深入面试题整理(一)

发布于 2022-09-16  31 次阅读


一、redis 双写一致性

分析redis执行原理

读:先读缓存
1)缓存有,就返回
2)缓存没有,就读取数据,更新缓存后再返回
先写数据库,后写缓存
并发,多线程下,可能存在的问题:

(1)状态的覆盖操作,如果不按顺序,redis和mysql结果不一致
(2)数据库更新成功,缓存更新失败,redis和mysql结果不一致
可以在缓存上加过期时间,但这个时间段内,结果还是不一致
先写数据库,后删缓存
并发,多线程下,可能存在的问题:

(1)数据库更新成功,缓存删除失败,redis和mysql结果不一致(读取的依然是老的数据)
先删缓存,后写数据库
并发,多线程下,可能存在的问题:

(1)缓存删除成功,但并发读取,在写数据之前又读取老的数据,并更新到缓存,redis和mysql结果不一致(读取的依然是老的数据)
先写缓存,后写数据库
并发,多线程下,可能存在的问题:

(1)状态的覆盖操作,如果不按顺序,redis和mysql结果不一致
延迟双删(进阶版本)
并发,多线程下,可能存在的问题:

(1)准备更新数据库的时候,缓存里的key已经被淘汰掉了,并发有人访问不到数据,那么就会从数据库读取老的数据,当准备更新到缓存的时候,数据库更新完成,把缓存删除,结果老的数据更新到缓存了,redis和mysql结果不一致(读取的依然是老的数据)

二、并发计算

- 假设有4台服务器构成集群,nginx-php-memcached-mysql
- 每天pv500W

pv : 5000000   # 日均请求
rel : 3               # 每个pv带来的总请求
reqtime : 2       # 请求平均时长
host :   1          # 前端服务器
sec  :86400
fact  :3           # 峰值请求3倍
conn : ?            # 并发数
计算公式:
并发连接数 = PV / 统计时间 * 页面衍生连接次数 * 请求响应时长 *  请求峰值系数  /  web服务器数量
conn =  pv /  sec *  rel  *  reqtime * fact  /  host 
PV = 并发连接数 * 统计时间 * web服务器数量/ 页面衍生连接次数 / 请求响应时长 / 请求峰值系数
pv =  conn  * sec * host / rel / reqtime / facta

三、主从延迟解决

什么是数据库主从延迟

为了完成主从复制,从库需要通过 I/O 线程获取主库中 dump 线程读取的 binlog 内容并写入到自己的中继日志 relay log 中,从库的 SQL 线程再读取中继日志,重做中继日志中的日志,相当于再执行一遍 SQL,更新自己的数据库,以达到数据的一致性。
与数据同步有关的时间点主要包括以下三个:
主库执行完一个事务,写入 binlog,将这个时刻记为 T1;
之后传给从库,将从库接收完这个 binlog 的时刻记为 T2;
从库执行完成这个事务,将这个时刻记为 T3。
所谓主从延迟,就是同一个事务,从库执行完成的时间与主库执行完成的时间之差,也就是 T3 - T1。
可以在备库上执行 show slave status 命令,它的返回结果里面会显示 seconds_behind_master,用于表示当前备库延迟了多少秒。
seconds_behind_master 的计算方法是这样的:
每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;
备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到 seconds_behind_master。
在网络正常的时候,日志从主库传给从库所需的时间是很短的,即 T2 - T1 的值是非常小的。也就是说,网络正常情况下,主从延迟的主要来源是从库接收完 binlog 和执行完这个事务之间的时间差。
由于主从延迟的存在,我们可能会发现,数据刚写入主库,结果却查不到,因为可能还未同步到从库。主从延迟越严重,该问题也愈加明显。

主从延迟的来源

主库和从库在执行同一个事务的时候出现时间差的问题,主要原因包括但不限于以下几种情况:
有些部署条件下,从库所在机器的性能要比主库性能差。
从库的压力较大,即从库承受了大量的请求。
执行大事务。因为主库上必须等事务执行完成才会写入 binlog,再传给备库。如果一个主库上语句执行 10 分钟,那么这个事务可能会导致从库延迟 10 分钟。
从库的并行复制能力。

主从延迟问题解决

配合 semi-sync 半同步复制;
一主多从,分摊从库压力;
强制走主库方案(强一致性);
sleep 方案:主库更新后,读从库之前先 sleep 一下;
判断主备无延迟方案(例如判断 seconds_behind_master 参数是否已经等于 0、对比位点);
并行复制 — 解决从库复制延迟的问题;
这里主要介绍我在项目中使用的几种方案,分别是半同步复制、实时性操作强制走主库、并行复制。

四、es集群容量预估及规划

存储容量评估
影响腾讯云 ES 服务存储容量的主要因素如下:

副本数量:副本有利于增加数据的可靠性,但同时会增加存储成本。默认和建议的副本数量为1,对于部分可以承受异常情况导致数据丢失的场景,可考虑设置副本数量为0。
数据膨胀:除原始数据外,ES 需要存储索引、列存数据等,在应用编码压缩等技术后,一般膨胀10%。
内部任务开销:ES 占用约20%的磁盘空间,用于 segment 合并、ES Translog、日志等。
操作系统预留:Linux 操作系统默认为 root 用户预留5%的磁盘空间,用于关键流程处理、系统恢复、防止磁盘碎片化问题等。
因此,数据在 ES 中占用的实际空间可通过下面公式估算:
实际空间 = 源数据 × (1 + 副本数量) × (1 + 数据膨胀) / (1 - 内部任务开销) / (1 - 操作系统预留)
        ≈ 源数据 × (1 + 副本数量) × 1.45
为保证服务的稳定运行,建议至少预留15%的存储空间,因此建议申请的存储容量为:
存储容量 = 源数据 × (1 + 副本数量) × 1.45 × (1 + 预留空间)
        ≈ 源数据 × (1 + 副本数量) × 1.67
对于内存与存储容量的关系,我们有如下经验比例,一般而言,为保证集群运行的性能和稳定,不建议磁盘存储超过这个比例限制。
对于热数据,我们推荐内存与磁盘的比例为:1:96
对于冷数据,我们推荐内存与磁盘的比例为:1:480