知乎实在太苦逼了,又亏钱了

360影视 动漫周边 2025-03-29 22:38 2

摘要:知乎是文字平台里内容算很优质的社区了,可往往知乎的用户群体大部分都是互联网上最精明又最鸡贼的人,男性群体偏多,女性群体偏少,想赚钱都难。

图解学习网站:https://xiaolincoding.com

大家好,我是小林。

赚男人的钱太难了,赚精明的人那更是难上加难啊!

知乎是文字平台里内容算很优质的社区了,可往往知乎的用户群体大部分都是互联网上最精明又最鸡贼的人,男性群体偏多,女性群体偏少,想赚钱都难。

再加上短视频等其他平台的冲击,用户流失率也越来越多,所以一直处于亏损的状态,实在太苦逼了。。

这不知乎 2024 财报也出来了,亏损 1.69 亿,营收 36 亿,比去年下降了 14.5%,股价那更是跌到没眼看了。

我在知乎也会创作内容,这几年也积累了有 12w 关注者,但是在知乎平台变现能力很一般,整体的收益和付出的精力,跟用爱发电没什么区别。

不过知乎对创作者还是蛮友好的,知乎有时候会在节假日会送一些礼品给创作者,比如中秋节和春节我都收到过官方寄来的礼物,祝愿知乎能找到新的商业突破口,虽然我知道挺难的,但是还是希望知乎能活的更久一点。

知乎校招后端开发岗位的薪资,我也收集了一波,年薪在 25~33w:

既然聊到知乎,那来聊聊知乎的面试吧。

知乎由于一直处于亏损状态,所以这几年也没怎么大规模招人,所以我翻阅了知乎的面经,发现不少都是前几年的了。

这次来看看知乎后端开发的一面面经,这场面试蛮有意思,80%的内容都在拷打MySQL,而且重点拷打了MySQL binlog、redolog、undolog 三大日志。

所以这场面试还是蛮适合大家一起复习复习 MySQL 日志的内容。

知乎(一面)

MySQL 在完成一条更新操作后,Server 层还会生成一条 binlog,等之后事务提交的时候,会将该事物执行过程中产生的所有 binlog 统一写 入 binlog 文件,binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用。

binlog 是追加写,写满一个文件,就创建一个新的文件继续写,不会覆盖以前的日志,保存的是全量的日志,用于备份恢复、主从复制;

binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。

binlog 有 3 种格式类型,分别是 STATEMENT(默认格式)、ROW、 MIXED,区别如下:

2. mysql里的redo log是什么?

redo log 是物理日志,记录了某个数据页做了什么修改,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新,每当执行一个事务就会产生这样的一条或者多条物理日志。

在事务提交时,只要先将 redo log 持久化到磁盘即可,可以不需要等到将缓存在 Buffer Pool 里的脏页数据持久化到磁盘,当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。

redo log 是 InnoDB 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复。它通过以下方式来保证持久性:

3. 什么时候会删除redo log?

img

4. undo log是什么?

undo log 是一种用于撤销回退的日志,它保证了事务的ACID 特性中的原子性(Atomicity)。

在事务没提交之前,MySQL 会先记录更新前的数据到 undo log 日志文件里面,当事务回滚时,可以利用 undo log 来进行回滚。

每当 InnoDB 引擎对一条记录进行操作(修改、删除、新增)时,要把回滚时需要的信息都记录到 undo log 里,比如:

在发生回滚时,就读取 undo log 里的数据,然后做原先相反操作。比如当 delete 一条记录时,undo log 中会把记录中的内容都记下来,然后执行回滚操作的时候,就读取 undo log 里的数据,然后进行 insert 操作。

5. 什么时候会写入和删除undo log

6. mysql里有哪些索引?介绍一下?

MySQL可以按照四个角度来分类索引。

7. b+树的结构是什么样的?

MySQL InnoDB 引擎是用了B+树作为了索引的数据结构。

B+Tree 是一种多叉树,叶子节点才存放数据,非叶子节点只存放索引,而且每个节点里的数据是按主键顺序存放的。每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息,并且每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。

主键索引的 B+Tree 如图所示:

比如,我们执行了下面这条查询语句:

select * from product where id= 5;

