今天突然发现很多以前理解过的概念,再次回顾的时候感觉有点模糊了,翻了翻笔记又有了一些新的理解。
1.场景
简单的异步任务执行可以直接通过管道向子进程投递异步任务,然后触发事件执行任务。
Redis的订阅与发布也可以实现上述的功能,但它的优势在于它可以一对多,PUBLISH之后可以同时触发多个订阅的事件,并且可以在任意进程内进行订阅。
专门的消息队列组件,则适用于对消息队列要求比较高的场景(消息确认、消费者组等)
在大多数操作系统中,父进程和子进程通常被分配相同的 CPU 时间片。时间片是操作系统用来调度进程的一种机制,它将 CPU 时间划分为较小的块,并按照某种策略分配给不同的进程。每个进程被分配一个时间片,在该时间片结束后,操作系统会剥夺该进程的 CPU 使用权,并将其分配给其他进程。所以多进程程序获得的CPU时间片比单进程程序多。
2.问题
Mysql一个链接的内存占用?(PHP协程创建了100个不进行操作的连接,占用内存7.8m)
主从复制,数据同步延时的问题?
数据量过大时,避免使用join,通过协程并发查询?
将单个查询分解成多个查询,通过协程并发查询?
读是共享锁,写是排它锁,考虑读写分离?
创建协程,单个协程需要的内存大小(底层默认分配2M(C)虚拟内存+8K(PHP)内存(PHP-7.2或更高版本)。这里的虚拟内存是指操作系统并不会立即分配2M物理内存,系统会根据在内存实际读写时发生缺页中断,再分配实际内存)?
测压过程中如何一步步排查问题所在?
自定义进程的数量,消费者消费的速度、消费者被阻塞的时长?
索引降维和连接池预热?
数据量过大时,直接分库,通过封装中间层,来实现现有业务的无缝迁移。
多个进程分配到的时间片会更多,通过多进程处理异步任务。多进程封装成一个进程组,然后通过原子计数器将任务平均派发到每一个进程。
协程机制的优点之一就是有阻塞就会自动处理别的任务,比如Mysql被阻塞就去处理Redis读取,Redis被阻塞就去Mysql;
3.Swoole协程
协程没有IO等待 正常执行PHP代码,不会产生执行流程切换
协程遇到IO等待 立即将控制权切,待IO完成后,重新将执行流切回原来协程切出的点
协程并行协程依次执行,同上一个逻辑
协程嵌套执行流程由外向内逐层进入,直到发生IO,然后切到外层协程,父协程不会等待子协程结束
Swoole的协程在底层实现上是单线程的,因此同一时间只有一个协程在工作,协程的执行是串行的。这与线程不同,多个线程会被操作系统调度到多个CPU并行执行。
一个协程正在运行时,其他协程会停止工作。当前协程执行阻塞IO操作时会挂起,底层调度器会进入事件循环。当有IO完成事件时,底层调度器恢复事件对应的协程的执行。
对CPU多核的利用,仍然依赖于Swoole引擎的多进程机制。
Swoole遇到需要等待的IO才会切换,比如SQL查询、比如网络请求等待响应、比如读取文件等找到那个文件。
从Mysql获取返回的结果集,这个需要CPU来计算,需要写内存,所以Swoole协程的单线程模型是串行来的,所以对于结果集数据量级过大的查询,效果不明显。
搞明白什么时候会发生协程切换,业务无关的任务可以异步处理
4.关于队列
队列可以通过客户重要性等条件因素,进行优先级划分。优先级越高的越先处理(Redis的zSet类型数据)。
如何及时处理的区别就在于,队列可以进行中间操作,根据任务进行不同的异步处理。
5.协程的调度
Swoole 的协程化主要集中在 I/O 操作上,通过异步 I/O 提升了 I/O 密集型任务的性能。对于 CPU 密集型操作,虽然不会阻塞协程,但可能会占用较多 CPU 时间,影响协程的响应速度。协程的切换主要依赖于以下几种情况:
I/O 操作:当协程执行异步 I/O 操作时,会自动挂起,让出 CPU 给其他协程运行。
显式让出:协程可以通过调用 Swoole\Coroutine::yield 或 Swoole\Coroutine::suspend 显式让出 CPU。
超时等待:协程在等待某个操作完成时,如果设置了超时时间,超时后会自动让出 CPU。
CPU 密集型操作不会触发协程的挂起。如果一个协程执行了耗时 5 秒的CPU 密集型操作,它会占用当前协程的 CPU 时间。具体影响如下:
当前协程:执行CPU 密集型操作的协程会持续占用 CPU,直到操作完成。
其他协程:其他协程仍然可以运行,但会受到当前协程占用 CPU 时间的影响。如果当前协程占用 CPU 时间过长,其他协程的执行时间会相应减少。
6.一个进程的 CPU 时间由什么决定
- 进程的优先级:
- 操作系统会根据进程的优先级分配 CPU 时间。高优先级的进程会获得更多的 CPU 时间,而低优先级的进程可能会被推迟执行。
- 进程的 CPU 使用情况:
- 如果进程执行的是 CPU 密集型任务(如计算密集型操作),它会占用较多的 CPU 时间。
- 如果进程执行的是 I/O 密集型任务(如文件读写、网络通信),它会在等待 I/O 操作完成时释放 CPU 时间,让其他进程运行。
- 操作系统的调度策略:
- 操作系统使用调度算法(如时间片轮转、优先级调度等)来分配 CPU 时间。每个进程会获得一定的时间片(通常几毫秒)来运行,时间片结束后,操作系统会切换到其他进程。
- 在多核处理器系统中,多个进程可以同时在不同的核心上运行,从而提高系统的整体性能。
- 系统负载:
- 当系统负载较高(即有多个进程同时竞争 CPU 资源)时,每个进程获得的 CPU 时间会减少。
- 当系统负载较低时,进程可能会获得更多的 CPU 时间。
- 进程的阻塞状态:
- 如果进程进入阻塞状态(如等待 I/O 操作完成),它会释放 CPU 时间,让其他进程运行。
- 阻塞状态的进程不会占用 CPU 时间,直到它从阻塞状态中恢复。
7.常见的进程阻塞
I/O 阻塞是指进程在等待输入/输出操作完成时进入的阻塞状态。常见的 I/O 操作包括:
文件读写:如打开文件、读取文件内容、写入文件等。
网络通信:如发送数据、接收数据等。
设备操作:如读取磁盘数据、等待用户输入等。
进程在等待某个时间间隔时会进入阻塞状态。常见的操作包括:
sleep:使进程休眠指定的时间。
usleep:使进程休眠指定的微秒数。
......