文章首发:面试随笔-tx后端开发(20220311) 作者:会玩code
网络
tcp连接为什么需要三次握手?
为了保证连接双方的发送和接收能力正常。
- 第一次握手,客户端发包,服务端收包。服务端得出结论:客户端的发送能力正常;服务端的接收能力正常;
- 第二次握手,服务端发包,客户端收包。客户端得出结论:客户端的发送能力和接收能力正常(因为之前发的包被服务端接收并正确回包了);服务端的发送能力正常。
- 第三次握手,客户端发ACK,服务端收包。服务端得出结论:服务端的发送能力正常;客户端的接收能力正常。
tcp连接为什么需要四次挥手?
tcp中数据是双向的,假设客户端主动断开;客户端发送fin包只是表示客户端->服务端无数据传输了;但服务端->客户端可能还有未传完的数据。所以需要四次握手:
客户端->服务端fin包服务端->客户端fin包的ack
(服务端->客户端完成剩下的数据传输后...)
服务端->客户端fin包客户端->服务端fin包的ack
tcp如何确保可靠性?
- 三次握手和四次挥手
- 序列号保证报文有序
- 校验和保证保文数据正确
- ack机制和重传机制
- 流量控制
- 拥塞阻塞
- ...
可参考后端面试总结-网络篇
udp和tcp的适用场景?
tcp注重稳定可靠,比较适用于对网络通信质量有要求,需要将数据准确无误的传递给对方的场景,比如HTTP,HTTPS,FTP等传输协议。
udp快但不稳定,比较适用于对当前网络通讯质量要求不高,但实时性比较高的场景,比如qq语音,直播等即时通讯。
数据库
简单谈下mysql的事务?先写undolog还是redolog?
mysql通过mvcc保证事务的隔离性,通过redolog、undolog、binlog保证数据的持久性和一致性;对任何数据行修改前都会先写undolog,奔溃恢复时,对于checkpoint之前的redo记录,是已经落盘了;对于checkpoint之后的,事务状态为commit的,表示事务已提交不需要回滚;对于事务为prepare的,先查看是否有完整的binlog日志,如果有,也不需要回滚;否则根据undolog对事务进行回滚。
mysql的强同步复制、半同步复制和异步复制?
- 异步复制:master只需要关心主库的提交,之后异步将binlog日志复制到从库进行重放;
- 半同步复制:master需等待至少一个从库回复日志复制的ack之后,再回复客户端成功,此时从库只是将日志写到relaylog,不一定已经完成binlog的重放,这种模式下会有读不一致,但是能保证写一致的;
- 强同步复制:master需要等待从库完成binlog的重放之后,再回复客户端成功。一致性最高,但可用性最差。
操作系统
进程间通信方式?
- 管道:简单,但效率较低,没有暂存的功能,不适合进程间频繁交换数据,并且管道只能传输无格式的字节流
- 消息队列:无锁,可以传输的数据量较大,但会造成频繁的系统调用,速度较慢。
- 共享内存:共享内存位于用户态,无需借助内核,速度最快,但读写竞争
- 信号量:是一种进程同步和互斥的方式(控制进程的执行顺序),信号量本质是一个变量;P操作将这个变量减一,表示占用一个资源,如果减完后信号量小于0,会阻塞P操作对应的进程;V操作将信号量加一,表示归还一个资源,如果加完后信号量小于等于0,需要唤醒等待该资源的进程。PV操作必须成对出现。
- 信号:程序可以注册多种信号处理回调函数,当接收到某些信号时,会中断程序当前执行流程,去执行信号处理函数,信号处理完毕后,被中断的进程将恢复执行。
- socket:能完成不同主机上的进程之间的通信。
语言
C 如何在栈上分配内存?
通过alloc函数
C++的虚函数?
- 通过virtual关键字定义,虚函数不代表基类不实现该函数;
- 定义虚函数是为了让基类的指针能调用子类的这个函数;
- 基类一般都采用虚析构函数,假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数,派生类中申请的空间就得不到释放从而产生内存泄漏
- 通过
virtual void funtion1()=0定义纯虚函数,在基类中没有定义,并要求任何子类必须实现该函数。
虚函数的实现原理?
当一个类声明了虚函数或者继承了虚函数,这个类就会有自己的虚函数表(一个链表/数组,每个元素是一个函数指针),子类的虚函数表中先将父类虚函数放在前面,再放自己的虚函数指针。调用时,根据对象的动态类型在其虚函数表中找到对应的函数指针。
指针和引用的区别?
如果把变量比作key:val(key: 内存地址;val:内存块);指针的内容是变量的key;引用是key的别名。