精华内容
参与话题
问答
  • 什么是高并发

    千次阅读 多人点赞 2019-08-05 20:51:29
    什么是高并发高并发(High Concurrency)是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问收到大量请 求(例如:12306的抢票情况;天猫双十一活动)。该情况的...

    什么是高并发?

    高并发(High Concurrency)是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问收到大量请

    求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。

    高并发的处理指标

    高并发相关常用的一些指标有:
    1.响应时间(Response Time)

    响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间

    2.吞吐量(Throughput)

    吞吐量:单位时间内处理的请求数量。

    3.每秒查询率QPS(Query Per Second)

    QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。

    4.并发用户数

    并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

    高并发和多线程的关系和区别?

    “高并发和多线程”总是被一起提起,给人感觉两者好像相等,实则 高并发 ≠ 多线程

    1.多线程

    多线程是java的特性,因为现在cpu都是多核多线程的,可以同时执行几个任务,为了提高jvm的执行效率,java提供了这种多线程的机制,以增强数据

    处理效率。多线程对应的是cpu,高并发对应的是访问请求,可以用单线程处理所有访问请求,也可以用多线程同时处理访问请求。

    在过去单CPU时代,单任务在一个时间点只能执行单一程序。之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程。虽然并不是真

    正意义上的“同一时间点”,而是多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一

    定的时间片运行。

    再后来发展到多线程技术,使得在一个程序内部能拥有多个线程并行执行。一个线程的执行可以被认为是一个CPU在执行该程序。当一个程序运行在多

    线程下,就好像有多个CPU在同时执行该程序。

    总之,多线程即可以这么理解:多线程是处理高并发的一种编程方法,即并发需要用多线程实现。

    2.高并发

    高并发不是JAVA的专有的东西,是语言无关的广义的,为提供更好互联网服务而提出的概念。

    典型的场景,例如:12306抢火车票,天猫双十一秒杀活动等。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操

    作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等

    如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、

    数据库优化等……而多线程只是其中解决方法之一。

    展开全文
  • 高并发解决方案】高并发解决方案汇总

    万次阅读 多人点赞 2018-05-18 17:06:16
    什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用户...

    【高并发解决方案】1、高并发解决方案汇总

    一、对于被频繁调用,更新频率较低的页面,可以采用HTML静态化技术

    二、图片服务器分离

    三、数据库集群和库表散列

          mysql主从。m-m-s-s-s...(2个主,多个从。多个从使用负载均衡。主写入数据,从读取数据)

    四、缓存。众多的缓存框架

    五、负载均衡。nginx,lvs,F5

    六、搜索用单独的服务器,搜索框架

    七、使用MQ服务器

    【高并发解决方案】2、集群概述

    1.什么是集群

    集群是一组协同工作的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台。在客户端看来,一个集群就象是一个服务实体,但 事实上集群由一组服务实体组成。

    2.集群的特性 
    与单一服务实体相比较,集群提供了以下两个关键特性: 
    1.可扩展性--集群的性能不限于单一的服务实体,新的服 务实体可以动态地加入到集群,从而增强集群的性能。 
    2. 高可用性--集群通过服务实体冗余使客户端免于轻易遇到out of service的警告。在集群中,同样的服务可以由多个服务实体提供。如果一个服务实体失败了,另一个服务实体会接管失败的服务实体。集群提供的从一个出 错的服务实体恢复到另一个服务实体的功能增强了应用的可用性。 
    为了具有可扩展性和高可用性特点,集群的必须具备以下两大能力: 
    (1) 负 载均衡--负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。 
    (2) 错误恢复--由于某种原因,执行某个任务的资源出现故障,另一服 务实体中执行同一任务的资源接着完成任务。这种由于一个实体中的资源不能工作,另一个实体中的资源透明的继续完成任务的过程叫错误恢复。 
    负载均衡 和错误恢复都要求各服务实体中有执行同一任务的资源存在,而且对于同一任务的各个资源来说,执行任务所需的信息视图(信息上下文)必须是一样的。

     

    3 集群的分类 
    集群主要分成三大类:高可用集群(High Availability Cluster/HA), 负载均衡集群(Load Balance Cluster),高性能计算集群(High Performance Computing Cluster/HPC) 
    (1) 高可用集群(High Availability Cluster/HA):一般是指当集群中有某个节点失效的情况下,其上的任务会自动转移到其他正常的节点上。还指可以将集群中的某节点进行离线维护再上线,该过程并不影响整个集群的运行。常见的就是2个节点做 成的HA集群,有很多通俗的不科学的名称,比如"双机热备", "双机互备", "双机",高可用集群解决的是保障用户的应用程序持续对外提供服 务的能力。 
    (2) 负载均衡集群(Load Balance Cluster):负载均衡集群运行时一般通过一个或者多个前端负载均衡器将工作负载分发到后端的一组服务器上,从而达到将工作负载分发。这样的计算机集群有时也被称为服务器群(Server Farm)。一般web服务器集群、数据库集群 和应用服务器集群都属于这种类型。这种集群可以在接到请求时,检查接受请求较少,不繁忙的服务器,并把请求转到这些服务器 上。从检查其他服务器状态这一点上 看,负载均衡和容错集群很接近,不同之处是数量上更多。 
    (3) 高性能计算集群(High Performance Computing Cluster/HPC):高性能计算集群采用将计算任务分配到集群的不同计算节点而提高计算能力,因而主要应用在科学计算领域。这类集群致力于提供单个计算机所不能提供的强大的计算能力

    【高并发解决方案】3、消息队列软件产品大比拼

    转自:http://www.oschina.net/news/17973/message-queue-shootout

    我花了一周的时间评估比较了一下各种消息队列产品,非常的有趣。我做这个事的动机是因为一个客户有一个很高性能需求。他们的消息信息突破了1百万个并发。目前他们使用的是SQL server,并不理想,我建议他们使用消息队列服务器。

    为了对一些相似的候选产品获得一个全面的但是粗浅的性能上的了解,我们它们放在一起做了个测试。我让每个消息产品各发送和接受1百万千条1K的消 息。测试准备的有些仓促,我并没有修改任何的配置,只是快速的看了一下它们的安装文档,安装好每种软件,然后就让它们做这些最简单的收发信息的操作。所以 这是一次真正的“开箱即装即用”的性能表现。我完全理解,这对那些初始配置十分保守的消息队列产品将会是个惩罚。

    候选产品有:

    • MSMQ.
      这是微软的产品里唯一被认为有价值的东西。对我的客户来说,如果MSMQ能证明可以应对这种任务,他们将选择使用它。关键是这个东西并不复杂,除了接收和 发送,没有别的;它有一些硬性限制,比如最大消息体积是4MB。然而,通过和一些像MassTransit 或 NServiceBus这样的软件的连接,它完全可以解决这些问题。
    • ActiveMQ.
      Java世界的中坚力量。它有很长的历史,而且被广泛的使用。它还是跨平台的,给那些非微软平台的产品提供了一个天然的集成接入点。然而,它只有跑过了MSMQ才有可能被考虑。
    • RabbitMQ.
      我听说了很多关于这个用Erlang写成的消息中间件的优秀的特性。它支持开放的高级消息队列协议 (AMQP,Advanced Message Queuing Protocol),从根本上避免了生产厂商的封闭,使用任何语言的各种客户都可以从中受益。这种协议提供了相当复杂的消息传输模式,所以基本上不需要 MassTransit 或 NServiceBus 的配合。它还具有“企业级”的适应性和稳定性。这些东西对我的客户来说十分的有吸引力。
    • ZeroMQ.
      我在研究AMQP时从发现了这个产品。开发这个产品的公司是AMQP集团的一部分,并且还有一个叫做OpenAMQ的产品。然而,他们却戏剧性的从AMQP分离的出去,并抱怨说这这个产品迷失了方向、变的越来越复杂。你可以到这里阅 读Dear John的关于此事的文章。ZeroMQ具有一个独特的非中间件的模式,也就是说,跟其它几个接受测试的产品不同,你不需要安装和运行一个消息服务器,或 中间件。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。非常有趣的是,他们也同样使用这 方式在任何利用ZeroMQ进行强大的进程内通信的语言里创建Erlang风格的这种执行角色。

    把这四个MQ产品装上、跑起来是一个很有趣的工作。当你需要安装一个非Windows平台的产品时,下一定的功夫那是必须的。ActiveMQ需要 在目标机器上安装Java,RabbitMQ需要Erlang环境。安装这两个产品都没有遇到麻烦,但我想这是否给系统的维护增加了一层任务。如果这个中 的一个被选中,我需要让系统维护的人去理解和维护他们以前不熟悉的运行库。ActiveMQ,
    RabbitMQ 和 MSMQ 都需要启动服务进程,这些都可以监控和配置,另外一个就有问题了。

    ZeroMQ,它没有中间件架构,不需要任何服务进程和运行时。事实上,你的应用程序端点扮演了这个服务角色。这让部署起来非常简单,但担心的是, 你没有地方可以观察它是否有问题出现。就目前我知道的,ZeroMQ仅提供非持久性的队列。你可以在需要的地方实现自己的审计和数据恢复功能。老实说,我 甚至不确信是否该把它列在此次测试中,它的运行原理和其它几种差别太大了。

    我就不瞎扯了,下面是测试结果。显示的是发送和接受的每秒钟的消息数。整个过程共产生1百万条1K的消息。测试的执行是在一个Windows Vista上进行的。

    Message Queue

    就像你看到的,ZeroMQ和其它的不是一个级别。它的性能惊人的高。公平的说,ZeroMQ跟其它几个比起来像头巨兽,尽管这样,结论很清楚:如果你希望一个应用程序发送消息越快越好,你选择ZeroMQ。当你不太在意偶然会丢失某些消息的情况下更有价值。

    老实讲,我更希望使用Rabbit。但这种事情是应该做更多的测试,你最终会有一个最爱,我所听到的、读到的各种关于Rabbit的事情让我觉得它应该是最佳选择。但使用这个测试结果,我很难说服他们不去使用MSMQ。

    如果你想自己跑一下这些测试,我的测试代码都放在了GitHub上。我很感兴趣(但不是非常非常感兴趣)想知道如何优化这些测试,所以,如果你能做到一个更好的测试结果,请告诉我。谢谢。


    【高并发解决方案】如何设计一个秒杀系统

    什么是秒杀

    秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用户前来抢购,并且会在约定的时间点同时在秒杀页面进行抢购。

    秒杀系统场景特点

    • 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增。
    • 秒杀一般是访问请求数量远远大于库存数量,只有少部分用户能够秒杀成功。
    • 秒杀业务流程比较简单,一般就是下订单减库存。

    秒杀架构设计理念

    限流: 鉴于只有少部分用户能够秒杀成功,所以要限制大部分流量,只允许少部分流量进入服务后端。

    削峰:对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。高峰值流量是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有利用缓存和消息中间件等技术。

    异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。

    内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。

    可拓展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。

    架构方案

    一般秒杀系统架构

    这里写图片描述

    设计思路

    将请求拦截在系统上游,降低下游压力:秒杀系统特点是并发量极大,但实际秒杀成功的请求数量却很少,所以如果不在前端拦截很可能造成数据库读写锁冲突,甚至导致死锁,最终请求超时。 
    充分利用缓存:利用缓存可极大提高系统读写速度。 
    消息队列:消息队列可以削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理。

    前端方案

    浏览器端(js):

    页面静态化:将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。 
    禁止重复提交:用户提交之后按钮置灰,禁止重复提交 
    用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流

    后端方案

    服务端控制器层(网关层)

    限制uid(UserID)访问频率:我们上面拦截了浏览器访问的请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率。

    服务层

    上面只拦截了一部分访问请求,当秒杀的用户量很大时,即使每个用户只有一个请求,到服务层的请求数量还是很大。比如我们有100W用户同时抢100台手机,服务层并发请求压力至少为100W。

    1. 采用消息队列缓存请求:既然服务层知道库存只有100台手机,那完全没有必要把100W个请求都传递到数据库啊,那么可以先把这些请求都写到消息队列缓存一下,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。

    2. 利用缓存应对读请求:对类似于12306等购票业务,是典型的读多写少业务,大部分请求是查询请求,所以可以利用缓存分担数据库压力。

    3. 利用缓存应对写请求:缓存也是可以应对写请求的,比如我们就可以把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。

    数据库层

    数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧。

    案例:利用消息中间件和缓存实现简单的秒杀系统

    Redis是一个分布式缓存系统,支持多种数据结构,我们可以利用Redis轻松实现一个强大的秒杀系统。

    我们可以采用Redis 最简单的key-value数据结构,用一个原子类型的变量值(AtomicInteger)作为key,把用户id作为value,库存数量便是原子变量的最大值。对于每个用户的秒杀,我们使用 RPUSH key value插入秒杀请求, 当插入的秒杀请求数达到上限时,停止所有后续插入。

    然后我们可以在台启动多个工作线程,使用 LPOP key 读取秒杀成功者的用户id,然后再操作数据库做最终的下订单减库存操作。

    当然,上面Redis也可以替换成消息中间件如ActiveMQRabbitMQ等,也可以将缓存和消息中间件 组合起来,缓存系统负责接收记录用户请求,消息中间件负责将缓存中的请求同步到数据库。

    【高并发解决方案】6、数据库水平切分的实现原理解析

     

    第1章 引言

    随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题。对于一个大型的互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载。对于系统的稳定性和扩展性造成了极大的问题。通过数据切分来提高网站性能,横向扩展数据层已经成为架构研发人员首选的方式。

    • 水平切分数据库:可以降低单台机器的负载,同时最大限度的降低了宕机造成的损失;
    • 负载均衡策略:可以降低单台机器的访问负载,降低宕机的可能性;
    • 集群方案:解决了数据库宕机带来的单点数据库不能访问的问题;
    • 读写分离策略:最大限度了提高了应用中读取数据的速度和并发量;

    第2章 基本原理和概念

    什么是数据切分

    "Shard" 这个词英文的意思是"碎片",而作为数据库相关的技术用语,似乎最早见于大型多人在线角色扮演游戏中。"Sharding" 姑且称之为"分片"。Sharding 不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是水平扩展(Scale Out,亦或横向扩展、向外扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。通过一系列的切分规则将数据水平分布到不同的DB或table中,在通过相应的DB路由或者table路由规则找到需要查询的具体的DB或者table,以进行Query操作。“sharding”通常是指“水平切分”,这也是本文讨论的重点。接下来举个简单的例子:我们针对一个Blog应用中的日志来说明,比如日志文章(article)表有如下字段:

    面对这样的一个表,我们怎样切分呢?怎样将这样的数据分布到不同的数据库中的表中去呢?我们可以这样做,将user_id为1~10000的所有的文章信息放入DB1中的article表中,将user_id为10001~20000的所有文章信息放入DB2中的 article表中,以此类推,一直到DBn。这样一来,文章数据就很自然的被分到了各个数据库中,达到了数据切分的目的。

    接下来要解决的问题就是怎样找到具体的数据库呢?其实问题也是简单明显的,既然分库的时候我们用到了区分字段user_id,那么很自然,数据库路由的过程当然还是少不了user_id的。就是我们知道了这个blog的user_id,就利用这个user_id,利用分库时候的规则,反过来定位具体的数据库。比如user_id是234,利用刚才的规则,就应该定位到DB1,假如user_id是12343,利用该才的规则,就应该定位到DB2。以此类推,利用分库的规则,反向的路由到具体的DB,这个过程我们称之为“DB路由”。

    平常我们会自觉的按照范式来设计我们的数据库,考虑到数据切分的DB设计,将违背这个通常的规矩和约束。为了切分,我们不得不在数据库的表中出现冗余字段,用作区分字段或者叫做分库的标记字段。比如上面的article的例子中的user_id这样的字段(当然,刚才的例子并没有很好的体现出user_id的冗余性,因为user_id这个字段即使就是不分库,也是要出现的,算是我们捡了便宜吧)。当然冗余字段的出现并不只是在分库的场景下才出现的,在很多大型应用中,冗余也是必须的,这个涉及到高效DB的设计,本文不再赘述。

    为什么要数据切分

    上面对什么是数据切分做了个概要的描述和解释,读者可能会疑问,为什么需要数据切分呢?像 Oracle这样成熟稳定的数据库,足以支撑海量数据的存储与查询了?为什么还需要数据切片呢?

    的确,Oracle的DB确实很成熟很稳定,但是高昂的使用费用和高端的硬件支撑不是每一个公司能支付的起的。试想一下一年几千万的使用费用和动辄上千万元的小型机作为硬件支撑,这是一般公司能支付的起的吗?即使就是能支付的起,假如有更好的方案,有更廉价且水平扩展性能更好的方案,我们为什么不选择呢?

    我们知道每台机器无论配置多么好它都有自身的物理上限,所以当我们应用已经能触及或远远超出单台机器的某个上限的时候,我们惟有寻找别的机器的帮助或者继续升级的我们的硬件,但常见的方案还是横向扩展,通过添加更多的机器来共同承担压力。我们还得考虑当我们的业务逻辑不断增长,我们的机器能不能通过线性增长就能满足需求?Sharding可以轻松的将计算,存储,I/O并行分发到多台机器上,这样可以充分利用多台机器各种处理能力,同时可以避免单点失败,提供系统的可用性,进行很好的错误隔离。

    综合以上因素,数据切分是很有必要的。 我们用免费的MySQL和廉价的Server甚至是PC做集群,达到小型机+大型商业DB的效果,减少大量的资金投入,降低运营成本,何乐而不为呢?所以,我们选择Sharding,拥抱Sharding。

    怎么做到数据切分

    数据切分可以是物理上的,对数据通过一系列的切分规则将数据分布到不同的DB服务器上,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。

    数据切分也可以是数据库内的,对数据通过一系列的切分规则,将数据分布到一个数据库的不同表中,比如将article分为article_001,article_002等子表,若干个子表水平拼合有组成了逻辑上一个完整的article表,这样做的目的其实也是很简单的。举个例子说明,比如article表中现在有5000w条数据,此时我们需要在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,5000w行数据建立索引的系统开销还是不容忽视的。但是反过来,假如我们将这个表分成100 个table呢,从article_001一直到article_100,5000w行数据平均下来,每个子表里边就只有50万行数据,这时候我们向一张 只有50w行数据的table中insert数据后建立索引的时间就会呈数量级的下降,极大了提高了DB的运行时效率,提高了DB的并发量。当然分表的好处还不知这些,还有诸如写操作的锁操作等,都会带来很多显然的好处。

    综上,分库降低了单点机器的负载;分表,提高了数据操作的效率,尤其是Write操作的效率。行文至此我们依然没有涉及到如何切分的问题。接下来,我们将对切分规则进行详尽的阐述和说明。

    上文中提到,要想做到数据的水平切分,在每一个表中都要有相冗余字符作为切分依据和标记字段,通常的应用中我们选用user_id作为区分字段,基于此就有如下三种分库的方式和规则:(当然还可以有其他的方式)

    (1) 号段分区

    user_id为1~1000的对应DB1,1001~2000的对应DB2,以此类推;

    优点:可部分迁移

    缺点:数据分布不均

    (2)hash取模分区

    对user_id进行hash(或者如果user_id是数值型的话直接使用user_id 的值也可),然后用一个特定的数字,比如应用中需要将一个数据库切分成4个数据库的话,我们就用4这个数字对user_id的hash值进行取模运算,也就是user_id%4,这样的话每次运算就有四种可能:结果为1的时候对应DB1;结果为2的时候对应DB2;结果为3的时候对应DB3;结果为0的时候对应DB4。这样一来就非常均匀的将数据分配到4个DB中。

    优点:数据分布均匀

    缺点:数据迁移的时候麻烦,不能按照机器性能分摊数据

    (3)在认证库中保存数据库配置

    就是建立一个DB,这个DB单独保存user_id到DB的映射关系,每次访问数据库的时候都要先查询一次这个数据库,以得到具体的DB信息,然后才能进行我们需要的查询操作。

    优点:灵活性强,一对一关系

    缺点:每次查询之前都要多一次查询,性能大打折扣

    以上就是通常的开发中我们选择的三种方式,有些复杂的项目中可能会混合使用这三种方式。 通过上面的描述,我们对分库的规则也有了简单的认识和了解。当然还会有更好更完善的分库方式,还需要我们不断的探索和发现。

    第3章 本课题研究的基本轮廓

    分布式数据方案提供功能如下:

    (1)提供分库规则和路由规则(RouteRule简称RR);

    (2)引入集群(Group)的概念,保证数据的高可用性;

    (3)引入负载均衡策略(LoadBalancePolicy简称LB);

    (4)引入集群节点可用性探测机制,对单点机器的可用性进行定时的侦测,以保证LB策略的正确实施,以确保系统的高度稳定性;

    (5)引入读/写分离,提高数据的查询速度;

    仅仅是分库分表的数据层设计也是不够完善的,当我们采用了数据库切分方案,也就是说有N台机器组成了一个完整的DB 。如果有一台机器宕机的话,也仅仅是一个DB的N分之一的数据不能访问而已,这是我们能接受的,起码比切分之前的情况好很多了,总不至于整个DB都不能访问。

    一般的应用中,这样的机器故障导致的数据无法访问是可以接受的,假设我们的系统是一个高并发的电子商务网站呢?单节点机器宕机带来的经济损失是非常严重的。也就是说,现在我们这样的方案还是存在问题的,容错性能是经不起考验的。当然了,问题总是有解决方案的。我们引入集群的概念,在此我称之为Group,也就是每一个分库的节点我们引入多台机器,每台机器保存的数据是一样的,一般情况下这多台机器分摊负载,当出现宕机情况,负载均衡器将分配负载给这台宕机的机器。这样一来,就解决了容错性的问题。

    如上图所示,整个数据层有Group1,Group2,Group3三个集群组成,这三个集群就是数据水平切分的结果,当然这三个集群也就组成了一个包含完整数据的DB。每一个Group包括1个Master(当然Master也可以是多个)和 N个Slave,这些Master和Slave的数据是一致的。 比如Group1中的一个slave发生了宕机现象,那么还有两个slave是可以用的,这样的模型总是不会造成某部分数据不能访问的问题,除非整个 Group里的机器全部宕掉,但是考虑到这样的事情发生的概率非常小(除非是断电了,否则不易发生吧)。

    在没有引入集群以前,我们的一次查询的过程大致如下:请求数据层,并传递必要的分库区分字段 (通常情况下是user_id)。数据层根据区分字段Route到具体的DB,在这个确定的DB内进行数据操作。

    这是没有引入集群的情况,当时引入集群会 是什么样子的呢?我们的路由器上规则和策略其实只能路由到具体的Group,也就是只能路由到一个虚拟的Group,这个Group并不是某个特定的物理服务器。接下来需要做的工作就是找到具体的物理的DB服务器,以进行具体的数据操作。

    基于这个环节的需求,我们引入了负载均衡器的概念 (LB),负载均衡器的职责就是定位到一台具体的DB服务器。具体的规则如下:负载均衡器会分析当前sql的读写特性,如果是写操作或者是要求实时性很强的操作的话,直接将查询负载分到Master,如果是读操作则通过负载均衡策略分配一个Slave。

    我们的负载均衡器的主要研究方向也就是负载分发策略,通常情况下负载均衡包括随机负载均衡和加权负载均衡。随机负载均衡很好理解,就是从N个Slave中随机选取一个Slave。这样的随机负载均衡是不考虑机器性能的,它默认为每台机器的性能是一样的。假如真实的情况是这样的,这样做也是无可厚非的。假如实际情况并非如此呢?每个Slave的机器物理性能和配置不一样的情况,再使用随机的不考虑性能的负载均衡,是非常不科学的,这样一来会给机器性能差的机器带来不必要的高负载,甚至带来宕机的危险,同时高性能的数据库服务器也不能充分发挥其物理性能。基于此考虑从,我们引入了加权负载均衡,也就是在我们的系统内部通过一定的接口,可以给每台DB服务器分配一个权值,然后再运行时LB根据权值在集群中的比重,分配一定比例的负载给该DB服务器。当然这样的概念的引入,无疑增大了系统的复杂性和可维护性。有得必有失,我们也没有办法逃过的。

    有了分库,有了集群,有了负载均衡器,是不是就万事大吉了呢? 事情远没有我们想象的那么简单。虽然有了这些东西,基本上能保证我们的数据层可以承受很大的压力,但是这样的设计并不能完全规避数据库宕机的危害。假如Group1中的slave2 宕机了,那么系统的LB并不能得知,这样的话其实是很危险的,因为LB不知道,它还会以为slave2为可用状态,所以还是会给slave2分配负载。这样一来,问题就出来了,客户端很自然的就会发生数据操作失败的错误或者异常。

    这样是非常不友好的!怎样解决这样的问题呢? 我们引入集群节点的可用性探测机制 ,或者是可用性的数据推送机制。这两种机制有什么不同呢?首先说探测机制吧,顾名思义,探测即使,就是我的数据层客户端,不定时对集群中各个数据库进行可用性的尝试,实现原理就是尝试性链接,或者数据库端口的尝试性访问,都可以做到。

    那数据推送机制又是什么呢?其实这个就要放在现实的应用场景中来讨论这个问题了,一般情况下应用的DB 数据库宕机的话我相信DBA肯定是知道的,这个时候DBA手动的将数据库的当前状态通过程序的方式推送到客户端,也就是分布式数据层的应用端,这个时候在更新一个本地的DB状态的列表。并告知LB,这个数据库节点不能使用,请不要给它分配负载。一个是主动的监听机制,一个是被动的被告知的机制。两者各有所长。但是都可以达到同样的效果。这样一来刚才假设的问题就不会发生了,即使就是发生了,那么发生的概率也会降到最低。

    上面的文字中提到的Master和Slave ,我们并没有做太多深入的讲解。一个Group由1个Master和N个Slave组成。为什么这么做呢?其中Master负责写操作的负载,也就是说一切写的操作都在Master上进行,而读的操作则分摊到Slave上进行。这样一来的可以大大提高读取的效率。在一般的互联网应用中,经过一些数据调查得出结论,读/写的比例大概在 10:1左右 ,也就是说大量的数据操作是集中在读的操作,这也就是为什么我们会有多个Slave的原因。

    但是为什么要分离读和写呢?熟悉DB的研发人员都知道,写操作涉及到锁的问题,不管是行锁还是表锁还是块锁,都是比较降低系统执行效率的事情。我们这样的分离是把写操作集中在一个节点上,而读操作其其他 的N个节点上进行,从另一个方面有效的提高了读的效率,保证了系统的高可用性。

     转自:http://www.cnblogs.com/zhongxinWang/p/4262650.html

    【高并发解决方案】7、HAProxy安装和配置

    简介

    HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。

    HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。

    HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。

    HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space) 实现所有这

    些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。

    安装

    复制代码
    #下载
    wget http://fossies.org/linux/misc/haproxy-1.6.9.tar.gz
    #解压
    tar -zxvf haproxy-1.6.9.tar.gz
    cd haproxy-1.6.9
    #安装
    make TARGET=linux2628 ARCH=x86_64 PREFIX=/usr/local/haproxy
    make install PREFIX=/usr/local/haproxy
    
    #参数说明
    TARGET=linux26 #内核版本,使用uname -r查看内核,如:2.6.18-371.el5,此时该参数就为linux26;kernel 大于2.6.28的用:TARGET=linux2628
    ARCH=x86_64 #系统位数
    PREFIX=/usr/local/haprpxy #/usr/local/haprpxy为haprpxy安装路径
    复制代码

    配置

    复制代码
    ###########全局配置#########
    global
      log 127.0.0.1 local0 #[日志输出配置,所有日志都记录在本机,通过local0输出]
      log 127.0.0.1 local1 notice #定义haproxy 日志级别[error warringinfo debug]
      daemon #以后台形式运行harpoxy
      nbproc 1 #设置进程数量
      maxconn 4096 #默认最大连接数,需考虑ulimit-n限制
      #user haproxy #运行haproxy的用户
      #group haproxy #运行haproxy的用户所在的组
      #pidfile /var/run/haproxy.pid #haproxy 进程PID文件
      #ulimit-n 819200 #ulimit 的数量限制
      #chroot /usr/share/haproxy #chroot运行路径
      #debug #haproxy 调试级别,建议只在开启单进程的时候调试
      #quiet
    
    ########默认配置############
    defaults
      log global
      mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
      option httplog #日志类别,采用httplog
      option dontlognull #不记录健康检查日志信息
      retries 2 #两次连接失败就认为是服务器不可用,也可以通过后面设置
      #option forwardfor #如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip
      option httpclose #每次请求完毕后主动关闭http通道,haproxy不支持keep-alive,只能模拟这种模式的实现
      #option redispatch #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器,以后将不支持
      option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
      maxconn 4096 #默认的最大连接数
      timeout connect 5000ms #连接超时
      timeout client 30000ms #客户端超时
      timeout server 30000ms #服务器超时
      #timeout check 2000 #心跳检测超时
      #timeout http-keep-alive10s #默认持久连接超时时间
      #timeout http-request 10s #默认http请求超时时间
      #timeout queue 1m #默认队列超时时间
      balance roundrobin #设置默认负载均衡方式,轮询方式
      #balance source #设置默认负载均衡方式,类似于nginx的ip_hash
      #balnace leastconn #设置默认负载均衡方式,最小连接数
    
    ########统计页面配置########
    listen stats
      bind 0.0.0.0:1080 #设置Frontend和Backend的组合体,监控组的名称,按需要自定义名称
      mode http #http的7层模式
      option httplog #采用http日志格式
      #log 127.0.0.1 local0 err #错误日志记录
      maxconn 10 #默认的最大连接数
      stats refresh 30s #统计页面自动刷新时间
      stats uri /stats #统计页面url
      stats realm XingCloud\ Haproxy #统计页面密码框上提示文本
      stats auth admin:admin #设置监控页面的用户和密码:admin,可以设置多个用户名
      stats auth Frank:Frank #设置监控页面的用户和密码:Frank
      stats hide-version #隐藏统计页面上HAProxy的版本信息
      stats admin if TRUE #设置手工启动/禁用,后端服务器(haproxy-1.4.9以后版本)
    
    ########设置haproxy 错误页面#####
    #errorfile 403 /home/haproxy/haproxy/errorfiles/403.http
    #errorfile 500 /home/haproxy/haproxy/errorfiles/500.http
    #errorfile 502 /home/haproxy/haproxy/errorfiles/502.http
    #errorfile 503 /home/haproxy/haproxy/errorfiles/503.http
    #errorfile 504 /home/haproxy/haproxy/errorfiles/504.http
    
    ########frontend前端配置##############
    frontend main
      bind *:80 #这里建议使用bind *:80的方式,要不然做集群高可用的时候有问题,vip切换到其他机器就不能访问了。
      acl web hdr(host) -i www.abc.com  #acl后面是规则名称,-i为忽略大小写,后面跟的是要访问的域名,如果访问www.abc.com这个域名,就触发web规则,。
      acl img hdr(host) -i img.abc.com  #如果访问img.abc.com这个域名,就触发img规则。
      use_backend webserver if web   #如果上面定义的web规则被触发,即访问www.abc.com,就将请求分发到webserver这个作用域。
      use_backend imgserver if img   #如果上面定义的img规则被触发,即访问img.abc.com,就将请求分发到imgserver这个作用域。
      default_backend dynamic #不满足则响应backend的默认页面
    
    ########backend后端配置##############
    backend webserver #webserver作用域
      mode http
      balance roundrobin #balance roundrobin 负载轮询,balance source 保存session值,支持static-rr,leastconn,first,uri等参数
      option httpchk /index.html HTTP/1.0 #健康检查, 检测文件,如果分发到后台index.html访问不到就不再分发给它
      server web1 10.16.0.9:8085 cookie 1 weight 5 check inter 2000 rise 2 fall 3
      server web2 10.16.0.10:8085 cookie 2 weight 3 check inter 2000 rise 2 fall 3
      #cookie 1表示serverid为1,check inter 1500 是检测心跳频率 
      #rise 2是2次正确认为服务器可用,fall 3是3次失败认为服务器不可用,weight代表权重
    
    backend imgserver
      mode http
      option httpchk /index.php
      balance roundrobin 
      server img01 192.168.137.101:80 check inter 2000 fall 3
      server img02 192.168.137.102:80 check inter 2000 fall 3
    
    backend dynamic 
      balance roundrobin 
      server test1 192.168.1.23:80 check maxconn 2000 
      server test2 192.168.1.24:80 check maxconn 2000
    
    
    listen tcptest 
      bind 0.0.0.0:5222 
      mode tcp 
      option tcplog #采用tcp日志格式 
      balance source 
      #log 127.0.0.1 local0 debug 
      server s1 192.168.100.204:7222 weight 1 
      server s2 192.168.100.208:7222 weight 1
    复制代码

    负载均衡算法

    复制代码
    一、roundrobin,表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法。该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
    
    二、static-rr,表示根据权重,建议关注;每个服务器根据权重轮流使用,类似roundrobin,但它是静态的,意味着运行时修改权限是无效的。另外,它对服务器的数量没有限制。
    
    三、leastconn,表示最少连接者先处理,建议关注;leastconn建议用于长会话服务,例如LDAP、SQL、TSE等,而不适合短会话协议。如HTTP.该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
    
    四、source,表示根据请求源IP,建议关注;对请求源IP地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。
               只要服务器正常,同一个客户端IP地址总是访问同一个服务器。如果哈希的结果随可用服务器数量而变化,那么客户端会定向到不同的服务器;
               该算法一般用于不能插入cookie的Tcp模式。它还可以用于广域网上为拒绝使用会话cookie的客户端提供最有效的粘连;
               该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
    五、uri,表示根据请求的URI;表示根据请求的URI左端(问号之前)进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。
            只要服务器正常,同一个URI地址总是访问同一个服务器。
            一般用于代理缓存和反病毒代理,以最大限度的提高缓存的命中率。该算法只能用于HTTP后端;
            该算法一般用于后端是缓存服务器;
            该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
    六、url_param,表示根据请求的URl参数'balance url_param' requires an URL parameter name
                  在HTTP GET请求的查询串中查找<param>中指定的URL参数,基本上可以锁定使用特制的URL到特定的负载均衡器节点的要求;
                  该算法一般用于将同一个用户的信息发送到同一个后端服务器;
                  该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
    七、hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求;
                  在每个HTTP请求中查找HTTP头<name>,HTTP头<name>将被看作在每个HTTP请求,并针对特定的节点;
                  如果缺少头或者头没有任何值,则用roundrobin代替;
                  该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
    八、rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。
                         为每个进来的TCP请求查询并哈希RDP cookie<name>;
                         该机制用于退化的持久模式,可以使同一个用户或者同一个会话ID总是发送给同一台服务器。
                         如果没有cookie,则使用roundrobin算法代替;
                         该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
    
    #其实这些算法各有各的用法,我们平时应用得比较多的应该是roundrobin、source和lestconn。
    
    haproxy负载均衡算法
    复制代码

    ACL规则定义

    复制代码
    ########ACL策略定义#########################
    1、#如果请求的域名满足正则表达式返回true -i是忽略大小写
    acl denali_policy hdr_reg(host) -i ^(www.inbank.com|image.inbank.com)$
    
    2、#如果请求域名满足www.inbank.com 返回 true -i是忽略大小写
    acl tm_policy hdr_dom(host) -i www.inbank.com
    
    3、#在请求url中包含sip_apiname=,则此控制策略返回true,否则为false
    acl invalid_req url_sub -i sip_apiname=#定义一个名为invalid_req的策略
    
    4、#在请求url中存在timetask作为部分地址路径,则此控制策略返回true,否则返回false
    acl timetask_req url_dir -i timetask
    
    5、#当请求的header中Content-length等于0时返回 true
    acl missing_cl hdr_cnt(Content-length) eq 0
    
    #########acl策略匹配相应###################
    1、#当请求中header中Content-length等于0 阻止请求返回403
    block if missing_cl
    
    2、#block表示阻止请求,返回403错误,当前表示如果不满足策略invalid_req,或者满足策略timetask_req,则阻止请求。
    block if !invalid_req || timetask_req
    
    3、#当满足denali_policy的策略时使用denali_server的backend
    use_backend denali_server if denali_policy
    
    4、#当满足tm_policy的策略时使用tm_server的backend
    use_backend tm_server if tm_policy
    
    5、#reqisetbe关键字定义,根据定义的关键字选择backend
    reqisetbe ^Host:\ img dynamic
    reqisetbe ^[^\ ]*\ /(img|css)/ dynamic
    reqisetbe ^[^\ ]*\ /admin/stats stats
    
    6、#以上都不满足的时候使用默认mms_server的backend
    default_backend mms
    
    haproxy acl定义
    复制代码

    配置日志

    复制代码
        1.创建记录日志文件
            mkdir /var/log/haproxy
            chmod a+w /var/log/haproxy
        2.编辑/etc/rsyslog.conf
          a) 开启514 UDP监听
               # Provides UDP syslog reception
               $ModLoad imudp
               $UDPServerRun 514
          b) 指定日志存放地点:
              local0.*      /var/log/haproxy/haproxy.log
        3.haproxy.conf 配置:
           global
             # 配置local2事件
            log    127.0.0.1  local0 info
    
        4.重启 rsyslog服务
           systemctl  restart   rsyslog
    复制代码

    启动

    /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg 

    查看状态

    复制代码
    http://192.168.1.22:1080/stats
    
    #说明:
    #1080即haproxy配置文件中监听端口
    s#tats 即haproxy配置文件中的监听名称

    监控页面详细说明

    复制代码

    展开全文
  • JAVA高并发的三种实现

    万次阅读 多人点赞 2018-07-23 10:50:59
    是用它可以解决一切并发问题,但是,对于系统吞吐量要求更的话,我们这提供几个小技巧。帮助大家减小锁颗粒度,提高并发能力。 初级技巧-乐观锁 乐观锁使用的场景是,读不会冲突,写会冲突。同时读的频率远大于...

    提到锁,大家肯定想到的是sychronized关键字。是用它可以解决一切并发问题,但是,对于系统吞吐量要求更高的话,我们这提供几个小技巧。帮助大家减小锁颗粒度,提高并发能力。

    初级技巧-乐观锁

    乐观锁使用的场景是,读不会冲突,写会冲突。同时读的频率远大于写。

     悲观锁的实现

    悲观的认为所有代码执行都会有并发问题,所以将所有代码块都用sychronized锁住

    乐观锁的实现

    乐观的认为在读的时候不会产生冲突为题,在写时添加锁。所以解决的应用场景是读远大于写时的场景。

    中级技巧-String.intern()

    乐观锁不能很好的解决大量的写冲突的问题,但是很多场景下,锁只是针对某个用户或者某个订单。 比如一个用户先创建session,才能进行后面的操作,但是由于网络的问题,创建session的请求和后续请求几乎同时到达,而并行线程可能会先处理后面的请求。一般情况需要对用户sessionMap加锁,比如上面的乐观锁。在这样的场景下,可以将锁限定在用户本身上,即原来的

    这个比较类似行锁和数据库表锁的概念。显然行锁的并发能力比表锁的高很多。

    实用String.intern();是这种方式的具体实现。类String维护了一个字符串池。当调用intern方法时,如果池已经包含一个等于此String对象的字符串(该对象由equals(Object)方法确定),则返回池中的字符串。可见,当String 相同时,总返回同一个对象,因此就实现了对同一用户加锁。由于所的颗粒度局限于具体用户,使得系统获得最大程度的并发。

    CopyOnWriteMap?

     

    既然说到了“类似于数据库中的行锁的概念”,就不得不提一下MVCC,Java中CopyOnWrite类实现了MVCC。Copy On Write是这样一种机制。当我们读取共享数据的时候,直接读取,不需要同步。当我们修改数据的时候,我们就把当前数据Copy一份副本,然后在这个副本 上进行修改,完成之后,再用修改后的副本,替换掉原来的数据。这种方法就叫做Copy On Write。

     

    但是,,,JDK并没有提供CopyOnWriteMap,为什么?下面有个很好的回答,那就是已经有了ConcurrentHashMap,为什么还需要CopyOnWriteMap?

     

    高级技巧 - 类ConcurrentHashMap

    String.inter()的缺陷是类 String 维护一个字符串池是放在JVM perm区的,如果用户数特别多,导致放入字符串池的String不可控,有可能导致OOM错误或者过多的Full GC。怎么样能控制锁的个数,同时减小粒度锁呢?直接使用Java ConcurrentHashMap?或者你想加入自己更精细的控制?那么可以借鉴ConcurrentHashMap的方式,将需要加锁的对象分为多个bucket,每个bucket加一个锁,伪代码如下:

     

     

     

     

     

     

    展开全文
  • 如何解决高并发问题

    千次阅读 2018-11-05 11:14:40
    一个小型的网站,比如个人网站,可以...已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很的要求,已经不是...

    一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的。

    大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。

    上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。

    1、HTML静态化

    其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。

    除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。

    同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。

    2、图片服务器分离

    大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。

    3、数据库集群和库表散列

    大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。

    在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。

    上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。

    4、缓存

    缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 
    架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。 
    网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多了,.net不是很熟悉,相信也肯定有。

    5、镜像

    镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。

    6、负载均衡

    负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。

    负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。

    1)硬件四层交换

    第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。

    在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。

    2)软件四层交换

    大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。

    软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。

    一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。

     

     

    一:高并发高负载类网站关注点之数据库

    没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用,数据库的响应是首先要解决的。
    一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降。常用的优化措施是M-S(主-从)方式进行同步复制,将查询和操作和分别在不同的服务器上进行操作。我推荐的是M-M-Slaves方式,2个主Mysql,多个Slaves,需要注意的是,虽然有2个Master,但是同时只有1个是Active,我们可以在一定时候切换。之所以用2个M,是保证M不会又成为系统的SPOF。
    Slaves可以进一步负载均衡,可以结合LVS,从而将select操作适当的平衡到不同的slaves上。
    以上架构可以抗衡到一定量的负载,但是随着用户进一步增加,你的用户表数据超过1千万,这时那个M变成了SPOF。你不能任意扩充Slaves,否则复制同步的开销将直线上升,怎么办?我的方法是表分区,从业务层面上进行分区。最简单的,以用户数据为例。根据一定的切分方式,比如id,切分到不同的数据库集群去。

    全局数据库用于meta数据的查询。缺点是每次查询,会增加一次,比如你要查一个用户nightsailer,你首先要到全局数据库群找到nightsailer对应的cluster id,然后再到指定的cluster找到nightsailer的实际数据。
    每个cluster可以用m-m方式,或者m-m-slaves方式。这是一个可以扩展的结构,随着负载的增加,你可以简单的增加新的mysql cluster进去。

    需要注意的是:
    1、禁用全部auto_increment的字段
    2、id需要采用通用的算法集中分配
    3、要具有比较好的方法来监控mysql主机的负载和服务的运行状态。如果你有30台以上的mysql数据库在跑就明白我的意思了。
    4、不要使用持久性链接(不要用pconnect),相反,使用sqlrelay这种第三方的数据库链接池,或者干脆自己做,因为php4中mysql的链接池经常出问题。

    二:高并发高负载网站的系统架构之HTML静态化

    其实大家都知道,效率最高、消耗最小的就是纯静态化 http://www.ablanxue.com/shtml/201207/776.shtml的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是 最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点 的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限 管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
      
      除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
      
       同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛 中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这 部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求高并发。
      

    网站HTML静态化解决方案 
    当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:

    HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填充JSP--响应请求

    HTML静态化之后:

    HTTP请求---Web服务器---Servlet--HTML--响应请求

    静态访求如下

    Servlet:

    public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        if(request.getParameter("chapterId") != null){  
            String chapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";  
            String chapterFilePath = getServletContext().getRealPath("/") + chapterFileName;  
            File chapterFile = new File(chapterFilePath);  
            if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有这个文件就告诉浏览器转向   
            INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();  
            NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));//章节信息   
            int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());  
            int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());  
            request.setAttribute("novelChapter", novelChapter);  
            request.setAttribute("lastPageId", lastPageId);  
            request.setAttribute("nextPageId", nextPageId);  
            new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(),   
                    chapterFileName, chapterFilePath, "/bookRead.jsp");  
        }  
    }  
    生成HTML静态页面的类:

    package com.jb.y2t034.thefifth.web.servlet;  
    import java.io.ByteArrayOutputStream;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.OutputStreamWriter;  
    import java.io.PrintWriter;  
    import javax.servlet.RequestDispatcher;  
    import javax.servlet.ServletContext;  
    import javax.servlet.ServletException;  
    import javax.servlet.ServletOutputStream;  
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
    import javax.servlet.http.HttpServletResponseWrapper;  
    /** 
    * 创建HTML静态页面 
    * 功能:创建HTML静态页面 
    * 时间:2009年1011日 
    * 地点:home 
    * @author mavk 

    */  
    public class CreateStaticHTMLPage {  
        /** 
         * 生成静态HTML页面的方法 
         * @param request 请求对象 
         * @param response 响应对象 
         * @param servletContext Servlet上下文 
         * @param fileName 文件名称 
         * @param fileFullPath 文件完整路径 
         * @param jspPath 需要生成静态文件的JSP路径(相对即可) 
         * @throws IOException 
         * @throws ServletException 
         */  
        public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException{  
            response.setContentType("text/html;charset=gb2312");//设置HTML结果流编码(即HTML文件编码)   
            RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//得到JSP资源   
            final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//用于从ServletOutputStream中接收资源   
            final ServletOutputStream servletOuputStream = new ServletOutputStream(){//用于从HttpServletResponse中接收资源   
                public void write(byte[] b, int off,int len){  
                    byteArrayOutputStream.write(b, off, len);  
                }  
                public void write(int b){  
                    byteArrayOutputStream.write(b);  
                }  
            };  
            final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//把转换字节流转换成字符流   
            HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用于从response获取结果流资源(重写了两个方法)   
                public ServletOutputStream getOutputStream(){  
                    return servletOuputStream;  
                }  
                public PrintWriter getWriter(){  
                    return printWriter;  
                }  
            };  
            rd.include(request, httpServletResponse);//发送结果流   
            printWriter.flush();//刷新缓冲区,把缓冲区的数据输出   
            FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath);  
            byteArrayOutputStream.writeTo(fileOutputStream);//把byteArrayOuputStream中的资源全部写入到fileOuputStream中   
            fileOutputStream.close();//关闭输出流,并释放相关资源   
            response.sendRedirect(fileName);//发送指定文件流到客户端   
        }  

    三:高并发高负载类网站关注点之缓存、负载均衡、存储

    缓存是另一个大问题,我一般用memcached来做缓存集群,一般来说部署10台左右就差不多(10g内存池)。需要注意一点,千万不能用使用
    swap,最好关闭linux的swap。


    负载均衡/加速

    可能上面说缓存的时候,有人第一想的是页面静态化,所谓的静态html,我认为这是常识,不属于要点了。页面的静态化随之带来的是静态服务的
    负载均衡和加速。我认为Lighttped+Squid是最好的方式了。
    LVS <------->lighttped====>squid(s) ====lighttpd

    上面是我经常用的。注意,我没有用apache,除非特定的需求,否则我不部署apache,因为我一般用php-fastcgi配合lighttpd,
    性能比apache+mod_php要强很多。

    squid的使用可以解决文件的同步等等问题,但是需要注意,你要很好的监控缓存的命中率,尽可能的提高的90%以上。
    squid和lighttped也有很多的话题要讨论,这里不赘述。


    存储
    存储也是一个大问题,一种是小文件的存储,比如图片这类。另一种是大文件的存储,比如搜索引擎的索引,一般单文件都超过2g以上。
    小文件的存储最简单的方法是结合lighttpd来进行分布。或者干脆使用Redhat的GFS,优点是应用透明,缺点是费用较高。我是指
    你购买盘阵的问题。我的项目中,存储量是2-10Tb,我采用了分布式存储。这里要解决文件的复制和冗余。
    这样每个文件有不同的冗余,这方面可以参考google的gfs的论文。
    大文件的存储,可以参考nutch的方案,现在已经独立为hadoop子项目。(你可以google it)

    其他:
    此外,passport等也是考虑的,不过都属于比较简单的了。
    四:高并发高负载网站的系统架构之图片服务器分离 
    大家知道,对于Web 服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他 们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用 服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule, 保证更高的系统消耗和执行效率。


    利用Apache实现图片服务器的分离
    缘由: 
    起步阶段的应用,都可能部署在一台服务器上(费用上的原因) 
    第一个优先分离的,肯定是数据库和应用服务器。 
    第二个分离的,会是什么呢?各有各的考虑,我所在的项目组重点考虑的节约带宽,服务器性能再好,带宽再高,并发来了,也容易撑不住。因此,我这篇文章的重点在这里。这里重点是介绍实践,不一定符合所有情况,供看者参考吧, 
    环境介绍: 
    WEB应用服务器:4CPU双核2G, 内存4G 
      部署:Win2003/Apache Http Server 2.1/Tomcat6 
    数据库服务器:4CPU双核2G, 内存4G 
      部署:Win2003/MSSQL2000 
    步骤: 
    步骤一:增加2台配置为:2CPU双核2G,内存2G普通服务器,做资源服务器 
      部署:Tomcat6,跑了一个图片上传的简单应用,(记得指定web.xml的<distributable/>),并指定域名为res1.***.com,res2.***.com,采用ajp协议 
    步骤二:修改Apache httpd.conf配置 
      原来应用的文件上传功能网址为: 
       1、/fileupload.html 
       2、/otherupload.html 
      在httpd.conf中增加如下配置

    <VirtualHost *:80>   
      ServerAdmin webmaster@***.com   
      ProxyPass /fileupload.html balancer://rescluster/fileupload lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3      
      ProxyPass /otherupload.html balancer://rescluster/otherupload.html lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3      
      #<!--负载均衡-->   
      <Proxy balancer://rescluster/>   
        BalancerMember ajp://res1.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat1  
        BalancerMember ajp://res2.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat2  
      </Proxy>   
       
    < /VirtualHost>  
    步骤三,修改业务逻辑: 
      所有上传文件在数据库中均采用全url的方式保存,例如产品图片路径存成:http://res1.***.com/upload/20090101/product120302005.jpg

    现在,你可以高枕无忧了,带宽不够时,增加个几十台图片服务器,只需要稍微修改一下apache的配置文件,即可。

    五:高并发高负载网站的系统架构之数据库集群和库表散列

    大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
      
      在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
      
       上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并 且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者 功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的 架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系 统随时增加一台低成本的数据库进来补充系统性能。


    集群软件的分类:
    一般来讲,集群软件根据侧重的方向和试图解决的问题,分为三大类:高性能集群(High performance cluster,HPC)、负载均衡集群(Load balance cluster, LBC),高可用性集群(High availability cluster,HAC)。
    高性能集群(High performance cluster,HPC),它是利用一个集群中的多台机器共同完成同一件任务,使得完成任务的速度和可靠性都远远高于单机运行的效果。弥补了单机性能上的不足。该集群在天气预报、环境监控等数据量大,计算复杂的环境中应用比较多;
    负载均衡集群(Load balance cluster, LBC),它是利用一个集群中的多台单机,完成许多并行的小的工作。一般情况下,如果一个应用使用的人多了,那么用户请求的响应时间就会增大,机器的性能也会受到影响,如果使用负载均衡集群,那么集群中任意一台机器都能响应用户的请求,这样集群就会在用户发出服务请求之后,选择当时负载最小,能够提供最好的服务的这台机器来接受请求并相应,这样就可用用集群来增加系统的可用性和稳定性。这类集群在网站中使用较多;
    高可用性集群(High availability cluster,HAC),它是利用集群中系统 的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务,等待故障机的维修和返回。最大限度的保证集群中服务的可用性。这类系统一般在银行,电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。
    2 数据库集群的现状
    数据库集群是将计算机集群技术引入到数据库中来实现的,尽管各厂商宣称自己的架构如何的完美,但是始终不能改变Oracle当先,大家追逐的事实,在集群的解决方案上Oracle RAC还是领先于包括微软在内的其它数据库厂商,它能满足客户高可用性、高性能、数据库负载均衡和方便扩展的需求。
    Oracle’s Real Application Cluster (RAC)
    Microsoft SQL Cluster Server (MSCS)
    IBM’s DB2 UDB High Availability Cluster(UDB)
    Sybase ASE High Availability Cluster (ASE)
    MySQL High Availability Cluster (MySQL CS)
    基于IO的第三方HA(高可用性)集群
    当前主要的数据库集群技术有以上六大类,有数据库厂商自己开发的;也有第三方的集群公司开发的;还有数据库厂商与第三方集群公司合作开发的,各类集群实现的功能及架构也不尽相同。
    RAC(Real Application Cluster,真正应用集群)是Oracle9i数据库中采用的一项新技术,也是Oracle数据库支持网格计算环境的核心技术。它的出现解决了传统数据库应用中面临的一个重要问题:高性能、高可伸缩性与低价格之间的矛盾。在很长一段时间里,甲骨文都以其实时应用集群技术(Real Application Cluster,RAC)统治着集群数据库市场

    六:高并发高负载网站的系统架构之缓存

    缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 
      架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。
       网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大 型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多 了,.net不是很熟悉,相信也肯定有。

    Java开源缓存框架 
    JBossCache/TreeCache JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行Jboss服务器之间的集群工作。JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务,当然,它也能独立运行。 JBossCache包括两个模块:TreeCache和TreeCacheAOP。 TreeCache --是一个树形结构复制的事务处理缓存。 TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO
    OSCache OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。 拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。 永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。 支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。 缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
    JCACHE JCACHE是一种即将公布的标准规范(JSR 107),说明了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等。它可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)。
    Ehcache Ehcache出自Hibernate,在Hibernate中使用它作为数据缓存的解决方案。
    Java Caching System JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架,以实现高性能的应用。 对于一些需要频繁访问而每访问一次都非常消耗资源的对象,可以临时存放在缓冲区中,这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。
    SwarmCache SwarmCache是一个简单而功能强大的分布式缓存机制。它使用IP组播来有效地在缓存的实例之间进行通信。它是快速提高集群式Web应用程序的性能的理想选择。
    ShiftOne ShiftOne Object Cache这个Java库提供了基本的对象缓存能力。实现的策略有先进先出(FIFO),最近使用(LRU),最不常使用(LFU)。所有的策略可以最大化元素的大小,最大化其生存时间。
    WhirlyCache Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。
    Jofti Jofti可对在缓存层中(支持EHCache,JBossCache和OSCache)的对象或在支持Map接口的存储结构中的对象进行索引与搜索。这个框架还为对象在索引中的增删改提供透明的功能同样也为搜索提供易于使用的查询功能。
    cache4j cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU, LRU, FIFO,可使用强引用(strong reference)与软引用(soft reference)存储对象。
    Open Terracotta 一个JVM级的开源群集框架,提供:HTTP Session复制,分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式,所以你不需要修改任何)。
    sccache SHOP.COM使用的对象缓存系统。sccache是一个in-process cache和二级、共享缓存。它将缓存对象存储到磁盘上。支持关联Key,任意大小的Key和任意大小的数据。能够自动进行垃圾收集。
    Shoal Shoal是一个基于Java可扩展的动态集群框架,能够为构建容错、可靠和可用的Java应用程序提供了基础架构支持。这个框架还可以集成到不希望绑定到特定通信协议,但需要集群和分布式系统支持的任何Java产品中。Shoal是GlassFish和JonAS应用服务器的集群引擎。
    Simple-Spring-Memcached Simple-Spring-Memcached,它封装了对MemCached的调用,使MemCached的客户端开发变得超乎寻常的简单。

    展开全文
  • 高并发详解(一)

    万次阅读 多人点赞 2018-05-08 07:40:46
    高并发是指在同一个时间点,有很多用户同时的访问URL地址,比如:淘宝的双11,双12,就会产生高并发,如贴吧的爆吧,就是恶意的高并发请求,也就是DDOS攻击,再屌丝点的说法就像玩撸啊撸被ADC暴击了一样,那伤害你懂得...
  • 高并发情况

    千次阅读 2017-06-28 15:54:39
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个W
  • 什么是高并发 ,详细讲解

    万次阅读 多人点赞 2018-08-30 13:38:58
    一、什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。   高并发相关常用的一些指标有响应时间(Response ...
  • 什么是高并发

    千次阅读 2017-11-11 16:54:42
    高并发的产生 对于web项目,随着用户量的增加就有可能产生高并发的问题。高并发简单的来说就是在同一时刻不同用户访问同一资源的问题,专业一点的说法就是在同一时刻有多个线程访问了同一个数据资源。 解决方案 ...
  • 高并发解决方案

    万次阅读 2018-03-03 17:07:45
    我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时,系统内有20台...
  • 处理高并发的六种方法

    万次阅读 2019-03-19 12:35:02
    处理高并发的六种方法 1:系统拆分,将一个系统拆分为多个子系统,用dubbo来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,这样就可以抗高并发。 2:缓存,必须得用缓存。大部分的高并发场景,...
  • Java高并发解决方案

    万次阅读 多人点赞 2019-03-03 22:23:50
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个W...
  • JavaWeb 并发编程 与 高并发解决方案

    万次阅读 多人点赞 2018-09-12 03:41:00
    在这里写写我学习到和自己所理解的 Java高并发编程和高并发解决方案。现在在各大互联网公司中,随着日益增长的互联网服务需求,高并发处理已经是一个非常常见的问题,在这篇文章里面我们重点讨论两个方面的问题,一...
  • .net高并发解决方案

    2019-03-04 13:53:03
    后台高并发解决方案demo,使用entity framework关系框架和rabbitmq
  • mysql高并发解决方案

    2018-06-07 11:26:56
    这个是很好解决高并发的一个方案,大家可以下载来看看,一同进步
  • java高并发解决方案

    万次阅读 2012-12-31 09:46:55
    一个小型的网站,比如个人网站,可以...已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很的要求,已经不是
  • 高并发解决方案相关面试题

    万次阅读 2019-09-06 20:48:16
    什么是DNS解析域名 DNS域名解析就是讲域名转化为不需要显示端口(二级域名的端口一般为80)的IP地址,域名解析的一般先去本地环境的host文件读取配置,解析成对应的IP地址,根据IP地址访问对应的服务器。...
  • 大数据和高并发解决方案

    千次阅读 2019-04-29 15:59:24
    一、网站应用背景 ...当问题的规模在经济条件下通过堆硬件的方式解决不了的时候,我们应该通过其他的思路去解决问题,互联网发展至今,已经提供了很多成熟的解决方案,但并不是都具有适用性,你...
  • java系统高并发解决方案(转载)

    万次阅读 多人点赞 2014-07-15 10:32:52
    转载博客地址:http://blog.csdn.net/zxl333/article/details/8454319 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化...已经细分到很细的方方面面,尤其对于大
  • Java 高并发解决方案(电商的秒杀和抢购)

    万次阅读 多人点赞 2018-07-25 14:08:08
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整...
  • 高并发服务限流特技有哪些算法? 传统计算器算法,滑动窗口计数器算法,令牌桶算法和漏桶算法。 传统计数器限流算法有什么弊端? 传统计数器限流方式不支持高并发,存在线程安全问题.若大量访问请求集中在计数器最后...

空空如也

1 2 3 4 5 ... 20
收藏数 756,232
精华内容 302,492
关键字:

高并发