mangodb和mysql处理高并发_常用高并发网络线程模型设计及mongodb线程模型优化实践(最全高并发网络IO线程模型设计及优化)...

常用高并发网络线程模型设计及mongodb线程 模型优化实践(最全高并发网络IO线程模型设计)

1. 线程模型一. 单线程网络IO复用模型

a1701560dccc374d177c2cbf808ea8f7.png

1.1 说明:

1. 所有网络IO事件(accept事件、读事件、写事件)注册到epoll事件集

2. 主循环中通过epoll_wait一次性获取内核态收集到的epoll事件信息,然后轮询执行各个事件对应的回调。

3.  事件注册、epoll_wait事件获取、事件回调执行全部由一个线程执行

1.2 该网络线程模型缺陷

1.  所有工作都由一个线程执行,只要任一一个请求的事件回调处理阻塞,其他请求都会阻塞。例如redis的hash结构,如果filed过多,例如一个hash key包含数百万filed,则该Hash key过期的时候,整个redis阻塞。

2. 单线程工作模型,CPU会成为瓶颈,如果QPS超过10万,整个CPU负载会达到100%。

1.3 典型案例

1. redis缓存

1.4 主循环工作流程:

while (1) {

//epoll_wait等待网络事件,如果有网络事件则返回,或者超时范围

size_t numevents= epoll_wait();

//遍历前面epoll获取到的网络事件,执行对应事件回调

for (j = 0; j < numevents; j++) {

if(读事件)

//读事件处理、读到数据后的业务逻辑处理

readEentDeal()

else if(写事件)

//写事件处理,写数据逻辑处理

writeEentDeal()

}

}

2. 线程模型二. 单listener+固定worker线程

2838e37e45a92b4c045384c1e0145c4f.png

1. listener线程负责接受所有的客户端链接

2. listener线程每接收到一个新的客户端链接产生一个新的fd,然后通过分发器发送给对应的工作线程(hash方式)

3. 工作线程获取到对应的新链接fd后,后续该链接上的所有网络IO读写都由该线程处理

4. 假设有32个链接,则32个链接建立成功后,每个线程平均处理4个链接上的读写、报文处理、业务逻辑处理

2.1 该网络线程模型缺陷

1.  进行accept处理的listener线程只有一个,在瞬间高并发场景容易成为瓶颈

2. 一个线程通过IO复用方式处理多个链接fd的数据读写、报文解析及后续业务逻辑处理,这个过程会有严重的排队现象,例如某个链接的报文接收解析完毕后的内部处理时间过长,则其他链接的请求就会阻塞排队

2.2 典型案例

1.  memcache缓存,适用于内部处理比较快的缓存场景、代理中间场景

3. 线程模型三. 固定worker线程模型

该模型原型图如下:

119e99a5803abb971d32d2bf554383eb.png

说明:

1. Linux kernel 3.9开始支持reuseport功能,内核协议栈每获取到一个新链接自动均衡分发给用户态worker线程。

2. 该模型解决了模型一的listener单点瓶颈问题

3.1该网络线程模型缺陷

单个线程accept接收客户端链接,同时通过IO复用方式处理多个链接fd的数据读写、报文解析、解析后的业务逻辑处理,这个过程会有严重的排队现象,例如某个链接的报文接收解析完毕后的内部处理时间过程,则其他链接的请求就会阻塞排队

3.2典型案例

1. nginx(nginx用的是进程,模型原理一样),该模型适用于内部业务逻辑简单的场景,如nginx代理等

4.线程模型四. 一个链接一个线程模型

该线程模型图如下图:

2beecc7a675b013b8bc51b77b7d3b227.png

说明:

1. listener线程负责接受所有的客户端链接

2. listener线程每接收到一个新的客户端链接就创建一个线程,该线程只负责处理该链接上的数据读写、报文解析、业务逻辑处理。

4.1 该网络线程模型缺陷:

1. 一个链接创建一个线程,如果10万个链接,那么就需要10万个线程,线程数太多,系统负责、内存消耗也会很多

2. 当链接关闭的时候,线程也需要销毁,频繁的线程创建和消耗进一步增加系统负载

4.2 典型案例:

1. mysql默认方式、mongodb同步线程模型配置,适用于请求处理比较耗时的场景,如数据库服务

2. Apache web服务器,该模型限制了apache性能,nginx优势会更加明显

5. 线程模型五. 单listener+动态worker线程(单队列)

该线程模型图如下图所示:

4e671767a1991e0ff3518a70a53fc214.png

说明:

1. listener线程接收到一个新链接fd后,把该fd交由线程池处理,后续该链接的所有读写、报文解析、业务处理都由线程池中多个线程处理。

2. 该模型把一次请求转换为多个任务(网络数据读写、报文解析、报文解析后的业务逻辑处理)入队到全局队列,线程池中的线程从队列中获取任务执行。

3. 同一个请求访问被拆分为多个任务,一次请求可能由多个线程处理。

4. 当任务太多,系统压力大的时候,线程池中线程数动态增加

5. 当任务减少,系统压力减少的时候,线程池中线程数动态减少

5.1工作线程运行时间相关的几个统计:

T1:调用底层asio库接收一个完整mongodb报文的时间

T2:接收到报文后的后续所有处理(含报文解析、认证、引擎层处理、发送数据给客户端等)

T3: 线程等待数据的时间(例如:长时间没有流量,则现在等待读取数据)

5.2单个工作线程如何判断自己处于”空闲”状态:

线程运行总时间=T1 + T2 +T3,其中T3是无用等待时间。如果T3的无用等待时间占比很大,则说明线程比较空闲。工作线程每一次循环处理后判断有效时间占比,如果小于指定阀值,则自己直接exit退出销毁

5.3如何判断线程池中工作线程“太忙”:

控制线程专门用于判断线程池中工作线程的压力情况,以此来决定是否在线程池中创建新的工作线程来提升性能。

控制线程每过一定时间循环检查线程池中的线程压力状态,实现原理就是简单的实时记录线程池中的线程当前运行情况,为以下两类计数:总线程数_threadsRunning、当前正在运行task任务的线程数_threadsInUse。如果_threadsRunning=_threadsRunning,说明所有工作线程当前都在处理task任务,线程池中线程压力大,这时候控制线程就开始增加线程池中线程数。该模型详细源码实现过程更多细节详见:https://my.oschina.net/u/4087916/blog/4295038

5.4该网络线程模型缺陷:

1.  线程池获取任务执行,有锁竞争,这里就会成为系统瓶颈

5.5典型案例:

mongodb动态adaptive线程模型,适用于请求处理比较耗时的场景,如数据库服务

该模型详细源码优化分析实现过程参考:

6.线程模型六. 单listener+动态worker线程(多队列)

该线程模型图如下:

63e3d2b381586aaa7a81264a1d202039.png

说明:

把一个全局队列拆分为多个队列,任务入队的时候按照hash散列到各自的队列,工作线程获取获取任务的时候,同理通过hash的方式去对应的队列获取任务,通过这种方式减少锁竞争,同时提升整体性能。

6.1 典型案例:

OPPO自研mongodb内核多队列adaptive线程模型优化,性能有很好的提升,适用于请求处理比较耗时的场景,如数据库服务。该模型详细源码优化分析实现过程参考:https://my.oschina.net/u/4087916/blog/4295038

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值