【八股】2023秋招八股复习笔记1(CSBase+部分WXG题)

2023-11-18

MYSQL & redis

redis:memcached/mysql,线程模型(6.0多线程),持久化(AOF,RDB),功能(过期删除,哨兵,集群,主从复制),缓存一致。
mysql:索引(innoDB, B+,索引优化,失效),事务(隔离级别,幻读,可重复读),锁(那些锁),其他(日志,内存池)

mysql基础,索引

  • MySQL 的架构共分为两层:服务层和逻辑索引层。

    Server 层负责建立连接、分析和执行 SQL。查询缓存、解析器、预处理器、优化器、执行器等。

    存储引擎层负责数据的存储和提取。支持 InnoDB、MyISAM、Memory 等多个存储引擎。

    从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎

  • 一条 SQL 查询语句的执行流程

    • 连接器:建立连接,管理连接、校验用户身份;
    • 查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;
    • 解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
    • 执行 SQL:执行 SQL 共有三个阶段:
      • 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
      • 优化阶段:基于查询成本的考虑, 选择查询成本最小的执行计划;
      • 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;
  • B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。

  • 从物理存储的角度来看,索引分为聚簇索引(主键索引)、二级索引(辅助索引)。

    这两个区别在前面也提到了:

    • 主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
    • 二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。

    所以,在查询时使用了二级索引,如果查询的数据能在二级索引里查询的到,那么就不需要回表,这个过程就是覆盖索引。如果查询的数据不在二级索引里,就会先检索二级索引,找到对应的叶子节点,获取到主键值后,然后再检索主键索引,就能查询到数据了,这个过程就是回表

索引最大的好处是提高查询速度,但是索引也是有缺点的,比如:

  • 需要占用物理空间,数量越大,占用空间越大;
  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增大;
  • 会降低表的增删改的效率,因为每次增删改索引,B+ 树为了维护索引有序性,都需要进行动态维护。

什么时候适用索引?

  • 字段有唯一性限制的,比如商品编码
  • 经常用于 WHERE 查询条件的字段,这样能够提高整个表的查询速度,如果查询条件不是一个字段,可以建立联合索引
  • 经常用于 GROUP BYORDER BY 的字段,这样在查询的时候就不需要再去做一次排序了,因为我们都已经知道了建立索引之后在 B+Tree 中的记录都是排序好的。

什么时候不需要创建索引

  • WHERE 条件,GROUP BYORDER BY 里用不到的字段,索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的,因为索引是会占用物理空间的。

  • 表数据太少的时候,不需要创建索引;

  • 经常更新的字段不用创建索引,比如不要对电商项目的用户余额建立索引,因为索引字段频繁修改,由于要维护 B+Tree的有序性,那么就需要频繁的重建索引,这个过程是会影响数据库性能的。

  • 字段中存在大量重复数据,不需要创建索引,比如性别字段,只有男女,如果数据库表中,男女的记录分布均匀,那么无论搜索哪个值都可能得到一半的数据。

    在这些情况下,还不如不要索引,因为 MySQL 还有一个查询优化器,查询优化器发现某个值出现在表的数据行中的百分比很高的时候,它一般会忽略索引,进行全表扫描。

