面试合集记录之一

一、构建一种死锁的场景

线程T1需要先后访问资源A和B,线程T2需要先后访问资源B和A;

T1先对A进行上锁处理,T2先对B进行上锁处理;T1在访问B时,B被占用,进入阻塞;T2在访问A时,A被占用,进入阻塞

二、延迟队列实现方法

1、zset,将timestamp+延迟时间作为sorce,轮询任务每秒只轮询 score 大于当前时间的 key即可

2、rabbitMQ,TTL(time to live)和DLX(Dead letter exchange)是两个关键的点

1、如果有事件需要延迟那么将该事件发送到MQ 队列中,为需要延迟的消息设置一个TTL;
2、TTL到期后就会自动进入设置好的DLX,然后由DLX转发到配置好的实际消费队列;
3、消费该队列的延迟消息,处理事件。

三、限流

1、固定窗口

三个值,当前时间curTime,标记时间markTime,时间窗口长度windowSize

如果curTime>markTime+windowSize,返回0,matkTime=curTime;

如果curTime<markTime+windowSize,查看计数器是否超过阈值,超过返回false,丢弃;否则正常处理

2、滑动窗口

在固定窗口的基础上,增加一个分片参数,将这个大的窗口分的更细

3、漏斗

设置一个最大容量的队列,有请求就进入队列,当队列达到最大容量时,废弃请求

4、令牌

请求来到时会向桶(redis list)中取令牌,取到就对请求进行处理,否则丢弃。

自我理解时,没当消费掉一个请求时,向桶中再写入令牌。

四、读写分离如何保证数据一致性

1、缓存标记

在进行写操作时,将唯一标识(用户id+业务id)写入数据库,并设置过期时间(需要预估主从同步时间)

用户在读取数据时,先从redis中查看是否有缓存标志,有的话读主库,否则读从库

2、本地缓存标记

这种方式还是会存在数据不一致,就是本地用户在写操作时,在客户端本地设置一个redis标志,本地用户在进行读操作的时候,检查该标志是否存在,存在,读主库;否则读从库

3、数据库同步写方案

数据库写操作成功返回前,等同步结果;同步成功,才进行返回

4、选择性强制读主

对于一些对一致性要求较高的场景,强制读主

5、中间件

同缓存标记,只是这个操作由中间件来做

五、主主复制冲突

不同机器的增长步长设置的不一致

六、分布式锁

使用redis的setnx来做分布式锁,客户端加锁时,使用setnx lockname value(如果lockname不存在则设置lockname值为value,否则返回0,表示操作不成功),进行具体的业务操作

改进方式1:如果客户端在加锁过程中崩溃,会导致锁无法释放,此时可以给锁设置一个过期时间

改进方式2:设置过期时间后,如果在业务代码执行过程中就到了过期时间,怎么办呢,起一个守护进程,对锁进行续期,检测到业务代码正常执行时,不断给锁续期

七、事务特性及隔离级别

https://www.jianshu.com/p/081a3e208e32

ACID 原子性、一致性、隔离性、持久性

redo log可以保证持久性

undo log 可以保证一致性

隔离级别

隔离级别脏读(A未提交的事务,B可以读到)

不可重复读

(针对update操作,

A读到1000,B读到1000,B优先A进行消费,A读不到)

幻读

(针对insert和delete操作

B读到80,A在消费,B最终打印出1080)

备注
读未提交
读已提交一般sql、oracal采用这种方式
可重复读
序列化

不可重复读:行锁可以解决

幻读:表锁可以解决

八、悲观锁和乐观锁

https://www.jianshu.com/p/d2ac26ca6525

1、乐观锁:适用于多读少写场景

不需要借助数据库的锁机制,但可以有版本的概念,在表的末尾增加一列,表示这一行数据的修改版本号,每次有修改,版本号+1;在提交修改时,比较上次读取的版本号和当前版本号是否一致,一致进行修改,否则丢弃或者重试

2、悲观锁:适用于多写少读场景

包括共享锁和排他锁,

共享锁:读锁,S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

排他锁:写锁, X 锁,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。获取排他锁的事务可以对数据行读取和修改。

悲观锁需要借助数据库的锁机制,要注意锁的级别,MySQL InnoDB 默认行级锁。行级锁都是基于索引的,如果一条 SQL 语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意。

九、TCP

为什么会出现大量的close_wait

大量 CLOSE_WAIT 表示程序出现了问题,对方的 socket 已经关闭连接,而我方忙于读或写没有及时关闭连接,需要检查代码,特别是释放资源的代码,或者是处理请求的线程配置。

为什么会出现大量的time_wait

大量的短连接(业务处理+传输时间 远远小于timewait超时时间 的连接)

  • 高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是

图片为引用:https://www.zhihu.com/question/271701044

十、TCP UDP区别

tcp是可靠传输,udp是不可靠传输

tcp是面向连接的,udp是无连接的

tcp是面向字节流传输,udp是面向报文传输

UDP
是否连接无连接面向连接
是否可靠不可靠传输,不使用流量控制和拥塞控制可靠传输,使用流量控制和拥塞控制
连接对象个数支持一对一,一对多,多对一和多对多交互通信只能是一对一通信
传输方式面向报文面向字节流
首部开销首部开销小,仅8字节首部最小20字节,最大60字节
适用场景适用于实时应用(IP电话、视频会议、直播等)适用于要求可靠传输的应用,例如文件传输

十一、session和cookies的区别

1、session存储在服务器端,cookie存储在客户端,session的安全性更高

2、获取session信息是通过存放在会话cookie里的session id获取的,而session是存放在服务器的内存里的;所以session里的数据不断增加会造成服务器的负担,因此要选择重要的信息存储在session中

3、cookie分为两类,会话cookie和持久化cookie;会话cookie的生命周期和浏览器是一致的,持久化cookie存放在客户端硬盘中,即cookie文件中,依据最大时间失效

4、session信息是通过sessionid获取的,而sessionid存储在会话cookie中,当cookie过期,sessionid也会消失,所以这个时候session并不是不存在,只是读不到。

十二、http返回码

499 超时 客户端在服务端没有返回之前就终止连接

500, Internal Server Error , 服务器内部错误

502 bad gateway 往往表示网关从上游服务器中接收到的响应是无效的。代理到一个不存在的端口/后端终止了程序

504 Gateway Timeout,网关超时,它表示网关没有从上游及时获取响应数据。扮演网关和代理的服务器无法在规定时间内得到有效响应

499,502,504都会因为超时而产生,区别是超时超了谁的时,499是超了客户端本身的连接时间,502是超了CGI的执行时间,504是超了服务器本身的最大允许读取时间。

302 重定向


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值