Reactor与多线程架构设计1.Redis 6.0 IO多线程方案 2.半同步半异步设计模式

lee老师

1.从0到1设计高并发的系统
    单机服务上面:
        cpu
        内存
        IO(性能影响很大,因为它很慢,1/100)
        多进程
        线程池
        read、write
        IO Reactor的设计模式

2.nginx源码很NB,如何学习?
    1.了解人家的设计方案

    2.当然还有语言、数据结构等细节

    3.把框框图转化为代码,如: redis 6.0的源码

3.reactor模式和线程池实现高并发服务
    背景:
        IO: socket函数、打开文件的文件句柄 ==> socket或fd就是IO

    方案:
        1.同步编程
            while(1){
                epoll_wait(..);
                for(;;){
                    if(fd == listener_socket){
                        cfd = accept(listener_socket)
                    }else{
                        read(fd, buf, size);
                        process(buf);
                    }
                }
            }


            好处:
                写代码很简单。

            坏处:
                写代码之前存在的问题。不明白存在的问题,那只能是一个coder,根本不理解技术。

                读写全在一个线程,那么这个线程压力是很大的。
                read、write性能是cpu的1/100左右,性能很低,很耗时。假如10W个读写,那么后面的请求都在排队,那么延时增加。
                    所以之前单线程的redis变为了现在6.0中多线程的方式。


        2.半同步、半异步编程
                初步改进:
                        T1线程:

                        while(1){
                            epoll_wait(..);
                            for(;;){
                                if(fd == listener_socket){
                                    cfd = accept(listener_socket)
                                }else{
                                    read(fd, buf, size);
                                    enqueue(buf); // 放入队列中
                                }
                            }
                        }

                        T2线程:
                            while(1){
                                wait_queue(buf);
                                process(buf)
                            }


                        如:
                            账户注册,要访问mysql数据库,那么process很耗时,那么我们能不能让其它的线程去处理它呢?

                            讲完后,我们脑袋中是否有一个模型?没有模型,则说明我们没有理解这个代码,我们写代码则无从下手。
                                某个线程在某个cpu上运行。

                            T1线程msg包装为task,然后交给T2线程处理。==》半同步,半异步的处理方案。

                问题:
                    线程间需要同步。
                    线程间有数据拷贝,这个拷贝也是很耗cpu的。
                    epoll所在的线程要处理所有的网络IO的读和写,这个线程的压力远远超过其余的业务处理线程。
                        那么==》read还是在T1线程中,能否拿出来呢?==》reactor的设计方案            

        3.纯异步-Reactor设计
            也叫做:底层IO事件驱动。如:nginx的设计。

            事件,如何理解?
                fd:socket/file(linux中一切皆文件)
                      这个客户端有数据过来了,那么就是fd有事件了,那么NGX_EVENT_READING 0x01 ...

                      那么我们就设置事件: EPOLLIN、EPOLL...==》我在Loop循环中,我们仅仅是做设置事件这个操作--》ev-->handler(ev)

                      如何设计呢?
                          路复用器:
                              我们封装为多路复用器,select、epoll、kqueue。
                              event->fd |= READ/WRITE/TIMEOUT;

                          反应堆:
                              我们在1的复用器里面设置了可读、可写后,就到反应堆里面。
                              我们反应堆中的handler是从哪里来呢?--》event、addEvent--》handler--》callback handler

                          dispatch:
                              如何派发出去?


                              T1线程把事件派发到其它Worker线程的队列中。而不是T1接到的先放到一个队列中,其它Worker线程从中读--》感觉少了一次拷贝?


        4.Reactor与多线程结合

4.IT行业
    1.我们2~3年在重复之前的经验的话,那说明有点问题

    2.我们面对新的问题,我们跳槽面对了新的业务
        1.学习理解能力

5.redis为何设计为单线程?
    (1)定位:内存操作的缓存服务:
        把值放内存就OK了,而不是写磁盘。

        我们尽量不存mysql中读,而是从redis中读。

    (2)还可能被其它服务同时访问,如:用户注册、订单处理。
        因此,我们需要顺序化的处理: 
            如,用户注册,公孙胜注册进来了。

            订单处理:
                也要操作公孙胜这个key。


    如何做到?
        第1步:
            谁先可读,就放到前面,fd_u, 严格的从上往下处理。 现在是单线程的方案,那么我们是否能改为多线程方案?
                主线程先放:pending client queue

        第2步:
            分发给所有的IO线程。 每个线程有个io_threads_list,
                不一定非得加锁? 忙等待也是一种思路。

        第3步: 
            忙等待所有的io thread处理完成。
            要么都在读,要么都在写。

        第4步:
            统一返回。

6.面试题与场景
    IM:先登录,再发送的聊天信息,如何保证顺序处理?

    斗地主:lee出了个3,darren一定要晚于出3这个操作。

7.如何把产品设计稳定,则需要功力。


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
主从 Reactor 多线程是一种常见的网络编程模型,它通常用于高并发服务器的开发。该模型的核心思想是将网络 I/O 与业务逻辑分离,并通过多线程来实现并发处理。 在主从 Reactor 多线程模型中,主线程(也称为 Acceptor 线程)负责监听客户端连接请求,并将连接分配给工作线程(也称为 EventLoop 线程)进行处理。工作线程负责处理连接上的读写事件和业务逻辑,并将需要执行的任务交给线程池中的线程进行处理。 主从 Reactor 多线程模型主要包含以下组件: 1. Acceptor:负责监听客户端连接请求,并将连接分配给工作线程进行处理。 2. EventLoop:负责处理连接上的读写事件和业务逻辑,并将需要执行的任务交给线程池中的线程进行处理。 3. Thread Pool:用于执行异步任务,例如数据库查询和计算密集型任务等。 在实现主从 Reactor 多线程模型时,需要注意以下几点: 1. Acceptor 线程与工作线程之间应该使用线程安全的队列进行通信。 2. 每个工作线程应该拥有一个 EventLoop 对象,用于处理连接上的读写事件和业务逻辑。 3. 线程池中的线程应该使用异步方式执行任务,以避免阻塞工作线程。 总之,主从 Reactor 多线程模型是一种高效的网络编程模型,可以有效地提高服务器的并发处理能力。但是它的实现比较复杂,需要考虑线程同步、线程安全和性能等方面的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值