这里说一下几种常见优化索引的方法:

  • 前缀索引优化;

    前缀索引顾名思义就是使用某个字段中字符串的前几个字符建立索引,那我们为什么需要使用前缀来建立索引呢?

    使用前缀索引是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。在一些大字符串的字段作为索引时,使用前缀索引可以帮助我们减小索引项的大小。

    不过,前缀索引有一定的局限性,例如:

    • order by 就无法使用前缀索引;
    • 无法把前缀索引用作覆盖索引;
  • 覆盖索引优化;

    覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。

    假设我们只需要查询商品的名称、价格,有什么方式可以避免回表呢?

    我们可以建立一个联合索引,即「商品ID、名称、价格」作为一个联合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表

    所以,使用覆盖索引的好处就是,不需要查询出包含整行记录的所有信息,也就减少了大量的 I/O 操作。

  • 主键索引最好是自增的;

    我们在建表的时候,都会默认将**主键索引设置为自增的,**具体为什么要这样做呢?又什么好处?

    InnoDB 创建主键索引默认为聚簇索引,数据被存放在了 B+Tree 的叶子节点上。也就是说,同一个叶子节点内的各个数据是按主键顺序存放的,因此,每当有一条新的数据插入时,数据库会根据主键将其插入到对应的叶子节点中。

    如果我们使用自增主键,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有的数据,当页面写满,就会自动开辟一个新页面。因为每次插入一条新记录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。

    如果我们使用非自增主键,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其它数据来满足新数据的插入,甚至需要从一个页面复制数据到另外一个页面,我们通常将这种情况称为页分裂页分裂还有可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率

  • 为了更好的利用索引,索引列要设置为 NOT NULL 约束。有两个原因:

    • 第一原因:索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化,因为可为 NULL 的列会使索引、索引统计和值比较都更复杂,比如进行索引统计时,count 会省略值为NULL 的行。
    • 第二个原因:**NULL 值是一个没意义的值,但是它会占用物理空间,所以会带来的存储空间的问题,**因为 InnoDB 存储记录的时候,如果表中存在允许为 NULL 的字段。
  • 防止索引失效;

    • 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
    • 当我们在查询条件中对索引列做了计算、函数、类型转换操作,这些情况下都会造成索引失效;
    • 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
    • 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
    • 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
    • 当我们在查询条件中对索引列使用函数,就会导致索引失效。
    • 当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
    • MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
    • 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
    • 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
  • 而树的高度决定于磁盘 I/O 操作的次数,因为树是存储在磁盘中的,访问每个节点,都对应一次磁盘 I/O 操作,也就是说树的高度就等于每次查询数据时磁盘 IO 操作的次数,所以树的高度越高,就会影响查询性能。

    B 树和 B+ 都是通过多叉树的方式,会将树的高度变矮,所以这两个数据结构非常适合检索存于磁盘中的数据。但是 MySQL 默认的存储引擎 InnoDB 采用的是 B+ 作为索引的数据结构,原因有:

    • B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树,B+树的非叶子节点可以存放更多的索引,因此 B+ 树可以比 B 树更「矮胖」,查询底层节点的磁盘 I/O次数会更少。
    • B+ 树有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让 **B+ 树在插入、删除的效率都更高,**比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化;
    • B+ 树叶子节点之间用链表连接了起来,有利于范围查询,而 B 树要实现范围查询,因此只能通过树的遍历来完成范围查询,这会涉及多个节点的磁盘 I/O 操作,范围查询效率不如 B+ 树。
  • MySQL 的表数据是以页的形式存放的,页在磁盘中不一定是连续的。

    • 页的空间是 16K, 并不是所有的空间都是用来存放数据的,会有一些固定的信息,如,页头,页尾,页码,校验码等等。
    • 在 B+ 树中,叶子节点和非叶子节点的数据结构是一样的,区别在于,叶子节点存放的是实际的行数据,而非叶子节点存放的是主键和页号。
    • 索引结构不会影响单表最大行数,2000W 也只是推荐值,超过了这个值可能会导致 B + 树层级更高,影响查询性能。
  • count

    count(1)、 count(*)、 count(主键字段)在执行的时候,如果表里存在二级索引,优化器就会选择二级索引进行扫描。

    所以,如果要执行 count(1)、 count(*)、 count(主键字段) 时,尽量在数据表上建立二级索引,这样优化器会自动采用 key_len 最小的二级索引进行扫描,相比于扫描主键索引效率会高一些。

    再来,就是不要使用 count(字段) 来统计记录个数,因为它的效率是最差的,会采用全表扫描的方式来统计。如果你非要统计表中该字段不为 NULL 的记录个数,建议给这个字段建立一个二级索引

