保持学习, 保持警惕, 居安思危, 走出舒适区.
字节一面
在面对未知的流量暴增,可以预先怎么处理
如果流量突然飙大,总有一个资源会遇到瓶颈。按照经验大概出问题地方是DB,磁盘IO、CPU、带宽、连接数、内存其中的一个或几个。
流量暴涨的原因
一般情况下,引起网站流量暴增大致为以下两种情况
- 不可预测流量(网站被恶意刷量;CDN回源抓取数据;合作业务平台调取平台数据等)
- 可预测流量(突然爆发的社会热点,营销活动的宣传;)
不管是可预测流量还是不可预测流量都会表现在带宽和网站整体架构的应对方案上
如果由于带宽原因引起,由于网站的并发量太高,达到服务器的吞吐极限,导致服务器宕机,这时需要做临时申请加大带宽,然后负载均衡分流。
如果由于外网请求数据库,导致数据库频繁读写,数据库处理能力低,导致大量请求积压;如果是这种情况,就需要优化SQL,存储过程等,如果是请求过大,就要考虑做集群等。
可预测流量的暴增也会拖慢网页的打开速度,甚至导致网站服务器宕机。要应对正常流量暴增,在流量高峰期到来之前就可以适当的调整,一般针对应用服务器的调整可以防止单点,负载均衡,高可用,增加后端web
应用服务器数量,数据库读写分离,分库分表等,防止流量暴增导致服务器挂掉
防止流量暴涨预备方案
流量估算
作为一个经验充足的老运维,可以把设计流量*3作为系统压力的下限,即实现完了要压测,压测得到的结果要达到设计流量 * 3( * 4, * 5都可以),比如服务器在IDC机房,在签合同之前就可以说明当流量异常的时候,提供一定的缓冲带宽,如果是云服务器,可以临时加带宽。
关键是要给系统留些缓冲。一旦发生了什么,不至于挂的太惨。此时,一般会得到一个带缓存的业务服务系统。考虑到缓存高于后台服务2~3个数量级的性能优势,多撑几倍流量一般不成问题。
降级方案
限流方案
- 参考: 如何应对网站流量暴增
如何限流,限流算法,对于ddos攻击怎么处理
如何限流
计数器
滑动窗口
漏桶
令牌
参考: 如何应对网站流量暴增
ddos处理
遇到1G以下的攻击,使用防火墙就可以搞定(或者使用一些免费的云防御产品);流量1G—10G时可以选择机房进行流量迁移和清洗;大于10G时使用高防CDN(云防御)是相对最靠谱并且价钱最能接受的。
参考: 记一次DDOS攻击防御实录
PHP数组的底层实现
PHP 数组的底层实现是散列表(也叫 hashTable ),散列表是根据键(Key)直接访问内存存储位置的数据结构,它的key - value 之间存在一个映射函数,可以根据 key 通过映射函数得到的散列值直接索引到对应的 value 值,无需通过关键字比较,在理想情况下,不考虑散列冲突,散列表的查找效率是非常高的,时间复杂度是 O(1)。
- 参考: PHP7 数组的底层实现
分布式事务
分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。
简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
RPC相对于传统的API调用的优点
REST(HTTP-Based)、RPC(Socket-Based)
|接口类型|优点|缺点|
|:—-|–:–|–:–|
|REST|RESTful API充分利用了HTTP协议的设计,使用了面向资源的接口设计,相对于传统RPC降低了接口设计的复杂度|RESTful API面向资源设计接口,而对于一些复杂操作来说,接口设计难度将大于RPC形式|
|RPC|1) 方便使用RPC来调用远程函数,冰得到对应的结果,就像调用本地方法一样 2) 编写分布式应用程序更加简单容易,因为RPC将所有的网络代码都隐藏到了存根函数中,开发人员不必关注通信等细节 3) RPC是跨语言的|1) 交互方式单一,不能进行复杂多模块之间的协议交互 2) 开发难度,RPC框架肯定高于基于简单HTTP协议的REST接口|
- 参考: Rest和RPC接口区别
服务调度中心的感知与动态上下线
zookeeper
参考: 分布式服务动态上下线感知
MySQL的索引,为什么是B+而不是平衡二叉树
索引查找在Linux的磁盘上是怎么操作的
聚簇索引相对于B+索引的优点
- 参考: 浅谈聚簇索引和非聚簇索引的区别
如何分析SQL执行慢的原因
Redis连接时的connect
与pconnect
的区别
connect
:脚本结束之后连接就释放了pconnect
:脚本结束之后连接不释放,连接保持在php-fpm进程中。
Redis有哪些结构时间复杂度较高
Redis hash的实现
- 参考: Redis之Hash数据结构
算法题
在1个10G大小的文件中,存储的都是int型的数据,如何在内存使用小于8M的情况下进行排序
设计题
以微博为例,有1个亿的用户,同时用户之间有关注和粉丝,用户的关注和取关操作比较频繁,如何设计架构和API接口
- 参考: 新浪微博技术架构分析和设计
字节二面
守护进程是什么,怎么实现
守护进程(Daemon)是运行在后台的一种特殊进程,也称为精灵进程。是生存期较长的一种进程,常常在系统自举时启动,仅在系统关闭时终止。没有控制终端,仅仅在后台运行,Linux有很多守护进程执行日常事务活动,是不受终端控制的进程。
- 参考: 守护进程详解及其代码实现
PHP是否适合做守护进程,为什么(内存管理这一块)
不适合,因为PHP本身不是常驻内存
PHP的垃圾回收机制
- 参考: php7 垃圾回收机制详解
进程间通信方式
IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC
参考: Liunx 六大进程间通信方式
共享内存是怎么实现的
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
- 参考: 进程间的五种通信方式介绍
怎么查看Linux服务器的负载,及判断哪些操作引起的负载过高
MySQL的IO过高怎么优化,分库分表及分区
MySQL的索引结构,myisam的索引结构, innodb的索引结构,innodb为什么必须要有主键索引
MyISAM: 使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址
InnoDB: 也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同
添加索引,为什么可以减少io操作(磁盘页)
首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。
nginx的负载均衡算法
round robin(默认)
: 轮询方式,依次将请求分配到各个后台服务器中,默认的负载均衡方式。weight
: 根据权重来分发请求到不同的机器中,指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。ip_hash
: 根据请求者ip的hash值将请求发送到后台服务器中,可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。url_hash
: 根据请求的url的hash值将请求分到不同的机器中,当后台服务器为缓存的时候效率高。fair
: 根据后台响应时间来分发请求,响应时间短的分发的请求多。参考: nginx负载均衡的五种算法
算法题
查找一个字符串中最长的无重复字串
字节三面
在一个横向和纵向都是递增的有界二维坐标轴中,如何快速判断某个数是否存在于这个二维坐标中
设计一个定时任务管理器
滴滴2020PHP面试题
处理算法题,最大无重复子串,链表的值交换
遇到过线上服务器CPU飙高的情况没有,如何处理
登录服务器,执行top命令,查看CPU占用情况;定位线程;定位代码,解决问题
对线程池的理解,项目中哪个地方使用了,如何使用的,用的框架中的哪个实现类,为什么用这个
- 1)创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率
- 2)线程并发数量过多,抢占系统资源从而导致阻塞
- 3)对线程进行一些简单的管理, 延时执行 定时循环执行
对MySQL索引的理解、对组合索引的理解、索引的最佳实践
- 普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
- 唯一索引:索引列的值必须唯一,但允许有空值
- 复合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
- 聚簇索引(聚集索引):并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。
- 非聚簇索引:不是聚簇索引,就是非聚簇索引
分布式锁的实现、对比Redis分布式锁 & ZK分布式锁
- 基于数据库实现;
- 基于缓存(Redis等)实现;
- 基于Zookeeper实现;
怎么理解微服务,服务如何划分,可以从哪几个方面去划分,为什么这样划分,微服务带来了哪些好处,哪些坏处,如何看待这个问题?
- 服务间调用,服务发现,服务容错,服务部署,数据调用
如何理解网关,网关带来的好处和坏处,如何解决
- 高性能,可横向扩展
- 高可靠,业务不中断
- 插件化的API安全控制
- 灵活的数据编排
- 精细化流控
- API版本管理
- API数据分析
- 高效插件化路由算法
- 安全认证,防攻击
- API访问控制
- Swagger导入导出
掌握哪些设计模式,常用哪些,项目中如何使用的,为什么用这个,不用那个?手写一个线程安全的单例模式
单例模式,工程模式,注册模式,适配器模式,观察者模式,策略模式
如何设计一个秒杀系统?
前端
- nginx负载均衡,将请求分发到各个服务器,减轻压力。
- js、css压缩,减少流量以及请求次数。
- js、css压缩,减少流量以及请求次数。
缓存
- 采用redis缓存,可以提前将某些秒杀的数据加载到缓存。如库存先加载到缓存,判断缓存里的库存,成功后再继续,同时为了防止大量访问redis,可以用共享变量标识是否卖完,如卖完了,则直接返回,不用访问redis。
- 页面缓存,即将页面直接缓存到redis,或者页面静态化,即前后端分离。
- 开启浏览器缓存。
限流
- 使用消息队列,例rabbitmq进行消峰。
- 利用验证码防止恶意刷单,可以有效降低单位时间内访问次数。
- 地址隐藏,防止知道地址后提前购买以及多刷。
- 一定时间内限制url访问次数。
数据库
- 利用行级锁,先扣库存,成功后再创建订单,防止超卖。
- 唯一索引,防止重复购买。
- 数据库读写分离,如mycat。
假设现在双十一零点,大量下单请求,如何对这些订单进行分库分表,为什么?
分布式ID
将订单数据划分成两大类型:分别是热数据和冷数据。
热数据:3个月内的订单数据,查询实时性较高。
冷数据A:3个月 ~ 12个月前的订单数据,查询频率不高。
冷数据B:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。
MySQL事务隔离级别、MVCC?
- 数据库事务的隔离级别ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)。
- SQL标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )。
知识点
分布式架构、高可扩展、高性能、高并发、服务器性能调优、Laravel、TP6、Yii2、Redis、Swoole、Swoft、RabbitMQ、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx