标签:
高并发下随笔
随便写写,有什么不对的地方,请多指教。
选NGINX还是APACHE抗并发:
首先常用的架构是LNMP,之前用过LAMP的架构,但发现APACHE在高并发下表现并没有NGINX优异,原因是NGINX是异步非阻塞,APACHE是同步多进程阻塞型,NGINX会占用更少的资源抗并发,可能几千上万个链接依旧使用一个链接,NGINX也很容易组成集群, 给不同配置的服务器分配不同的权重,还包括负载均衡的方式,比如轮询与我们常用的IP_HASH等,所以推荐LNMP的架构。
选择HDD还是SSD硬盘:
首先我们要知道,在我们的系统中,调起一个页面就相当于对硬盘做了一次IO操作,IO的速度正是取决于我们的硬盘类型,所以有了IOPS这个说法,即每秒能做多少次IO读写操作,在高并发场景下HDD硬盘肯定是不够的,读写速度大致在80M~90M/s, 而SSD硬盘通常都在380M~450M/s,我们可以想象,在高并发下最大的瓶颈就是在IO这块,如数据库,你IO越高对数据库读写的速度也就意味着越快;
架构的优化:
1.在实际情况中,我们首页受冲击量是最大的,那么我们可以不可以让服务器少受到流量的冲击呢?答案当然是可以的,在我们开发中常常会用的缓存这个概念,可以是静态页面,也可以是Redis这类的数据缓存,但无论从何处来说,这都意味着这些文件或者cache都是在我们服务器上,第一种方案是由于CDN来抗第一波流量,将首页静态页面放置CDN来降低服务器压力,可能有人会说那首页的数据怎么办?如果你的数据实时性要求性不高,那么完全可以1个小时或者5个小时生成新的静态页面来刷新CDN,如果实时性要求较高,那么可以讲js/css/img等静态文件放置到cdn,通常我的做法是利用websocket与服务器进行全双工通信的连接,做法是在页面引入io.socket.js埋点监听服务器的指定端口,当页面加载中,可以在数据展现的地方放置加载图案,同时js与服务器进行socket通信,获取数据填充,那么实际上,服务器只承担了一次请求的消耗,同时也可以在和服务器通信之前的过程传出用户的ip,这样还可以对不同区域的用户展现不同的内容。
缓存是应用:
2.在第一段中我们已经用CDN清洗了大约40-60%的流量,那么剩下的流量压力将由于缓存完成,在我们常见用户场景,往往是用户请求指定的url,服务器响应这个request时候往往是去做一些数据库查询的工作,在请求少的时候,这样做完全是可以的,但是有一天公司领导对你说,XX.我们要做一次秒杀和团购,预计高峰会有1W以上的请求同时涌入,你要全力保障服务器稳定。
这个时候,除了之前我们配好的nginx集群之外,我们就要祭出我们大杀器,Redis类的缓存来清洗第二波流量,我们将一些需要抢购的商品提前放到redis缓存中,让数据库的table与redis的hash做一次映射,让redis的哈希表来缓存这些信息,为什么用HASH不用SET KEY,因为HASH可以更节约内存,你可以把Redis的HASH当做一个数组(在实际上Redis也是这样做的,HASH出你key与value的HASH值成一个类似数组的下标)当然,Redis的主从也是要做的,避免活动中,Redis突然挂掉,虽然Redis可以持久化到硬盘,但也会不可避免的丢掉一些数据,重启redist时候重载入数据也会花费时间,那么我们可以这样做,首先数据库表数据提前写入masterRedis,请求去读Redis的slave服务器,master和slave实时的同步,如果你量够大的话,可以试试使用一致性HASH做多个redis主从集群,高峰请求做队列,lpush或者lpop都是随便你,当然这个并不是最完善的,如果消费失败,在队列里其实也没有了,最好的是阿里的RTMQ。
数据库的架构:
3.在第二段中我们利用redis大约能抗住了从cdn和其他地方穿透的请求流量,那么当请求穿透Redis时候,那就到了真正要查询数据库的时候,这个时候就是考验数据库设计与架构的地方,
通常我们优化索引,表结构,选用表引擎,优化SQL,但这都是有上限的,这个时候我们使出第一招,数据库主从同步,流量大的可以做多个slave,这招通常可以解决很多问题,写Master DB 读 slave,读写分离,通常瓶颈在这里已经解决了,但是,如果你是一个超大型的网站,数据库的主从依旧没有满足需求的时候,那我们只能祭出最终的杀器:分布式分库分表数据库中间件,我经常用的是阿里开源的cobar中间件,原理是将数据库先形成读写分离,将读OR写分摊到几台服务器上,假设有这张表,记录基础数据,但写不是很频繁,数据最多不超过十几万,那么我会将这张表在几台服务器上都同步,查询的时候这几天服务器上的DB都参与负载均衡语句,哪台DB压力低就去哪台服务器查询这张表,又假设我们有这样一张表,用户表,当前用户激增,每天都有几十万新增用户,单表基数已经接近千万级别,这个时候无论单表优化对剧降性能都是不能满足的,那么着就涉及到分库分表,服务器A上有USER库,库里存放USER表,表最多可以存放500W条用户数据,当这张表满时,新增用户语句指向服务器B上的USER库的USER表,在1000W数据时候又会指向服务器C....,通常我们使用取模方式获取用户具体的表,公式是:用户ID%8。
一些小细节:
以后补充,先吃饭~~
标签:
原文地址:http://www.cnblogs.com/shumingjian/p/5795059.html