这条语句使用了主键索引查询 id 号为 5 的商品。查询过程是这样的,B+Tree 会自顶向下逐层进行查找:

数据库的索引和数据都是存储在硬盘的,我们可以把读取一个节点当作一次磁盘 I/O 操作。那么上面的整个查询过程一共经历了 3 个节点,也就是进行了 3 次 I/O 操作。

B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。

8. 插入一条数据的流程是什么?

InnoDB 表是 索引组织表,数据按主键顺序存储在 B+树中。插入流程的核心是 维护主键索引的 B+树结构

B+树是分层结构,包含 根节点 → 非叶子节点(中间层)→ 叶子节点,从根节点开始,根据主键值逐层向下查找,直到找到目标叶子节点。

比如,插入主键为

当叶子节点空间不足时,InnoDB 会执行页分裂,确保 B+树的有序性和平衡性。

分裂的过程:

比如,原页存储主键

在 MySQL 里,当使用 InnoDB 存储引擎创建表时,如果表定义了主键,那么 InnoDB 会自动为主键创建聚簇索引。这是因为 InnoDB 以主键作为聚簇索引的键值,数据会按照主键的顺序物理存储在磁盘上。

例如创建一个用户信息表:

CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), age INT);这里的id列作为主键,InnoDB 会自动为其创建聚簇索引,表中的数据会按照id的值进行物理排序存储。

InnoDB 在创建聚簇索引时,会根据不同的场景选择不同的列作为索引:

12. mysql里的hash索引有什么用,mysql哪里使用到了?

IN),原理是通过哈希函数将键值映射到固定长度的哈希值,直接定位数据位置,时间复杂度为 **O(1)**,比 B+树(O(log n))更快,但是Hash 索引无法加速BETWEENORDER BY排序。

mysql 用到 hash 索引的地方:

13. redis和mysql做数据一致性时,如果redis没有正常消费怎么处理?

对于读数据,我会选择旁路缓存策略,如果 cache 不命中,会从 db 加载数据到 cache。对于写数据,我会选择更新 db 后,再删除缓存。

缓存是通过牺牲强一致性来提高性能的。这是由CAP理论决定的。缓存系统适用的场景就是非强一致性的场景,它属于CAP中的AP。所以,如果需要数据库和缓存数据保持强一致,就不适合使用缓存。

所以使用缓存提升性能,就是会有数据更新的延迟。这需要我们在设计时结合业务仔细思考是否适合用缓存。然后缓存一定要设置过期时间,这个时间太短、或者太长都不好:

但是,通过一些方案优化处理,是可以最终一致性的。

针对删除缓存异常的情况,可以使用 2 个方案避免:

我们可以引入消息队列,将第二个操作(删除缓存)要操作的数据加入到消息队列,由消费者来操作数据。

举个例子,来说明重试机制的过程。

重试删除缓存机制还可以,就是会造成好多业务代码入侵

先更新数据库,再删缓存」的策略的第一步是更新数据库,那么更新数据库成功,就会产生一条变更日志,记录在 binlog 里。

于是我们就可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。

Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。

下图是 Canal 的工作原理:

将binlog日志采集发送到MQ队列里面,然后编写一个简单的缓存删除消息者订阅binlog日志,根据更新log删除缓存,并且通过ACK机制确认处理这条更新log,保证数据缓存一致性

14. 平时会用到哪些linux命令

15. linux下存在一个日志文件,格式为id size time,命令行如何统计相同id的总size大小和平均time

可以借助awkid的总size假定日志文件名为log.txt,以下是实现该功能的awk '{ # 累加每个 id 的 size 总和 size_sum[$1]+=$2; # 累加每个 id 的 time 总和 time_sum[$1]+=$3; # 记录每个 id 出现的次数 count[$1]++;}END { for (id in size_sum) { # 计算每个 id 的平均 time avg_time = time_sum[id] / count[id]; # 输出结果 printf "%s %.2f %.2f\n", id, size_sum[id], avg_time; }}' log.txt假设文件内容如下:运行上述这表明。

推荐阅读:

后端训练营,又开卷了!!

中国电信一二面,直接秒了。。

果然,校招的尽头是中小厂。。

来源:肖敏搞笑说一点号

相关推荐