mysql事务,锁

  • 并行事务会引发什么问题?

    MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。

    那么在同时处理多个事务的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题

    假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库中读取小林的余额数据,然后再执行更新操作,如果此时事务 A 还没有提交事务,而此时正好事务 B 也从数据库中读取小林的余额数据,那么事务 B 读取到的余额数据是刚才事务 A 更新后的数据,即使没有提交事务。

    假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库中读取小林的余额数据,然后继续执行代码逻辑处理,在这过程中如果事务 B 更新了这条数据,并提交了事务,那么当事务 A 再次读取该数据时,就会发现前后两次读到的数据是不一致的,这种现象就被称为不可重复读。

    假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库查询账户余额大于 100 万的记录,发现共有 5 条,然后事务 B 也按相同的搜索条件也是查询出了 5 条记录。接下来,事务 A 插入了一条余额超过 100 万的账号,并提交了事务,此时数据库超过 100 万余额的账号个数就变为 6。

    然后事务 B 再次查询账户余额大于 100 万的记录,此时查询到的记录数量有 6 条,发现和前一次读到的记录数量不一样了,就感觉发生了幻觉一样,这种现象就被称为幻读。

  • 前面我们提到,当多个事务并发执行时可能会遇到「脏读、不可重复读、幻读」的现象,这些现象会对事务的一致性产生不同程序的影响。

    • 脏读:读到其他事务未提交的数据;
    • 不可重复读:前后读取的数据不一致;
    • 幻读:前后读取的记录数量不一致。
  • SQL 标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能效率就越低,这四个隔离级别如下:

    • 读未提交(*read uncommitted*),指一个事务还没提交时,它做的变更就能被其他事务看到;
    • 读提交(*read committed*),指一个事务提交之后,它做的变更才能被其他事务看到;
    • 可重复读(*repeatable read*),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别
    • 串行化(*serializable* );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;
  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
  • 针对当前读(select … for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
  • 全局锁

    执行后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞:

    • 对数据的增删改操作,比如 insert、delete、update等语句;
    • 对表结构的更改操作,比如 alter table、drop table 等语句。
    • 当然,当会话断开了,全局锁会被自动释放。

    全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

  • 既然备份数据库数据的时候,使用全局锁会影响业务,那有什么其他方式可以避免?

    有的,如果数据库的引擎支持的事务支持可重复读的隔离级别,那么在备份数据库之前先开启事务,会先创建 Read View,然后整个事务执行期间都在用这个 Read View,而且由于 MVCC 的支持,备份期间业务依然可以对数据进行更新操作。

    因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。

MySQL 里面表级别的锁有这几种:

  • 表锁;

  • 元数据锁(MDL);

    再来说说元数据锁(MDL)。

    我们不需要显示的使用 MDL,因为当我们对数据库表进行操作时,会自动给这个表加上 MDL:

    • 对一张表进行 CRUD 操作时,加的是 MDL 读锁
    • 对一张表做结构变更操作的时候,加的是 MDL 写锁

    MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更

    当有线程在执行 select 语句( 加 MDL 读锁)的期间,如果有其他线程要更改该表的结构( 申请 MDL 写锁),那么将会被阻塞,直到执行完 select 语句( 释放 MDL 读锁)。

    反之,当有线程对表结构进行变更( 加 MDL 写锁)的期间,如果有其他线程执行了 CRUD 操作( 申请 MDL 读锁),那么就会被阻塞,直到表结构变更完成( 释放 MDL 写锁)。

    MDL 是在事务提交后才会释放,这意味着事务执行期间,MDL 是一直持有的

  • 意向锁;

    • 在使用 InnoDB 引擎的表里对某些记录加上「共享锁」之前,需要先在表级别加上一个「意向共享锁」;
    • 在使用 InnoDB 引擎的表里对某些纪录加上「独占锁」之前,需要先在表级别加上一个「意向独占锁」;

    也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。

    而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。

    不过,select 也是可以对记录加共享锁和独占锁的,具体方式如下:

    意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(*lock tables … read*)和独占表锁(*lock tables … write*)发生冲突。

    表锁和行锁是满足读读共享、读写互斥、写写互斥的。

    如果没有「意向锁」,那么加「独占表锁」时,就需要遍历表里所有记录,查看是否有记录存在独占锁,这样效率会很慢。

    那么有了「意向锁」,由于在对记录加独占锁前,先会加上表级别的意向独占锁,那么在加「独占表锁」时,直接查该表是否有意向独占锁,如果有就意味着表里已经有记录被加了独占锁,这样就不用去遍历表里的记录。

  • AUTO-INC 锁;

    表里的主键通常都会设置成自增的,这是通过对主键字段声明 AUTO_INCREMENT 属性实现的。

    之后可以在插入数据时,可以不指定主键的值,数据库会自动给主键赋值递增的值,这主要是通过 AUTO-INC 锁实现的。

    AUTO-INC 锁是特殊的表锁机制,锁不是再一个事务提交后才释放,而是再执行完插入语句后就会立即释放

    在插入数据时,会加一个表级别的 AUTO-INC 锁,然后为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等插入语句执行完成后,才会把 AUTO-INC 锁释放掉。

    那么,一个事务在持有 AUTO-INC 锁的过程中,其他事务的如果要向该表插入语句都会被阻塞,从而保证插入数据时,被 AUTO_INCREMENT 修饰的字段的值是连续递增的。

redis

  • 什么是redis

    Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景

    对数据类型的操作都是原子性的,因为执行命令由单线程负责的,不存在并发竞争的问题。

  • Redis 和 Memcached 有什么区别?

    很多人都说用 Redis 作为缓存,但是 Memcached 也是基于内存的数据库,为什么不选择它作为缓存呢?要解答这个问题,我们就要弄清楚 Redis 和 Memcached 的区别。 Redis 与 Memcached 共同点

    • Redis 支持的数据类型更丰富(String、Hash、List、Set、ZSet),而 Memcached 只支持最简单的 key-value 数据类型;
    • Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 没有持久化功能,数据全部存在内存之中,Memcached 重启或者挂掉后,数据就没了;
    • Redis 原生支持集群模式,Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据
    • Redis 支持发布**订阅模型、Lua 脚本、事务等功能,**而 Memcached 不支持;
  • 为什么用 Redis 作为 MySQL 的缓存?

    主要是因为 Redis 具备「高性能」和「高并发」两种特性

    假如用户第一次访问 MySQL 中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据缓存在 Redis 中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了,操作 Redis 缓存就是直接操作内存,所以速度相当快。

    单台设备的 Redis 的 **QPS(Query Per Second,每秒钟处理完请求的次数) 是 MySQL 的 10 倍,**Redis 单机的 QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w。

    所以,**直接访问 Redis 能够承受的请求是远远大于直接访问 MySQL 的,**所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

  • Redis 数据类型以及使用场景分别是什么?

    Redis 提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)

    • String 类型的应用场景:缓存对象、常规计数、分布式锁、共享 session 信息等。
    • List 类型的应用场景:消息队列(但是有两个问题:1. 生产者需要自行实现全局唯一 ID;2. 不能以消费组形式消费数据)等。
    • Hash 类型:缓存对象、购物车等。
    • Set 类型: 聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等。
    • Zset 类型**:排序场景,比如排行榜、电话和姓名排序等**。

    Redis 后续版本又支持四种数据类型,它们的应用场景如下:

    • BitMap(2.2 版新增):二值状态统计的场景,比如签到、判断用户登陆状态、连续签到用户总数等;
    • HyperLogLog(2.8 版新增):海量数据基数统计的场景,比如百万级网页 UV 计数等;
    • GEO(3.2 版新增):存储地理位置信息的场景,比如滴滴叫车
    • Stream(5.0 版新增):消息队列,相比于基于 List 类型实现的消息队列,有这两个特有的特性:自动生成全局唯一消息ID,支持以消费组形式消费数据。

