[Design] 后端程序高并发与异步

既然涉及到高并发这个概念,就少不了先谈这么几个概念,并发数、多进程、多线程、协程、负载均衡。

操作系统上讲的并发是操作系统上有几个程序在同时执行,单核CPU在微观上是由CPU调度执行,非同时执行,多核CPU在微观上才是真正的并行。

互联网产品的并发通常是指并发连接数,用户同时访问数量,哪些因素能影响到并发能力,既有编程模型,也有服务器负载能力。

PHP 依赖多进程解决并发数,是最原始和耗费资源的一种方式。

以 8G 内存服务器为例,一个PHP进程占用20M内存,最多也就开几百个进程,假如任务比较耗时且并发很高,那么新请求很快就得不到响应了。

对于并发访问 PHP 提供 curl_multi_* 系列函数,纯接口的并发调用就不需要自己写多进程、多线程程序了。

Java是多线程模型,每个进程可以创建多个线程,线程使用进程的上下文,每个线程只需要小部分运行资源,所以比进程轻量许多。

进程和线程都是依赖操作系统的系统调用支持的,所以这部分调度开销是难以避免的。

协程是程序级的调度模型,最轻量,好比框架级实现像操作系统一样能自由对程序中断、调度,比如借助于 C 的 setjmp 系列函数就能做到中断。

不管编程模型多先进,单机总会达到并发上限,要想突破限制就必须引入负载均衡,通过横向扩展解决问题。

上面所提到的编程模型优劣,本质上还都是语言层面的,短期内并不能真正解决问题,下面就延伸出从应用层面的考虑:

为什么高性能都离不开异步,比如 Swoole ? 目的就是提升响应时间,提高Qps。

在我们通常的业务开发过程中,逻辑代码一般是同步阻塞模式,一方面它容易理解,另一方面也方便进行一些测试。

这些优势再加上大部分业务场景对并发并没有较高的要求,所以是可以接受的。

但是对于一个大的网站,以及对响应速度和并发要求高的场景,这时候就需要做些优化了,尽量把阻塞操作给异步化。

通过消息队列来做异步的场景:

  加速响应:比如注册后的提醒邮件,注册操作成功后将发消息交给队列,直接返回信息给用户,写入队列的速度非常快,然后由订阅的异步任务处理邮件发送。

  应用解耦:比如用户发帖之后要给他的粉丝推送帖子,这时候实时性要求并不高,可以将新帖的消息写入队列,然后由队列处理程序操作。

  流量削峰:比如秒杀活动,我们不需要实时处理一些购买逻辑,只要将用户请求写入消息队列,长度达到限制就提示用户已结束,后续程序再对队列内容处理。

  日志收集:日志一般都需要进行写磁盘操作,大访问量会对 I/O 造成压力,降低程序性能;此时可以将日志写入消息队列,由处理程序订阅该队列进行消费。

  广播聊天:用户通过订阅频道来获得最新发布的消息。

实例演示

<?php
/**
 * Pub.php
 *
 * @author farwish
 */

// 1.连接并选择数据库
$redis = new \Redis();

$bool = $redis->connect(‘127.0.0.1‘, 6379, 2.5, null, 100);

if (! $bool) {
    die(‘连接失败‘);
}

$bool = $redis->select(0);

// 模拟将一个任务放置队列中, 并发布
//$phone = 13199999999;
//$redis->lpush(‘sms-signin‘, $phone);
//$redis->publish(‘sms-signin‘, $phone);
//

// 2.模拟生成批量数据

for ($i = 0; $i < 10; $i++) {
    $phone = mt_rand(10000000000, 99999999999);

    echo $phone . PHP_EOL;

    // 模拟每个任务耗时100ms, 使用 publish 代替方案,在 subscribe 中处理
    //echo $phone . PHP_EOL;
    //usleep(100000);

    $redis->publish(‘signin-sms‘, $phone);
}

如果不将消息写入队列,而是每次都自己执行,响应时间很长,用户体验不好。

通过订阅程序异步处理任务,用户无感知,并且体验会很好。

<?php
/**
 * Sub.php
 *
 * @author farwish
 */

// 1.连接并选择数据库
$redis = new \Redis();

$bool= $redis->connect(‘127.0.0.1‘, 6379, 2.5, null, 100);

if (! $bool) {
    die(‘连接失败‘);
}
// * 阻止 redis read timeout
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

// 2.订阅耗时任务并处理
// 如果这个订阅的任务比较重要,将对可用性有要求,日志收集等可以采用。
$redis->subscribe([‘signin-sms‘, ‘signin-mail‘, ‘crawler-task-1‘], function($redis, $chan, $msg) {
    switch ($chan) {
        case ‘signin-sms‘:

            // 耗时1s, 发送并记录数据库
            sleep(1);
            echo "{$msg} 发注册短信\n";

            break;

        case ‘signin-mail‘:

            break;

        case ‘crawler-task-1‘:
            // 其他耗时任务,通过 $msg 传递参数来执行
            break;
    }
});

其它常见的消息队列产品有 RabbitMQ、ZeroMQ、ActiveMQ、Kafka ..

Link:https://www.cnblogs.com/farwish/p/9513100.html

原文地址:https://www.cnblogs.com/farwish/p/9513100.html

时间: 2024-11-10 16:02:03

[Design] 后端程序高并发与异步的相关文章

