惊群效应
惊群现象就是多进程在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发送,那么它就会幻想等待的所有进程,但是最终却只可能由一个进程获得这个时间的“控制权”,对改事件进行处理,而其他进程获取“控制权”是吧,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群。
惊群效应的危害
系统对用户进程/线程品牌地做无效的调度,上下文切换系统性能大打折扣。为了确保只有一个线程得到资源,用户必须对资源操作进行加锁保护,进一步加大了系统开销。
解决办法
在accept之前加锁
SO_REUSEPORT
在使用SO_REUSEPORT后,多个进程的socket可以同时监听同一个ip:端口,然后由内核决定将新链接发送给哪个进程,显然会降低每个进程接收新链接时锁竞争。
允许多个socket bind()/listen()同一个tcp/udp端口。每个线程拥有字节的服务器socket,在服务器socket上没有锁的竞争
在内核层面实现负载均衡
安全层面,监听同一个端口的套接字只能位于同一个用户下面
处理新建连接时,查找listener的时候,能够支持在监听相同IP和端口的多个socket之间均衡选择
当一个连接到来的时候,系统到底是怎么决定哪个套接字来处理它?
对于不同内核,存在两种模式,一种叫做热备份模式,一种叫做负载均衡模式
热备份模式:一般而言,会将所有reuseport同一个ip地址/端口的socket挂在一个链表上,取第一个即可,工作的只有一个,其他的作为备份存在,如果该socket挂了,它会被从链表删除,然后第二个变化成为第一个。
负载均衡模式:和热备份模式一样,所有reuseport同一个ip地址/端口的socket会挂在一个链表上,当有谅解到来时,用数据包的源ip、源端口作为一个hash函数的输入,将结果对reuseport套接字数量取模,得到一个索引,该索引指示的位置对应的socket便是工作socket。这样就可以达到负载均衡的目的,从而降低某个服务的压力。
孤儿进程/僵尸进程
TCP连接过程、连接后处于什么状态
客户端最大连接数是多少
一个tcp连接由四元组成
本地ip+本地端口+远端ip+远端端口
一个设备不管是服务端还是客户端,所支持的最大tcp连接数,如果不考虑cpu以及内存消耗,只和这四个因素有关
服务端最大支持多少tcp连接?
不考虑cpu、内存、linux文件数目限制的前提下
变化一:客户端ip地址,由多少个客户端就有多少个端口
变化二:客户端发起端口,通常Linux默认情况下单ip支持的端口是65535个,除去1024个端口(保留端口),其他均可以作为客户端发起端口,因此这里的个数是6万
每个tcp连接都需要内存、cpu、端口号资源、文件描述符、线程
由于远端ip和远端端口已经固定,唯一遍历是本地ip和本地端口,而本地ip也是固定的,也就只有本地端口可变,前1024个端口保留,剩下的都可以用。
几个注意事项
1、客户端连接同一个服务端web应用的相同监听端口最大支持6w+,且需要调整linuxtcp连接参数
2、客户端如果可以在发起连接的时候改变本地ip地址,每增加一个ip,其最大连接能力增加6w+,比如配置多网卡、配置子接口等等
3、
select和epoll区别
mysql深度分页
mysql的InnoDB是非聚簇索引,分为主键索引和普通索引,把查询条件转移到主键索引树
通过子查询优化
子查询可以减少回表次数,加快查询速度
select id,name,balance FROM account where id in (select a.id from account a where a.update_time > "2020-09-19&" limit 100000, 1) LIMIT 10;
INNER JOIN 延迟关联
延迟关联的优化思路,跟子查询的优化思路是一样的,都是把条件转移到主键索引树,然后减少回表
SELECT acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.update_time >"2020-09-19" ORDER BY a.update_time LIMIT 100000, 10) AS acct2 on acct1.id= acct2.id;
标签记录法
limit深分页问题的本质原因就是“偏移量越大,mysql就会扫描越多的行,然后在抛弃掉,这样就导致查询新能下降。
其实我们可以采用标签记录法,就是标记一些上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描,这种方式由局限性,首先要按照id排序才可行。
select id,name,balance FROM account where id > 100000 order by id limit 10;
使用between…and…
很多时候,可以将limit查询转换为已知伪造查询,这样mysql通过范围扫描between…and…就能得到对应的结果。
select id,name,balance FROM account where id between 100000 and 100010 order by id;
算法
删除链表重复节点
查找最长不重复子串