网络 & 系统

网络 = HTTP,TCP,IP

系统 = 内存管理,进程管理,文件管理,IO管理

计算机网络

  • TCP/IP 网络有几层?

    通常是由上到下分成 4 层,分别是应用层,传输层,网络层和网络接口层

  • 键入网址到网页显示,期间发生了什么?

    • 浏览器解析 URL,查看系统缓存路由缓存, 如有存在缓存, 就直接显示。
    • 域名解析(DNS)获取相应的 IP,产生 HTTP 请求信息。
    • 浏览器向服务器发起 tcp 连接, 与浏览器建立 tcp 三次握手。
    • 握手成功, 浏览器向服务器发送 http 请求, 请求数据包。
    • 服务器请求数据, 将数据返回到浏览器。
    • 浏览器接收响应, 读取页面内容, 解析 html 源码, 生成 Dom 树。 解析 css 样式、 浏览器渲染, js交互。
  • TCP 和 UDP 可以使用同一个端口吗?可以的,TCP 和 UDP,在内核中是两个完全独立的软件模块。

操作系统

  • Linux和Win的内核有什么区别?

    Linux 的内核设计是采用了宏内核(包含多个模块,整个内核像一个完整的程序),Window 的内核设计则是采用了混合内核(内核中会有一个小型的内核,其他模块由用户管理,并在基本内核上上搭建完整的内核)。

    可执行文件格式也不一样, Linux 可执行文件格式叫作 ELF,Windows 可执行文件格式叫作 PE。

  • 为什么要由虚拟内存?

    为了在多进程环境下,使得进程之间的内存地址不受影响,相互隔离。

    虚拟地址与物理地址的映射关系可以有分段(栈段、堆段、数据段、代码段等,大小不一导致内存碎片)分页(4kb, 页表过大?=>多级页表+TLB)的2种方式实现,Linux 系统主要采用了分页管理

  • 最后,说下虚拟内存有什么作用?

    • 第一,虚拟内存可以使得进程对运行内存超过物理内存大小,因为程序运行符合局部性原理,CPU 访问内存会有很明显的重复访问的倾向性,对于那些没有被经常使用到的内存,我们可以把它换出到物理内存之外,比如硬盘上的 swap 区域。
    • 第二,由于每个进程都有自己的页表,所以每个进程的虚拟内存空间就是相互独立的。进程也没有办法访问其他进程的页表,所以这些页表是私有的,这就解决了多进程之间地址冲突的问题
    • 第三,页表里的页表项中除了物理地址之外,还有一些标记属性的比特,比如控制一个页的读写权限,标记该页是否存在等。在内存访问方面,操作系统提供了更好的安全性
  • 如何避免死锁?

    简单来说,死锁问题的产生是由两个或者以上线程并行执行的时候,争夺资源而互相等待造成的。

    死锁只有同时满足互斥、持有并等待、不可剥夺、环路等待这四个条件的时候才会发生。

    所以要避免死锁问题,就是要破坏其中一个条件即可,最常用的方法就是使用资源有序分配法来破坏环路等待条件。

  • 什么是悲观锁、乐观锁?

    • 另外,互斥锁、自旋锁、读写锁都属于悲观锁,悲观锁认为并发访问共享资源时,冲突概率可能非常高,所以在访问共享资源前,都需要先加锁。

    • 相反的,如果并发访问共享资源时,冲突概率非常低的话,就可以使用乐观锁,它的工作方式是,在访问共享资源时,不用先加锁,修改完共享资源后,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作。

