精华内容
下载资源
问答
  • 高并发风控技术解密(上)

    万次阅读 多人点赞 2017-12-13 21:57:51
    本人将就参与的风控建设谈谈风控的技术。(本文来源于内部分享PPT,限于篇幅,一些细节没能交待完整)  风控架构演进  经过1年多风控系统的建设,已经将公司内部风控系统从业务代码为主的风控架构改造为了平台化...

      风控在任何一个公司都是比较神秘的存在,不仅线上很少分享,从安全角度讲也很少对外披露它的架构及设计。本人将就参与的风控建设谈谈风控的技术。(本文来源于本人内部分享PPT,仅从技术角度探讨风控体系建设,不涉及公司内部机密,限于篇幅,一些细节没能交待完整)

    风控架构演进

      经过1年多风控系统的建设,已经将公司内部风控系统从业务代码为主的风控架构改造为了平台化为主的2代架构,进而改造成为动态化及离线数据模型化的2.5代架构,正在向深度学习,在线数据模型的3代架构上演变。

      不得不说,与阿里,腾讯,京东等大厂相比,公司的风控体系还相对比较薄弱,但在有限的资源下将整个体系建设推进到目前的程度已经比较满意。

     技术架构

      首先来看目前风控的技术架构,从业务及架构层面将风控划分为五大体系:分别是存储体系,识别体系,支撑体系,运营体系,数据计算体系。

      其中存储体系包括hbase,mysql,redis,es,hive,实际上都利用了现有的框架或开源项目。

      识别体系包括控制平台(控制系统,批处理系统,决策系统,总线系统),处罚平台(处罚系统),分析平台(规则系统,模型系统), 数据平台(数据系统,运营数据系统)。

      支撑体系主要是指后台配置系统。

      运营体系主要是指风控运营系统,kibana报表系统。

      数据计算体系主要指大数据及离线计算平台及基于其上的数据分析业务。

     

      其调用关系如下图:

     

     业务架构

      其次,来看整个系统的业务架构。目前已经初步具备的

      业务能力有,营销作弊,交易欺诈,登录注册防控,内容防控

      数据模型能力有,用户画像及风险评级,关联反查,风险大盘,各类报表等

      运营能力有,用户预警,商户预警,案件审核,综合信息查询

      并且基于现有的数据,分类整理并形成了自身的数据资产,分别为名单类,用户类,设备类,环境类,位置类。

     

    风控系统的性能表现

      下图是生产环境压测效果,采用12000用户并发压测得到约8w TPS,平均响应时间为141ms,错误率在万分之五。

      其中积累的有效请求达到1.7亿,数据量达8TB

    风控系统建设的难点

      灵活高效的接入:通常只有1周甚至更短时间,业务复杂多样;如何减少发版失误和事故

      极短的响应时间:业务通常只给100ms,最多200ms的超时

      并发吞吐要求高:接入业务较多,调用量大;有的业务用风控抵挡攻击

      大量数据处理:数据量相对较大,如何有效利用;数据查询回溯要求较高

      对抗升级:攻击者不停猜测内部规则;数据如何为对抗服务

      大促稳定性:如何保证调用量增加后不宕机;如何在出问题情况下依然服务

      下篇将针对这些难点一一详细描述如何去解决。

    What else?

      多租户及开放平台服务

      由于公司内部有多个子公司都想通过风控系统去自行控制,因而将数据隔离的多租户就尤为重要了,对于不同的租户而言,使用的是同一个平台同一套系统,但是所有的界面,数据计算,报表都只会看到本租户下的数据,而不能越权到其他租户,多租户本质上是一种权限控制,但是相比权限,其隔离更深更彻底。

      另外,由于风控积累数据及服务已经较多,许多外部系统都想共享风控的数据和服务,将风控的部分业务作为开放平台提供服务也是深化风控改造的重要步骤。


      规则效能分析

      对于规则的设定只能凭经验,规则到底定得好不好也需要有数据衡量,规则效能分析就是用来衡量规则有效性的手段。


      基于神经网络的反欺诈

      基于这篇论文,将每次session的点击序列输入RNN,提供适当风险样本,让其识别风险session《Session Based Fraud Detection》反欺诈这方面可以做得更多,但是神经网络在可解释性方面太差,这种场合被控了申述时毫无反驳理由。不过不失为一个判断依据。


     

      智能运维
      对于线上系统,从智能运维到智能决策,从熔断到自愈,寄往于系统可以做到自动决策,某些问题自动修复。

      TimeWheel算法
      对于风控这种时效要求较高的应用,需要在请求时控制超时。通常,这种控制超时的方式是新起一个线程,通过控制线程的执行时间来控制超时,在大压力时,大量线程会给整个系统的CPU切换带来负担,能否只用一个线程控制所有超时的计算,这样一来,将大大减小线程数量,将CPU负载降低。
      如下是一种称为Timewheel的算法,实际上是模仿TCP发送包之后用来计算超时的算法,试想,如果操作系统底层对每个tcp包都新建一个线程来计时,那操作系统早挂了。
     

      参考资料:
      美团点评业务风控系统构建经验 https://zhuanlan.zhihu.com/p/24936694
      携程在线风控系统架构 https://zhuanlan.zhihu.com/p/30152434
      干货 | 构建风控系统之排坑扫雷(一) https://zhuanlan.zhihu.com/p/24859431
      干货 | 构建风控系统之排坑扫雷(二) https://zhuanlan.zhihu.com/p/25110386
      搭建风控系统道路上踩过的坑(1)-信息采集 https://zhuanlan.zhihu.com/p/31285366
      搭建风控系统道路上踩过的坑(2)-风险分析 https://zhuanlan.zhihu.com/p/31331140
      搭建风控系统道路上踩过的坑(3)-阻断风险 https://zhuanlan.zhihu.com/p/31366714
      搭建风控系统道路上踩过的坑(4)-风险分析 https://zhuanlan.zhihu.com/p/31443357
      氪信资深数据科学家主讲:如何构建基于AI的金融风控系统 | 硬创公开课 https://zhuanlan.zhihu.com/p/26500991
      timewheel算法 http://blog.csdn.net/mindfloating/article/details/8033340
      细说延时任务的处理 http://www.jianshu.com/p/7beebbc61229
    展开全文
  • 1、并发队列的选择 Java的并发包提供了三个常用的并发队列实现,分别是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。 ArrayBlockingQueue是初始容量固定的阻塞队列,我们可以用来作为...

    1、并发队列的选择

    Java的并发包提供了三个常用的并发队列实现,分别是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。

    ArrayBlockingQueue是初始容量固定的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。

    ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。

    LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。

    在请求预处理阶段,由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现。

    2、请求接口的合理设计

    一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。

    通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。

    为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。

    当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。

    但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。推荐:秒杀系统设计的 5 个要点。

    3、高并发下的数据安全

    我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。

    如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。

    我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

    超发的原因

    假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。

    这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景)

    在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

    悲观锁思路

    解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。

    悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

    虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。

    同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。推荐:并发控制--悲观锁和乐观锁详解。

    FIFO队列思路

    那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

    然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。

    或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。

    也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。

    乐观锁思路

    这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。

    实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。推荐:并发控制--悲观锁和乐观锁详解。

    这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

    有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

    展开全文
  • 高并发高性能服务器是如何实现的

    千次阅读 2021-03-03 14:44:42
    总结 高并发技术从最开始的多进程一路演进到当前的事件驱动,计算机技术就像生物一样也在不断演变进化,但不管怎样,了解历史才能更深刻的理解当下。希望这篇文章能对大家理解高并发服务器有所帮助。 ······...

    当在读这篇文章的时候,你有没有想过,服务器是怎么把这篇文章发送给你的呢?

    说简单也简单,不就是一个用户请求吗?服务器根据请求从数据库中捞出这篇文章,然后通过网络发回去。

    说复杂也复杂,服务器是如何并行处理成千上万个用户请求呢?这里面涉及到哪些技术呢?

    这篇文章就来为你解答这个问题。

    多进程

    历史上最早出现也是最简单的一种并行处理多个请求的方法就是利用多进程

    比如在Linux世界中,我们可以使用fork、exec等系统调用创建多个进程,我们可以在父进程中接收用户的连接请求,然后创建子进程去处理用户请求,就像这样:

    这种方法的优点就在于:

    1. 编程简单,非常容易理解

    2. 由于各个进程的地址空间是相互隔离的,因此一个进程崩溃后并不会影响其它进程

    3. 充分利用多核资源

    多进程并行处理的优点很明显,但是缺点同样明显:

    1. 各个进程地址空间相互隔离,这一优点也会变成缺点,那就是进程间要想通信就会变得比较困难,你需要借助进程间通信(IPC,interprocess communications)机制,想一想你现在知道哪些进程间通信机制,然后让你用代码实现呢?显然,进程间通信编程相对复杂,而且性能也是一大问题

    2. 我们知道创建进程开销是比线程要大的,频繁的创建销毁进程无疑会加重系统负担。

    幸好,除了进程,我们还有线程。

    多线程

    不是创建进程开销大吗?不是进程间通信困难吗?这些对于线程来说统统不是问题。

    什么?你还不了解线程,赶紧看看这篇《看完这篇还不懂线程与线程池你来打我》,这里详细讲解了线程这个概念是怎么来的。

    由于线程共享进程地址空间,因此线程间通信天然不需要借助任何通信机制,直接读取内存就好了。

    线程创建销毁的开销也变小了,要知道线程就像寄居蟹一样,房子(地址空间)都是进程的,自己只是一个租客,因此非常的轻量级,创建销毁的开销也非常小。

    我们可以为每个请求创建一个线程,即使一个线程因执行I/O操作——比如读取数据库等——被阻塞暂停运行也不会影响到其它线程,就像这样:

    但线程就是完美的、包治百病的吗,显然,计算机世界从来没有那么简单。

    由于线程共享进程地址空间,这在为线程间通信带来便利的同时也带来了无尽的麻烦。

    正是由于线程间共享地址空间,因此一个线程崩溃会导致整个进程崩溃退出,同时线程间通信简直太简单了,简单到线程间通信只需要直接读取内存就可以了,也简单到出现问题也极其容易,死锁、线程间的同步互斥、等等,这些极容易产生bug,无数程序员宝贵的时间就有相当一部分用来解决多线程带来的无尽问题

    虽然线程也有缺点,但是相比多进程来说,线程更有优势,但想单纯的利用多线程就能解决高并发问题也是不切实际的

    因为虽然线程创建开销相比进程小,但依然也是有开销的,对于动辄数万数十万的链接的高并发服务器来说,创建数万个线程会有性能问题,这包括内存占用、线程间切换,也就是调度的开销。

    因此,我们需要进一步思考。

    Event Loop:事件驱动

    到目前为止,我们提到“并行”二字就会想到进程、线程。但是,并行编程只能依赖这两项技术吗,并不是这样的。

    还有另一项并行技术广泛应用在GUI编程以及服务器编程中,这就是近几年非常流行的事件驱动编程,event-based concurrency。

    大家不要觉得这是一项很难懂的技术,实际上事件驱动编程原理上非常简单。

    这一技术需要两种原料:

    1. event

    2. 处理event的函数,这一函数通常被称为event handler

    剩下的就简单了:

    你只需要安静的等待event到来就好,当event到来之后,检查一下event的类型,并根据该类型找到对应的event处理函数,也就是event handler,然后直接调用该event handler就好了。

    That's it !

    以上就是事件驱动编程的全部内容,是不是很简单!

    从上面的讨论可以看到,我们需要不断的接收event然后处理event,因此我们需要一个循环(用while或者for循环都可以),这个循环被称为Event loop。

    使用伪代码表示就是这样:

    while(true) {
        event = getEvent();
        handler(event);
    }
    

    Event loop中要做的事情其实是非常简单的,只需要等待event的带来,然后调用相应的event处理函数即可。

    注意,这段代码只需要运行在一个线程或者进程中,只需要这一个event loop就可以同时处理多个用户请求。

    有的同学可以依然不明白为什么这样一个event loop可以同时处理多个请求呢?

    原因很简单,对于web服务器来说,处理一个用户请求时大部分时间其实都用在了I/O操作上,像数据库读写、文件读写、网络读写等。当一个请求到来,简单处理之后可能就需要查询数据库等I/O操作,我们知道I/O是非常慢的,当发起I/O后我们大可以不用等待该I/O操作完成就可以继续处理接下来的用户请求

    现在你应该明白了吧,虽然上一个用户请求还没有处理完我们其实就可以处理下一个用户请求了,这也是并行,这种并行就可以用事件驱动编程来处理。

    这就好比餐厅服务员一样,一个服务员不可能一直等上一个顾客下单、上菜、吃饭、买单之后才接待下一个顾客,服务员是怎么做的呢?当一个顾客下完单后直接处理下一个顾客,当顾客吃完饭后会自己回来买单结账的。

    看到了吧,同样是一个服务员也可以同时处理多个顾客,这个服务员就相当于这里的Event loop,即使这个event loop只运行在一个线程(进程)中也可以同时处理多个用户请求。

    相信你已经对事件驱动编程有一个清晰的认知了,那么接下来的问题就是事件驱动、事件驱动,那么这个事件也就是event该怎么获取呢?

    事件来源:IO多路复用

    在《终于明白了,一文彻底理解I/O多路复用》这篇文章中我们知道,在Linux/Unix世界中一切皆文件,而我们的程序都是通过文件描述符来进行I/O操作的,当然对于socket也不例外,那我们该如何同时处理多个文件描述符呢?

    IO多路复用技术正是用来解决这一问题的,通过IO多路复用技术,我们一次可以监控多个文件描述,当某个文件(socket)可读或者可写的时候我们就能得到通知啦。

    这样IO多路复用技术就成了event loop的原材料供应商,源源不断的给我们提供各种event,这样关于event来源的问题就解决了。

    当然关于IO多路复用技术的详细讲解请参见《终于明白了,一文彻底理解I/O多路复用》。

    至此,关于利用事件驱动来实现并发编程的所有问题都解决了吗?event的来源问题解决了,当得到event后调用相应的handler,看上去大功告成了。

    想一想还有没有其它问题?

    问题:阻塞式IO

    现在,我们可以使用一个线程(进程)就能基于事件驱动进行并行编程,再也没有了多线程中让人恼火的各种锁、同步互斥、死锁等问题了。

    但是,计算机科学中从来没有出现过一种能解决所有问题的技术,现在没有,在可预期的将来也不会有。

    那上述方法有什么问题吗?

    不要忘了,我们event loop是运行在一个线程(进程),这虽然解决了多线程问题,但是如果在处理某个event时需要进行IO操作会怎么样呢?

    在《读取文件时,程序经历了什么》一文中,我们讲解了最常用的文件读取在底层是如何实现的,程序员最常用的这种IO方式被称为阻塞式IO,也就是说,当我们进行IO操作,比如读取文件时,如果文件没有读取完成,那么我们的程序(线程)会被阻塞而暂停执行,这在多线程中不是问题,因为操作系统还可以调度其它线程。

    但是在单线程的event loop中是有问题的,原因就在于当我们在event loop中执行阻塞式IO操作时整个线程(event loop)会被暂停运行,这时操作系统将没有其它线程可以调度,因为系统中只有一个event loop在处理用户请求,这样当event loop线程被阻塞暂停运行时所有用户请求都没有办法被处理,你能想象当服务器在处理其它用户请求读取数据库导致你的请求被暂停吗?

    因此,在基于事件驱动编程时有一条注意事项,那就是不允许发起阻塞式IO

    有的同学可能会问,如果不能发起阻塞式IO的话,那么该怎样进行IO操作呢?

    有阻塞式IO,就有非阻塞式IO。

    非阻塞IO

    为克服阻塞式IO所带来的问题,现代操作系统开始提供一种新的发起IO请求的方法,这种方法就是异步IO,对应的,阻塞式IO就是同步IO,关于同步和异步这两个概念可以参考《从小白到高手,你需要理解同步与异步》。

    异步IO时,假设调用aio_read函数(具体的异步IO API请参考具体的操作系统平台),也就是异步读取,当我们调用该函数后可以立即返回,并继续其它事情,虽然此时该文件可能还没有被读取,这样就不会阻塞调用线程了。此外,操作系统还会提供其它方法供调用线程来检测IO操作是否完成。

    就这样,在操作系统的帮助下IO的阻塞调用问题也解决了。

    基于事件编程的难点

    虽然有异步IO来解决event loop可能被阻塞的问题,但是基于事件编程依然是困难的。

    首先,我们提到,event loop是运行在一个线程中的,显然一个线程是没有办法充分利用多核资源的,有的同学可能会说那就创建多个event loop实例不就可以了,这样就有多个event loop线程了,但是这样一来多线程问题又会出现。

    另一点在于编程方面,在《从小白到高手,你需要理解同步与异步》这篇文章中我们讲到过,异步编程需要结合回调函数(关于回调函数请才参考《程序员应如何彻底理解回调函数》),这种编程方式需要把处理逻辑分为两部分,一部分调用方自己处理,另一部分在回调函数中处理,这一编程方式的改变加重了程序员在理解上的负担,基于事件编程的项目后期会很难扩展以及维护。

    那么有没有更好的方法呢?

    要找到更好的方法,我们需要解决问题的本质,那么这个本质问题是什么呢?

    更好的方法

    为什么我们要使用异步这种难以理解的方式编程呢?

    是因为阻塞式编程虽然容易理解但会导致线程被阻塞而暂停运行。

    那么聪明的你一定会问了,有没有一种方法既能结合同步IO的简单理解又不会因同步调用导致线程被阻塞呢?

    答案是肯定的,这就是用户态线程,user level thread,也就是大名鼎鼎的协程,关于协程值得单独拿出一篇文章来讲解,就在下一篇。

    虽然基于事件编程有这样那样的缺点,但是在当今的高性能高并发服务器上基于事件编程方式依然非常流行,但已经不是纯粹的基于单一线程的事件驱动了,而是event loop + multi thread + user level thread。

    关于这一组合,同样值得拿出一篇文章来讲解,我们将在后续文章中详细讨论。

    总结

    高并发技术从最开始的多进程一路演进到当前的事件驱动,计算机技术就像生物一样也在不断演变进化,但不管怎样,了解历史才能更深刻的理解当下。希望这篇文章能对大家理解高并发服务器有所帮助。

    ·················· END ··················

    关注后回复「1024」,获取海量学习资源

    展开全文
  • 12306网站曾被认为是“全球最忙碌的网站”,在应对高并发访问处理方面,曾备受网民诟病。因此记者在第一时间联系到一位对12306改造非常关注的技术架构师,他从技术的角度,用科学论证的方式,指出原因所在,并根据他...

    12306网站曾被认为是“全球最忙碌的网站”,在应对高并发访问处理方面,曾备受网民诟病。因此记者在第一时间联系到一位对12306改造非常关注的技术架构师,他从技术的角度,用科学论证的方式,指出原因所在,并根据他的经验进一步说明12306是如何实现高流量高并发的关键技术,与大家共享。以下为正文:

    前言:

    12306互联网售票系统在2011年下半年开始上线使用,但在2012年春运期间引发无数的争议。在2012年春运后,12306项目承接单位与多家IT公司联系,经过多次论证和POC 测试, 最终引入分布式内存运算数据管理云平台 - Pivotal Gemfire做试点,用以提高12306系统性能,解决“高流量和高并发“的难题。

    高流量高并发是指某特定时间段的海量请求,根据过去的经验法则,高并发是指访问流量是平常流量的 3-5倍;但由于互联网和移动设备apps的普遍化,电商网站的促销模式“11.11“,或是厂商的“饥饿营销“,都会衍生“秒杀“现象。所以过去的经验法则用到12306春运售票系统,往往是远远低于实际的的流量。例如,12306平常一天的PV(page views)值大约是在 2500万到 3000万左右, 在2015年春运高峰日的PV值是297亿,流量增加1000倍,这样海量的请求,假如不能在短时间内动态调整网络带宽或增加服务器数量,就会造成网络阻塞或是服务器性能无法满足要求,甚至使整个系统不稳定。

    12306成长之路

    短短的3年,从2012年春运到2015年春运,12306网站从10亿的PV(page views)值增加到297亿PV值,PV值成长 30倍;网络带宽从 1.5G调整到12G,带宽成长8倍;而12306的售票量从110万增加到564万 ,成长5倍。出票处理能力从 每秒200张提升到 每秒1032张,也是5倍的成长。

    PV值的增加是与放票的次数和可出售的票量有关系,例如,2015年PV值是2014年的2.3倍, 原因是放票次数多了5次“秒杀”,另外增加12% 的售票量。由此可见,互联网流量PV值的增加速度远远高于售票量增加的速度。


    高流量除了代表网络容易造成阻塞以外,系统服务器也会面临更高的CPU负载,在此情况下又该如何应对呢?是选择基于原来系统框架上购买更昂贵的硬件做“scale up“升级呢 ?还是选择购买低成本的x86服务器,进行”可扩展云平台架构“ scale out的改造设计呢?12306互联网购票系统的改造给我们一个很好的案例参考,也让政府单位和企业进一步了解了具体是如何实现的。

    12306改造的关键技术– 建立可伸缩扩展的云应用平台

    2015年12306网站顺利过关,没有“瘫痪”,是值得庆祝的。根据互联网上的新闻,中国铁道科学研究院电子计算技术研究所副所长,12306网站技术负责人朱建生说,为了应对2015年春运售票高峰,该网站采取5项措施:一是利用外部云计算资源分担系统查询业务,可根据高峰期业务量的增长按需及时扩充。二是通过双中心运行的架构,系统内部处理容量扩充一倍,可靠性得到有效保证。三是对系统的互联网接入带宽进行扩容,并可根据流量情况快速调整,保证高峰时段旅客顺畅访问网站。四是防范恶意抢票,通过技术手段屏蔽抢票软件产生的恶意流量,保证网站健康运行,维护互联网售票秩序。五是制定了多套应急预案,以应对突发情况。

    “利用云计算资源“,“按需及时扩充“和”快速调整“,这几个字眼是12306改造的精神,其核心就是要建立一个从下到上全面“可伸缩扩展的云平台”。底层的硬件架构要支持可伸缩扩展,上层的应用系统架构也需要支持可伸缩扩展。

    1. 在过去数年,云计算的基础架构虚拟化已经非常成熟,也日益普遍部署;当网络阻塞时,可以动态增加带宽,当服务器 CPU到达高位时,可以快速从资源池获取虚拟机资源来分摊负荷。 “软件定义的数据中心“ 可以轻易完成这些伸缩性扩展的配置。

    2. 当客户将底层的架构都虚拟化后,网络设备,Web服务器,应用服务器都可以做“伸缩性”的扩展;但遇到一个难点就是“12306的应用系统框架”无法支持可伸缩扩展。原因是关系型数据库Sybase无法支持“应用系统”的伸缩扩展。

    3. 客户在过去数年已经投入大笔经费在IT方面的建设,但“系统框架设计”还是沿用10几年前的三层设计,而且每年都在原来的基础上做不断的升级。当业务不断成长时,数据量也跟着成长,功能越来越多, 但系统性能越来越差。客户该如何选择呢 ?是 scale up? 还是 scale out ?

    为什么选择Pivotal Gemfire构建12306的云应用平台?

    要解决12306春运时高流量高并发的问题,如果单靠硬件升级解决的话,可能需要扩充数十倍的硬件服务器。但在春运以后,又该如何解决服务器过剩的问题呢?

    要真正解决“高流量,高并发“的难题是需要从软件和应用系统层面出发,唯有实现“可扩展的应用云平台架构”,灵活和快速热部署的机制,才是真正解决高并发访问的根本。

    在经过多次论证和POC测试后, 12306 最后选择Pivotal Gemfire作为系统改造的平台,其主要原因如下:

    1. 关联数据节点设计:可以根据客户的业务逻辑特性和数据关联性,将关联性强的数据放置于同一个服务器节点,提高系统性能,避免分布式系统服务器的频繁数据交换。

    2. 将数据移到内存:由于数据是放在内存里面,屏蔽传统数据库频繁访问, CPU与数据库的交互作用,影响服务器性能。内存的数据交换速度远高于磁盘速度上千倍, 极大提高系统性能。

    3. 扩展和伸缩性:以Gemfire构建的应用云平台,是以 x86 PC服务器为主的硬件基础。在保证系统的性能下,此平台可以随着客户业务的成长来任意调配x86服务器的数量,避免以后昂贵的硬件升级带来的困扰。经POC测试结果显示,整个系统性能可随着服务器的数量的增加实现几乎线性的成长。

    4. 数据可靠性:在同个集群里面可以有多个数据节点备份,数据可以自动同步,或是将内存数据持久化到硬盘或是数据库

    5. 跨地域的数据分布或同步 :可以透过“广域网”将指定的 Gemfire集群的内存数据“实时同步”到异地的数据中心。这是属于“应用层”的数据同步异于传统的“数据库”同步。

    6. Pivotal Gemfire使用 x86 PC服务器,其性价比远远高于 Unix 小型机。

    在后续章节,以12306为案例做进一步分析,使用Pivotal Gemfire会给12306带来什么好处。

     

    回顾12306 成长的烦恼

    (1)网络阻塞是个门槛

    网络是进入12306征程的起点,网络带宽快慢往往决定“秒杀“的结果,这在很多电商网站促销时时常发生, 因此12306也无法避免。下面数字是由互联网收集得到的,可能有偏差。但我们尽可能根据这些数目字来解析数年来网络原因发生的问题。

    2012 年:12306 第一次在春运使用, 网络带宽1.5G,可以支持最大的PV值是11,250;根据报导,此系统有10,000人的登陆限制, 假如每人每秒点击一次的话,理论上是可以勉强支持正常的点击量。

    但在购票尖峰日,有上千万的网民第一次上网购票,在无法登陆的情况下, 用户不断刷取首页,或是已登陆者无法得到系统的及时反应,不断点击页面,产生大量的请求,造成网络和系统的高负载,导致崩溃。

    2013年 :宽带增加一倍到达3G频宽,有20万用户登陆的限制,采取10次放票,分散流量,防止买票过度集中;但不幸的是“刷票软件”横行,每秒可以刷票数十次到数百次,高峰期有25万的PV值, 远远超过带宽的最大理论值 22,500 PV。

    2014年 : 宽带增加到达5G,16次放票,有屏蔽刷票软件抢票的设计,有效阻挡90%的点击,但实名制有漏洞,每秒还是有15万次的浏览需求,远超过37,500 PV的的理论带宽承载量。

    2015年 : 12306有21次放票,增加带宽到12G,手机订票(流量小)分担25%的12306售票,解决实名制的问题,可以阻挡95% 刷票软件的点击量,每秒最大有117,800次的浏览请求,此数目字已经很接近理论带宽承载量117,400 PV值。

    根据上述解析, 2012年 – 2014年春运的网络带宽给12306带来很多问题。根据网民的反应,在2015年12306带宽在 12G的情况下,虽然稍微有点卡, 但是大致的反应还是不错的。此轮点与我们的推论是大致符合。


    1. PV值和放票次数是根据互联网的报导。

    2. 2013年与2014年的PV值有10倍的差异, 2014年多了6次放票时段,票的出售量增加90%。但在 2013年,极有可能是大部分的票量集中在少数时段就放完,减少多次的“秒杀“发生。

    3. 2012和2013年, 12306 没有屏蔽抢票软件的设置。在2014年以后,实现了基本的屏蔽功能。 假设此在2014年可以阻挡90%抢票软件的点击, 在2015年可以阻挡 95%的点击。

    4. 在2015年, 假设互联网的平均PV值的数据量是15K byte, 手机上网的PV值是 1K byte,占有25%的流量。

    5. 带宽最大理论PV值/秒 : 1G的带宽是1,000,000,000 bit/second,1 byte = 8 bits.

    2015年平均PV值 =11.5K byte (含手机上网), 2012-2014年的PV值= 15K bytes。

    另外,假设考虑网络IP协议交换有10%的损耗。

    6. 浏览请求最大PV值/秒:假设在每个放票时段,抢票的高峰期是5分钟(含查询, 下单,付款等操作),在高峰期5分钟的下载流量是整个时段下载总量50%;

    再假设有效的浏览下载量是5%上传的请求点击量,换句话说,有95%的点击量被屏蔽,可能是阻挡刷票软件,或是网络阻塞丢包,或是系统忙碌没有反应等等。

    (2)服务器集群性能无法伸缩性扩展

    参考互联网上的资料,12306服务器集群是传统的三层架构设计,如果不考虑最前端的F5负载均衡服务器,它是由 数百部 Web服务器集群和应用服务器集群构成前端,64部数据库小型机集群(用于专门实现并行计算每班车次的余票量),和订单处理服务器集群构成后端。从专业的角度来看,此种框架设计是中规中矩的,国内99%的框架设计师都是如此设计。

    如前述所提,由于Sybase数据库的原因,此种设计无法做伸缩性的扩展。因此,12306要进一步提高性能就面临很大的抉择。在此,先了解服务器集群性能与实际需求之间有多少差距。

    回顾2012年到2015年,12306系统在这3年内有很大的变化。

    1. 2012年春运 :根据互联网上的信息,2012年 12306设计的售票指标是在100万张票的销售,这完全低估了互联网网民的实际需求,在尖峰日,有上千万人登陆。网络带宽,Web服务器集群,应用服务器集群,余票查询/计算集群,到订单处理集群, 这些设备性能完全无法应付高流量高并发的请求。由于极大的低估互联网的需求,造成12306整个系统不稳定。

    在12306系统,余票查询/计算子系统是最复杂的, 最耗损服务器CPU资源。在整个客票系统里,有数十条行车路线,有3000多个车次(G,D,K,Z,C,..),5000多个火车站,不同的席次(硬座,硬卧, 软座, 软卧, etc),座位等级(商务, 一等, 二等),和车票等级(一般,军人, 学生,残障,小孩)等因素,将这些参数换算成数学模型,那可是有数千亿条的排列组合。

    2012年的余票计算系统实际处理能力据估计不会超过 300-400 TPS,而有效的余票查询请求远远高于3000 QPS (query per second)。另外,系统每隔10分钟更新车次的余票,这些余票信息是没有参考价值,因为在10分钟里已经售出数十万张票。如果要满足余票计算的需求达到至少 3000 TPS, 那么12306 需要再增加6倍的服务器,即将近 400部小型机(原有系统有64部服务器)。

    2. 2013年春运:在2012年6月进行第一步余票查询/计算改造,使用Pivotal Gemfire改造后的结果是每秒至少支持 10,000 TPS 以上,此数目字已经足够应付高并发的需求,因此在2013年春运余票查询顺利过关。 由于集群计算能力大增,余票更新缩短到每隔2分钟提供最及时的信息。

    在余票查询瓶颈移除后,订单处理服务器的瓶颈就出现在订单排队,网民必须等待数十秒到数十分钟才会得到订单的确认。订单的请求累积高达数千甚至数万个以上,估计当时订单处理服务器的处理能力不超过 200-300 TPS。

    3. 2014年:在2013年后,进行“订单分库二级查询”处理,将订单生成与订单查询分开处理。因为订单查询的数量远远超过订单生成的数量。因此, 12306将查询订单的热点数据放在Gemfire集群, 将历史订单数据放在Hadoop集群。如此设计,不但提高订单查询的功能数十倍,而且订单生成的性能至少也提高5倍以上(使用原有服务器)。

    4. 2015年:进一步使用Gemfire优化整个 12306系统,总共建立5个Gemfire集群。另外建立三个数据中心(高铁公司, 铁科院,和阿里云),在阿里云上部署数百个虚拟机(有 Web服务器,应用服务器,和余票查询服务器集群)分流余票查询75%的流量,因为余票查询流量占据12306整体流量的90%。


    在12306系统,余票计算的结果是放在“数据缓存应用服务器”,在2012年每隔10分钟更新每班车次的余票结果。如果新请求与上次更新的时间间隔低于10分钟,数据缓存系统就直接返回上次计算的结果。而在10分钟左右再重新计算新的请求。在10分钟的间隔,服务器集群需要计算3000多个车次的余票结果。自2013年以后,12306系统每隔2分钟更新车次余票结果。

    使用Gemfire改造后12306的现状和启示

    2015年的春运购票期间12306系统的表现是很令人瞩目的,它的效果和影响总结如下:

    1. 提供“高并发,低延迟”的解决方案,一劳永逸,不用烦恼后续硬件升级的问题

    2. 通过GemFire多集群技术,实现多重的高可用性,确保高峰压力下和系统异常的情况下保证业务的持续性。

    3. 构建一个可扩展的云应用平台架构,灵活和快速热部署的机制,为未来混合云的部署打基础。

    4. 余票查询集群性能提升 :

    使用数十部 x86服务器 (或是上百部虚拟机)可以达到 10,000 TPS以上,提升原来系统性能达30倍以上。原来的系统是使用64部Unix 小型机。

    余票信息更新从原来10分钟缩短到2分钟,使信息更有参考价值。

    5. 12306“订单分库二级查询”子系统:

    将订单生成与订单查询分库处理,订单查询性能提高50倍, 订单生成性能提高4-5倍。

    将热点订单放在Gemfire集群,将历史订单数据放在Hadoop集群。这是快数据和大数据结合的完美案例。

    6. 混合云的应用:

    使用Gemfire改造后的分布式系统,极易分散部署到不同的数据中心

    例如,余票查询子系统可以独立于原来的大系统部署到公有云上,同时也可以再将此子系统一分为二,将另一部分服务器部署在私有云的数据中心。即按业务需求随时部署所需要的资源,来解决高并发的难题。


    展开全文
  • 当用户点击去结算时,返回订单页面 cart/cart.html <form method="post" action="{% url 'order:place' %}"> {% for sku in skus %} ...ul class="cart_list_td clearfix">...input type...
  • 在现代的互联网应用设计当中,通常会提到应用系统需要达到高性能,高可用和高并发这三“高”目标,其中这三个概念既有联系又有区别。 高性能 首先高性能是指应用系统对于客户端请求的处理速度快,响应时间短,对于...
  • 在过往的面试中,如果候选人做过高并发的项目,我通常会让对方谈谈对于高并发的理解,但是能系统性地回答好此问题的人并不多,大概分成这样几类: 1、对数据化的指标没有概念:不清楚选择什么样的指标来衡量...
  • 写在前面 工作了3年的小菜同学,平时在公司只是做些CRUD的常规工作,这次,出去面试被...并发编程的难点 并发编程一直是很让人头疼的问题,因为多线程环境下不太好定位问题,它不像一般的业务代码那样打个断点,deb...
  • Java面试题大全(2020版)

    万次阅读 多人点赞 2019-11-26 11:59:06
    BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。 NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路...
  • 在过往的面试中,如果候选人做过高并发的项目,我通常会让对方谈谈对于高并发的理解,但是能系统性地回答好此问题的人并不多,大概分成这样几类: 1、对数据化的指标没有概念 不清楚选择什么样的指标来衡量高并发...
  • 在优酷创立之初(2006年),老大古永锵就对优酷的技术平台定下了基调,那就是“快者为王”。后来的事实证明,这个原则帮助优酷在众多平台中脱颖而出,受到了终端用户的普遍欢迎。 因此,作为优酷平台的前研发
  • 浅析分布式、集群及高并发

    千次阅读 2019-03-09 14:54:53
    要应对大并发,要实现可用,既需要分布式,也离不开集群。 分布式    将一个大的系统划分为多个业务模块,业务模块分别部署到不同的机器上,各个业务模块之间通过接口进行数据交互。区别分...
  • 目录业务场景项目难点1.发券并发问题2.支付宝技术对接3.服务器升级繁琐4.线上并发问题解决方案1.发券并发问题2.redis队列3.线程池异步4.多实例负载均衡项目收获 业务场景 上上周新启动了一个项目,是和支付宝合作的...
  • 点击上方蓝色小字,关注“涛哥聊Python”重磅干货,第一时间送达作者 |骆俊武来源 | IT人的职场进阶高并发,几乎是每个程序员都想拥有的经验。原因很简单:随着流量变大,会遇到各种各...
  • 全面认识高并发

    2020-09-14 12:04:26
    高并发,几乎是每个程序员都想拥有的经验。原因很简单:随着流量变大,会遇到各种各样的技术问题,比如接口响应超时、CPU load升高、GC频繁、死锁、大数据量存储等等,这些问题能推动我们在技术深度上不断精进。 在...
  • 秒杀系统的难点 友好的用户体验 用户不能接受破窗的体验,例如:系统超时、系统错误的提示,或者直接 404 页面 瞬时高并发流量的挑战 木桶短板理论,整个系统的瓶颈往往都在 DB,如何设计出高并发、高可用系统?...
  • 高可用,高并发,高性能 高并发(High Concurrency) 是互联网分布式系统架构设计中必须考虑的因素之一, 它通常是指,通过设计保证系统能够同时并行处理很多请求。 高并发相关常用的一些指标有响应时间(Response ...
  • 高并发,几乎是每个程序员都想拥有的经验。原因很简单:随着流量变大,会遇到各种各样的技术问题,比如接口响应超时、CPU load升高、GC频繁、死锁、大数据量存储等等,这些问题能推动我们在技术深度上不断精进。
  • 主要讲解可用的互联网交易系统架构,包括双十一、支付宝&微博红包技术架构,以及微信红包的技术架构,希望能给各位提供价值。   概述 话说每逢双十一节或春节等节假日,对大家来讲是最欢乐的日子,可以...
  • 分布式、多线程、高并发都不懂,拿什么去跳槽

    万次阅读 多人点赞 2019-10-09 01:03:16
    当提起这三个词的时候,是不是很多人都认为分布式=高并发=多线程?当面试官问到高并发系统可以采用哪些手段来解决,或者被问到分布式系统如何解决一致性的问题,是不是一脸懵逼?确...
  • 难点:如何高效地处理“竞争”。 2 开发环境 InteliJ IDEA + Maven + Tomcat8 + JDK8 3 工程创建 新建一个 Maven 工程,并完善相应的目录结构。 pom 文件的依赖可以分为 4 部分: 日志。使用的是 slf4j + logback 的...
  • 曾经有太多人问过我这样一个问题: 如何搭建一个优酷这样的视频网站,与普通的图文网站差异大吗,这里面会有哪些坑需要...在优酷创立之初(2006年),老大古永锵就对优酷的技术平台定下了基调,那就是“快者为王”...
  • 接着继续讲,接下来主要介绍交易总体设计的技术要点设计,对于电商中台来说,交易系统是核心中的核心,一开始就需要围绕性能,可用,和扩展三个方面来重点设计。本篇主要介绍性能设计。 对于性能的定义,...
  • 如此大规模、高峰值的业务需要,背后需要怎样的技术支撑?百亿级别的红包规模,如何保证并发性能与资金安全? 背景介绍 2017年1月28日,正月初一,…   每年节假日,微信红包的收发数量都会暴涨,尤以除夕为最...
  • 这里面涉及到哪些技术呢? 多进程 历史上最早出现也是最简单的一种并处处理多个请求的方法就是利用多进程。 比如在Linux世界中,我们可以使用fork、exec等方法创建多个进程,我们可以在父进程中接收用户的链接请求,...
  • 背景 可用性(Availability)和一致性(Consistency)是分布式系统的基本问题,先有著名的CAP理论定义过...在大数据场景下,分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库满足数...
  • 来源:InfoQ 作者:方乐明 背景介绍 ...面对挑战,微信红包在分析了业界“秒杀”系统解决方案的基础上,采用了SET化、请求排队串行化、双维度分库表等设计,形成了独特的高并发、资金安全系统解决方

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,343
精华内容 8,137
关键字:

高并发网站技术难点