Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.6k views
in Technique[技术] by (71.8m points)

PHP 单进程同步阻塞处理优化

前段时间接手了一个老系统,其中对于“订单”的处理是通过一个 PHP 脚本来完成的。

这里说的“订单”,不一定是传统的订单概念,因为业务场景相对特殊,上面脚本的作用就是用来处理大量数据库 IO 操作。

<?php
function doSomething(){
     // 查询数据库是否有需要处理的"订单"
     if ($exists) {
        // todo 
     }
}
while (true) {
    doSomething();
}

起初上线时并没有什么问题,但随着用户逐渐增多,最近暴露出了很多问题。

  • 首先上面那个脚本的处理方式是同步阻塞
  • “旧订单”还没处理完,“新订单”又进来了,“订单”处理不及时从而引发一系列业务问题
  • 类似处理还有其他几个脚本。导致数据库压力较大(数据库没做读写分离,单机部署)。

请问:

  • 这个场景有什么好的处理方式吗?
  • Swoole 的协程是否适用于该场景?

(老系统历史包袱较重,不适宜对项目整体进行大改动)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

处理任务递交到队列中是个很好的思路。

判断一下无效的IO操作多吗?最先能想到的是空轮询。队列的阻塞能力可以避免过多空轮询消耗在网络传输中。
可以分析一下exists()的sql是否存在锁表现象,这会导致CPU长时间处于sleep状态,会让你的任务吞吐速度很慢。数据库出现压力跟处理速度慢应该是互为因果的。
如果IO阻塞过于频繁,可以考虑使用swoole协程或者简单一点直接fork多进程去处理任务就好了。
关于数据库压力要根据你的业务来分析,如果是通过减缓处理速度来实现的话(“订单”处理不及时从而引发一系列业务问题)这个问题应该还是会处理,需要提交doSomething();对于数据库的压力。队列可以分担走existst()产生的压力,后面的要看具体业务了


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...