安全 & C++

  • 说一说常用的 Linux 命令
    cd, ls, grep, cp, rm, ps,kill,cat,tar,top,pwd

  • 静态库和动态库如何制作及使用,区别是什么
    静态库在进行编译和链接时,会把静态库代码打包到可执行程序中,在编译时加载
    动态库不会,而是在运行时加载。通常发布程序需提供动态库,内存占用小,更新部署发布简单

  • 简述一下 GDB 常见的调试命令
    b某行打断点 r运行程序,断点停 c继续执行 p打印指定值 n单步运行 q终止调试

  • 说一说进程调度算法有哪些
    先来先服务算法,短作业优先算法,高响应比优先算法,时间片调度算法,优先级调度算法,多级反馈队列调度算法

八股参考资料1
其他参考资料见牛客

招聘要求(x3)

  • 要求1:
软件开发-全栈开发方向

必须具备的: 
熟练掌握React/vue等前端技术; 
熟悉java/c++/python/go等主流编程语言,接触过相应的框架并有一定的理解; 
能熟练使用MySQL/MongoDB等数据库; 
有较强的学习能力、分析及解决问题能力,具备良好的团队合作意识,心态好,有责任心。 

可以加分的: 
有jQuery、node.js等js框架使用及扩展编写经验者优先; 
了解redis/memcache等缓存中间件者优先; 
有性能优化方面的经验者优先。

要求2:

软件开发-后台开发方向

必须具备的: 
扎实的编程能力; 
熟练掌握C/C++/Java/Go等其中一门开发语言; 
TCP/UDP网络协议及相关编程、进程间通讯编程; 
专业软件知识,包括算法、操作系统、软件工程、设计模式、数据结构、数据库系统、网络安全等。 

有一定了解的: 
Python、Shell、Perl等脚本语言; 
MySQL及SQL语言、编程; 
NoSQL, Key-value存储原理。 

可以加分的: 
分布式系统设计与开发、负载均衡技术,系统容灾设计,高可用系统等知识;
对云原生相关技术有所有了解。



  • 要求3:
微信支付-后台


【任职要求】
熟练掌握C/C++语言,熟悉面向对象、设计模式,熟悉LINUX开发环境。在海量数据处理方面有专长者优先; 
熟悉多线程编程技术,对异步、并发技术有深入理解。有大规模高并发系统开发和设计经验者优先;
掌握扎实的计算机基础知识,HTTPS通信、数据结构、算法、数据库和操作系统知识;
责任心强,有较好的逻辑思维能力、沟通能力、能够承担工作压力,有强烈的求知欲,以及优秀的学习能力;


通用面试题-流程

自我介绍,反问

