Swoole

[PHP] Swoole整合PHP性能分析

不羁岁月 提交于 2020-08-05 22:54:41
参考文章: Swoole整合PHP性能分析平台: Tideways+Xhgui 根据以上文章,作为修改和补充 本文章是这文章的补充和延伸: [Docker] 用PHP7.4+Swoole+sdebug打开PHP的二次元世界 安装tideways扩展 !!!FBI WARNING!!! git clone https://github.com/tideways/php-xhprof-extension.git cd php-xhprof-extension phpize ./configure --with-php-config=/usr/local/php7/bin/php-config make && make install 编译完成后在php.ini中加入 extension=tideways_xhprof.so 查看是否安装成功 php --ri tideways_xhprof 成功会输出以下内容 安装mongodb扩展 其实非一定要依赖这个扩展的,但下面介绍的laynefyc/php-monitor扩展,会检测mongodb,所以也需要装上这个 wget https://pecl.php.net/get/mongodb-1.7.4.tgz tar -zxvf mongodb-1.7.4.tgz cd mongodb-1.7.4 phpize ./configure

redis主从复制数据延迟解决方案

有些话、适合烂在心里 提交于 2020-08-05 18:13:56
在 redis 主从复制模式下可能会出现 slave 延迟导致读写不一致的问题。 解决办法有2种 1. 修改从几点参数配置 从节点的 slave-serve-stale-data 参数也与此有关,它控制这种情况下从节点的表现 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式: 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”。 2. 编写外部监控程序 将主从模式更换为哨兵模式则无需自己去做监控 对于无法容忍大量延迟场景,可以编写外部监控程序监听主从节点的复制偏移量,当延迟较大时触发报警或者通知客户端避免读取延迟过高的从节点。 编写监控程序,然后定时执行 <?php /** * [监控 redis 主从复制偏移量:当监控到延迟高的节点时,移除延迟高的从节点, 即动态修改读写分离配置信息。(可以添加触发报警机制)] * [在做主从复制时推荐使用 redis 的哨兵模式,则无需自己去监控,哨兵模式能自己监控并切换主从] * * @Author leeprince:2020-05-05 10:29 */ define ( 'IS_DEBUG' ,

mysql读写分离在项目实践中的应用

心已入冬 提交于 2020-08-05 17:03:42
工程背景介绍: 我们开发了一个万能接口,用户通过这个接口中传入数据,我们拿到数据进行复杂的逻辑处理然后再将数据各种匹配展示分发等操作,处理的流程相当庞大,接口中我们只保留了接收数据和返回一个本次请求的id的操作,其余操作都是异步到其他程序中处理的。 返回id的操作是需要和数据库进行两次连接,一次读库得到最新的id 然后把id更新到数据库。 项目出现问题: 我们以为自己的程序就像上图中的那样运行,一次请求,读库,写库,返回id,其余异步处理。但是没有考虑高并发,强压力写的性能问题,在高并发下,多个接口线程同事访问数据库,这样的情况会出现并发同步的问题,当然这点我们是考虑到了 ,使用线程锁可避免数据的幻读,重复读等。可一旦这样大量的接口线程堆积,很快服务器cpu将扛不住发生宕机! 那如果不试用线程同步锁呢,很明显不只是数据的错乱问题将发生,数据库在极大线程的访问压力下也将抗不住,cpu使用率达到85%!程序面临着瘫痪的风险。 解决方式: 1.数据库集群? 好处:增加数据库服务器,压力随之分摊到几个服务器中,减小数据库压力 坏处:硬件成本大 数据库主从问题 哈希一致性问题 单点故障问题 2.接口服务器集群 好处:访问压力被分摊到几个服务器中 线程的堆积问题得到有效解决 坏处:硬件成本大 单点故障问题 nignx负载均衡服务器的搭建 操作复杂 以上两种方案都是增加硬件成本,加大了开发难度

php+redis消息队列实现抢购功能

三世轮回 提交于 2020-08-05 16:45:07
实现功能: 1. 基于redis队列,防止高并发的超卖 2. 基于mysql的事务加排它锁,防止高并发的超卖 基于redis队列工作流程: 1. 管理员根据goods表中的库存,创建redis商品库存队列 2. 客户端访问秒杀API 3. web服务器先从redis的商品库存队列中查询剩余库存重点内容 4. redis队列中有剩余,则在mysql中创建订单,去库存,抢购成功 5. redis队列中没有剩余,则提示库存不足,抢购失败重点内容 基于mysql事务和排它锁工作流程: 1. 开启事务 2. 查询库存,并显示的设置写锁(排他锁):SELECT * FROM goods WHERE id = 1 FOR UPDATE 3. 生成订单 4. 去库存,隐示的设置写锁(排他锁):UPDATE goods SET counts = counts – 1 WHERE id = 1 5. commit,释放锁 注意:第二步步可以设置共享锁,不然有可能会造成死锁。 代码: <?php /********************************************** * 抢购模块 * * @author liubin * @date 2018-02-10 * * ab -n 1000 -c 100 http://192.168.16.73/Seckill/buy.php * */

Swoole 中协程的使用注意事项及协程中的异常捕获

让人想犯罪 __ 提交于 2020-08-05 04:47:23
协程使用注意事项 协程内部禁止使用全局变量,以免发生数据错乱; 协程使用 use 关键字引入外部变量到当前作用域禁止使用引用,以免发生数据错乱; 不能使用类静态变量 Class::$array / 全局变量 $_array / 全局对象属性 $object->array / 其他超全局变量 $GLOBALS 等保存协程上下文内容,以免发生数据错乱; 协程之间通讯必须使用通道(Channel); 不能在多个协程间共用一个客户端连接,以免发生数据错乱;可以使用连接池实现; 在 Swoole\Server 中,客户端连接应当在 onWorkerStart 中创建; 在 Swoole\Process 中,客户端连接应当在 Swoole\Process->start 后,子进程的回调函数中创建; 必须在协程内捕获异常,不得跨协程捕获异常; 在 __get / __set 魔术方法中不能有协程切换。 协程中的异常捕获 示例一:协程中使用exit函数抛出 ExitException 异常 function route() { controller(); } function controller() { your_code(); } function your_code() { co::sleep(.001); exit(1); } go(function () { try { route();

Swoole 中涉及的一些基本概念

巧了我就是萌 提交于 2020-08-05 00:13:23
IO(Input/Output,输入输出) 在计算机中,输入 / 输出(即 IO)是指信息处理系统(比如计算机)和外部世界(可以是人或其他信息处理系统)的通信。输入是指系统接收的信号或数据,输出是指从系统发出的数据或信号。由于程序和运行时数据是在内存中驻留,由 CPU 这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就会有 IO 产生。 同步 - 异步 同步和异步是一种消息通信机制 (synchronous communication/asynchronous communication),关注点在于 被调用者返回 和 结果返回 之间的关系, 描述对象是被调用对象的行为。 # 同步(Synchronous):在发出一个同步调用时,在没有得到结果之前,该调用就不返回,等待返回结果才继续执行后续的操作。 # 异步( Asynchronous):发出调用,直接返回,不关心是否返回结果。异步可以通过状态、回调、 通知调用者结果,可以先去执行其他操作,然后等待通知再回来执行刚才没执行完的操作。 阻塞 - 非阻塞 阻塞和非阻塞是一种业务流程处理方式。关注点在于调用发生时 调用者状态 和 被调用者返回结果 之间的关系。 描述的是等待结果时候调用者的状态此时结果可能是同步返回的,也能是异步返回。 # 阻塞( Blocking ):在结果返回之前,当前线程被挂起

Redis面试高级应用解析:缓存穿透、击穿、雪崩

对着背影说爱祢 提交于 2020-07-29 05:02:21
1 背景 像我们去面试一些大公司的时候,就会遇到一些关于缓存的问题。可能很多同学都是接触过,多多少少了解一些,但是如果没有好好记录这些内容,不熟练精通的话,在真正面试的时候,就很难答出来了。 在我们的平常的项目中多多少少都会使用到缓存,因为一些数据我们没有必要每次查询的时候都去查询到数据库。 特别是高 QPS 的系统,每次都去查询数据库,对于你的数据库来说将是灾难。 今天我们不牵涉多级缓存的知识,就把系统使用到的缓存方案,不管是一级还是多级的都统称为缓存,主要是为了讲述使用缓存的时候可能会遇到的一些问题以及一些解决办法。 我们使用缓存时,我们的业务系统大概的调用流程如下图: 当我们查询一条数据时,先去查询缓存,如果缓存有就直接返回,如果没有就去查询数据库,然后返回。这种情况下就可能会出现一些现象。 2 缓存穿透 2.1 什么是缓存穿透 正常情况下,我们去查询数据都是存在。 那么请求去查询一条压根儿数据库中根本就不存在的数据,也就是缓存和数据库都查询不到这条数据,但是请求每次都会打到数据库上面去。 这种查询不存在数据的现象我们称为 缓存穿透 。 2.2 穿透带来的问题 试想一下,如果有黑客会对你的系统进行攻击,拿一个不存在的id 去查询数据,会产生大量的请求到数据库去查询。可能会导致你的数据库由于压力过大而宕掉。 2.3 解决办法 2.3.1 缓存空值 之所以会发生穿透

Swoole 协程使用示例及协程优先级

我的未来我决定 提交于 2020-07-28 17:12:24
示例一: Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); Co\run(function () { go(function() { var_dump(file_get_contents("http://www.baidu.com/")); }); go(function() { Co\System::sleep(1); echo "done\n"; }); }); echo 1; //可以执行 示例二: Co\run(function () { $server = new Co\Http\Server("127.0.0.1", 9502, false); $server->handle('/', function ($request, $response) { $response->end("<h1>Index</h1>"); }); $server->start(); }); echo 1; //不能执行 示例三: Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); go(function() { // 底层优先执行子协程的代码 go(function () { // 子协程挂起,执行上层代码 Co\System::sleep(3.0); go(function () { Co\System::sleep(2

swoole+PHP实现自动取消订单,还原库存等操作

拟墨画扇 提交于 2020-07-28 15:09:11
一、业务场景: 当客户下单在指定的时间内如果没有付款,那我们需要将这笔订单取消掉,比如好的处理方法是运用延时取消,这里我们用到了swoole,运用swoole的异步毫秒定时器不会影响到当前程序的运行,具体参考: https:// wiki.swoole.com/wiki/pa ge/319.html 二、说明, order_status为1时代表客户下单确定,为2时代表客户已付款,为0时代表订单已取消(正是swoole来做的),下面的代表我没有用框架,比较纯的PHP代表方便理解和应用 三、举例说明, 库存表csdn_product_stock产品ID为1的产品库存数量为20,产品ID为2的库存数量为40,然后客户下单一笔产品ID1减10,产品ID2减20,所以库存表只够2次下单,例子中10秒后自动还原库存,如下图: 图解: 1、第一次下完单产品ID1库存从20减到了10,产品ID2库存从40减到了20;2、第二次下完单产品ID的库存为0了,产品ID2的库存也为0了,3、第三次下单时,程序提示Out of stock;4、过了10秒钟(每个订单下单后往后推10秒),客户两次下单,由于没有付款(csdn_order表的order_status为1),产品1和产品2的库存被还原了(csdn_order表的order_status变为0),客户又可以继续下单了 1、所需要sql数据库表

PHP监控进程状态,完成掉线自动重启

China☆狼群 提交于 2020-07-28 11:29:26
1. 利用Shell脚本实现 #!/bin/bash PORT=0 while [ true ];do read -p "please enter the port that you want to minitor:" port if [ $port -gt 65536 ] || [ $port -lt 1 ];then echo 'the port you enter is not correctly' else PORT=$port break fi done while [ true ]; do if [ `netstat -anp 2> /dev/null | grep ${PORT} | wc -l` -gt 0 ] ;then echo 'service is online' else echo 'service is offline' cd /home/eko/share/live_admin/script php ./ws.php & fi sleep 3 done 2. 利用Swoole定时器实现 class Server { const PORT = 8811; public function port() { $shell = "netstat -anp 2>/dev/null | grep ". self::PORT . " | grep LISTEN |