nginx、swoole高并发原理初探

原文:https://segmentfault.com/a/1190000007614502 一.阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 1.同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步当一个同步调用发出去后,调用者要一直等待调用结果的通知后,才能进行后续的执行 异步:当一个异步调用发出去后,调用者不能立即得到调用结果的返回. 异步调用,要想获得结果,一般有两种方式:1.主动轮询异步调用的结果;2.被调用

单线程、高并发的运行时环境

浅谈Node.js单线程模型 Node.js采用 事件驱动 和 异步I/O 的方式,实现了一个单线程.高并发的运行时环境,而单线程就意味着同一时间只能做一件事,那么Node.js如何利用单线程来实现高并发和异步I/O?本文将围绕这个问题来探讨Node.js的单线程模型: 1.高并发 一般来说,高并发的解决方案就是多线程模型,服务器为每个客户端请求分配一个线程,使用同步I/O,系统通过线程切换来弥补同步I/O调用的时间开销,比如Apache就是这种策略,由于I/O一般都是耗时操作,因此这种策略很难

面试中的nginx高可用高并发!

本文转自:91博客:原文地址:http://www.9191boke.com/439923471.html 面试题: nginx高可用?nginx 是如何实现并发的?为什么nginx不使用多线程?nginx常见的优化手段有哪些?502错误可能原因有哪些? 面试官心理分析 主要是看应聘人员的对NGINX的基本原理是否熟悉,因为大多数运维人员多多少少都懂点NGINX,但是真正其明白原理的可能少之又少.明白其原理,才能做优化,否则只能照样搬样,出了问题也无从下手. 懂皮毛的人,一般会做个 Web Se

Java异步NIO框架Netty实现高性能高并发

1. 背景 1.1. 惊人的性能数据 近期一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用.相比于传统基于Java序列化+BIO(同步堵塞IO)的通信框架.性能提升了8倍多. 其实,我对这个数据并不感到吃惊,依据我5年多的NIO编程经验.通过选择合适的NIO框架,加上高性能的压缩二进制编解码技术,精心的设计Reactor线程模型,达到上述性能指标是全然有可能的. 以下我们就一起来看下Ne

配置开发支持高并发TCP连接的Linux应用程序全攻略

http://blog.chinaunix.net/uid-20733992-id-3447120.html http://blog.chinaunix.net/space.php?uid=16480950&do=blog&id=103598 原文见:http://www.cppblog.com/flashboy/articles/47012.html1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到

每一个程序员都应该知道的高并发处理技巧、创业公司如何解决高并发问题、互联网高并发问题解决思路、caoz大神多年经验总结分享

本文来源于caoz梦呓公众号高并发专辑,以图形化.松耦合的方式,对互联网高并发问题做了详细解读与分析,"技术在短期内被高估,而在长期中又被低估",而不同的场景和人员成本又导致了巨头的方案可能并不适合创业公司,那么如何保证高并发问题不成为创业路上的拦路虎,是每一个全栈工程师.资深系统工程师.有理想的程序员必备的技能,希望本文助您寻找属于自己的"成金之路",发亮发光. 目录: 场景及解决方法解读 认识负载 数据跟踪 脑图.caoz大神公众号分享 参考资料 秉承知其然及其

【转】大话程序猿眼里的高并发

原文: http://blog.thankbabe.com/2016/04/01/high-concurrency/ 大话程序猿眼里的高并发 2016-04-01 YYQ 高并发 高并发  负载均衡  并发  锁  事务  集群 高并发是指在同一个时间点,有很多用户同时的访问URL地址,比如:淘宝的双11,双12,就会产生高并发,如贴吧的爆吧,就是恶意的高并发请求,也就是DDOS攻击,再屌丝点的说法就像玩撸啊撸被ADC暴击了一样,那伤害你懂得(如果你看懂了,这个说法说明是正在奔向人生巅峰的屌丝.

大话程序猿眼里的高并发

高并发是指在同一个时间点,有很多用户同时的访问URL地址,比如:淘宝的双11,双12,就会产生高并发,如贴吧的爆吧,就是恶意的高并发请求,也就是DDOS攻击,再屌丝点的说法就像玩撸啊撸被ADC暴击了一样,那伤害你懂得(如果你看懂了,这个说法说明是正在奔向人生巅峰的屌丝. 高并发会来带的后果 服务端: 导致站点服务器/DB服务器资源被占满崩溃,数据的存储和更新结果和理想的设计是不一样的,比如:出现重复的数据记录,多次添加了用户积分等. 用户角度: 尼玛,这么卡,老子来参加活动的,刷新了还是这样,垃

程序猿眼中的高并发

简单理解下高并发: 高并发是指在同一个时间点,有很多用户同时的访问URL地址,比如:淘宝的双11,双12,就会产生高并发,如贴吧的爆吧,就是恶意的高并发请求,也就是DDOS攻击,再屌丝点的说法就像玩撸啊撸被ADC暴击了一样,那伤害你懂得(如果你看懂了,这个说法说明是正在奔向人生巅峰的屌丝. 高并发会来带的后果 服务端: 导致站点服务器/DB服务器资源被占满崩溃,数据的存储和更新结果和理想的设计是不一样的,比如:出现重复的数据记录,多次添加了用户积分等. 用户角度: 尼玛,这么卡,老子来参加活动的