八股
计网(http)+数据结构(语法)+操作系统(linux)+数据库(mysql, redis)+算法题

岗位
场景,后端,安全(sql注入), 前端(js)


部分面经和题目(WXG-后端)(x5)

WXG - 微信支付,后台开发。
临时抱佛脚系列,网上找的一些面经大概答了一下,不保证答案对。
在这里插入图片描述

1、

引用:
nowcoder.com/feed/main/detail/edecba5db7e44227834d3151fa212168

介绍项目,java后端,问了好多安全问题、遇到攻击怎么办。
场景提问:抢消费券后端怎么处理高峰流量(要答架构每一层怎么设计)
60分钟做题:
3道题,都用c++写了,做完第二题还问我想不想继续做(这是啥意思啊,只能说可以继续)

反问:
有什么提升的,负责的工作,后续面试安排。

面试官很友好
HTTPS怎么保证安全(先TCP三次,然后SSL/tlc握手)
然后又是一堆安全问题()

公钥私钥(非对称加密方式,公钥可对会话进行加密、验证数字签名,使用对应的私钥才能解密会话数据,从而保证数据传输的安全性。 公钥是密钥对外公开的部分,私钥则是非公开的部分,由用户自行保管。)
token盗用伪造鉴别…(前端鉴权,后端鉴权,用过JWT)
又介绍了一下项目,开始深挖
指出了我项目安全性和应用性的问题(说得对)

反问:
和我说两三天会有结果。然后一小时秒挂


2、

引用:
nowcoder.com/feed/main/detail/35d10685f4b245ff9ca8db81310ffeec

一面3.14

算法题
链表求环 leetcode142
不用额外空间计算数组中出现了两次的数据并返回
OO设计

八股
计网
get/post(get是获取指定资源,post是上传资源并对上传的资源请求做出响应)
http和https(在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程。HTTPS 默认端口号是 443,要申请证书。)
http 301 302 404 501 502 503( 3xx重定向&永久临时,4xx客户端错&资源不存在,5xx服务器错&未开业&代理错&网络忙)
浏览器输入url幂等性(GET 方法是安全、幂等、可被缓存的,post是不安全不幂等的)

安全
session cookie 区别 什么时候都要使用(cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。session会在一定时间内保存在服务器上。 当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。)
泛洪攻击(一种拒绝服务(DDoS) 攻击,旨在耗尽可用服务器资源,致使服务器无法传输合法流量。通过重复发送初始连接请求(SYN) 数据包,攻击者将可击垮目标服务器计算机上的所有可用端口,导致目标设备在响应合法流量时表现迟钝乃至全无响应。)
sql注入 (SQL注入式攻击,把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的)
xss (跨站脚本攻击,利用XSS利用的是用户对网站的信任,指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的. 比如获取用户的Cookie,导航到恶意网站,携带木马)
crsf(跨站请求伪造,CSRF利用的是网站对用户网页浏览器的信任,欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。)

数据结构
数据结构里面堆和栈(栈是后进先出, 堆是大的或小的在上面 )
分布式锁(Redis 的 SET 命令有个 NX 参数可以实现「key不存在才插入,加锁成功」,反之失败) SET lock_key unique_value NX PX 10000  加锁时标识客户端和设置过期时间。)
hashmap hashtable(哈希计算方法不同,Hashtable不允许建为空,继承类为map&字典不同,初始容量16/11不同,遍历方式和迭代器不同,table同步且线程安全)
java 8种基本数据类型(byte、short、int、long、float、double、boolean、char)
int几个字节(4字节)

数据库
数据库索引(数据的目录,优化效率,B+/hash/全文,聚簇/二级,单列/联合)
B+树(B+ 树叶子节点之间用链表连接了起来,有利于范围查询,B+ 树的非叶子节点不存放实际的记录数据。
比B树更矮胖,IO次数少。)
哪些场景不适合用索引(索引失效,对索引使用函数&表达式计算&隐式转换,联合查找不满足最左匹配,模糊查找like,where子句or不满足)
innodb/myisam(都是B+树,但是MyISAM引擎不支持事务,所以mysql5.5以后默认用innodb)
limit 性能瓶颈(Redis 6.0引入的多线程,提高网络 I/O 的并行度,性能提升至少是一倍以上)
千万数据量解决方案(mysql是2000w数据,分库分表,或按一定的规则拆分,做到查询某一条数据库,尽量在一个子表中。 维护合适的索引,删掉不必要的。)
快排和堆排思路(递归,每次选个一个基准,小的放左边大的放右边。  构造一个堆,每次在末尾插入一个数,然后向上调整直到满足堆的根节点最大特性,删除时先跟最末尾交换再向下调整)

linux
进程和线程的区别(进程是资源拥有的基本单位,线程是调度的基本单位。一个进程同时存在多线程,共享地址空间资源)
线程占用的是那些资源(线程运行的本质就是函数运行,函数运行时信息是保存在栈帧中的,因此每个线程都有自己独立的、私有的栈区,这些局部变量是线程私有的)
了解协程吗(比线程更轻量级,完全由程序所控制,一个线程可以有多个协程,可以提高效率)
top命令可以看到哪些信息(系统的CPU、内存、运行时间、交换分区、执行的线程等信息)

前端
js变量类型(八种数据类型:未定义(Undefined)、空(Null)、数字(Number)、字符串(String)、布尔值(Boolean)、符号(Symbol)、任意大整数(BigInt)、对象(Object))
js定时器 描述使用场景 两个定时器区别
== 和 ===(严格相等,宽松相等)
定宽定高元素横向居中
css 圆角矩形 (border-radius 属性中只指定一个值,那么将生成 4 个 圆角)
radius=50%时是什么形状(宽度和高度的百分比,圆形)

场景
三个定时任务脚本部署在三台服务器上,如何设计只让一个脚本运行
50万行excel导入系统实现(参考developer.aliyun.com/article/1203833)

反问
面评
算法题a 2/3还需要锻炼编码能力,后面的面试多准备下项目
微信支付做什么
balabala
技术栈
c++,js,node,php还解释了原因

总计面了100多分钟



当晚官网查询进入复试(二面)
3.16
两道算法题
阿拉伯转中文大写人民币
合并顺序链表
问项目
问了Java里面怎么分配内存

反问
微信支付做什么
微信支付呗
技术栈什么
c++


3.17 接到电话hr预约面委面
3.20
聊项目
讨论设计一个web服务器 类似于nginx
再聊一个项目
两道算法题lru和按数字出现频率打印数组

3、

总结: 项目是重点,其他都是常规八股


23.03.22WXG微信支付
无自我介绍,提前十分钟直接开始 无算法题
上来先介绍部门,问我是哪人,技术栈是c++能不能接受,能不能接受工作城市是深圳 (上来就是劝退三连?)

我看你简历上项目挺多,能不能选择一两个最能体现你优势的项目来讲一讲?
面对抢优惠券这样的高负载场景,你从架构、负载均衡等方面说一下你的设计? 
答了参考Nginx进行负载均衡,然后在每台服务器怎么怎么弄 (面试官答希望听到的是逻辑层、数据层分别干了啥。。)

看你写了评论区功能,有考虑数据安全吗?用户隐私数据怎么处理? 说了雪花加密,sql注入这些
能不能再说下你对后台了解的一些东西? 说了下redis


问完马上说有什么要问他的,这时候感觉已经是凉了,就问了下建议
建议:能听出来你对后台知识,包括架构、高负载方面的了解,这点很不错;加强对后端知识的了解,微信支付是最注重安全的,刚刚你说的HTTPS、敏感词处理等等都没有回答的很好,希望能够再多补一下这方面的知识。
面完不到一分钟,官网啪挂了。


wxg还是wxg,捞得快挂得快不问八股,真的有点打击到了,继续再面吧。

作者:牛客摸鱼佬
链接:nowcoder.com/discuss/468140291388674048?sourceSSR=search
来源:牛客网


4、



第一次发帖,记录一下自己的秋招过程
许愿四面  (不用许愿了今天看已经挂了									
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【八股】2023秋招八股复习笔记1(CSBase+部分WXG题) 的相关文章

  • Android 打包aar给unity3d使用 项目心得

    步骤 制作androidproject 修改build gradle配置 打包aar 1 混淆打包aar 2 jar包导出 3 在其他的android工程引入aar 导入unity项目 运行unity3d输出apk包 新建一个project
  • JAVA性能分析工具--Jvisualvm使用方法

    JDK自带的JAVA性能分析工具 它已经在你的JDK bin目录里了 只要你使用的是JDK1 6 Update7之后的版本 点击一下jvisualvm exe图标它就可以运行了 这里是VisualVM 的官方网站 https visualv

随机推荐

Powered by Hwhale