当前位置: 首页 > news >正文

制作网站需要什么语言wordpress 免签约支付宝

制作网站需要什么语言,wordpress 免签约支付宝,合肥做微网站建设,北京营销网站建设公司0 系列目录 秒杀系统架构 秒杀系统架构分析与实战1 秒杀业务分析 正常电子商务流程 #xff08;1#xff09;查询商品#xff1b;#xff08;2#xff09;创建订单#xff1b;#xff08;3#xff09;扣减库存#xff1b;#xff08;4#xff09;更新订单#xff1…0 系列目录 秒杀系统架构 秒杀系统架构分析与实战1 秒杀业务分析 正常电子商务流程 1查询商品2创建订单3扣减库存4更新订单5付款6卖家发货 秒杀业务的特性 1低廉价格2大幅推广3瞬时售空4一般是定时上架5时间短、瞬时并发量高 2 秒杀技术挑战 假设某网站秒杀活动只推出一件商品预计会吸引1万人参加活动也就说最大并发请求数是10000秒杀系统需要面对的技术挑战有 对现有网站业务造成冲击 秒杀活动只是网站营销的一个附加活动这个活动具有时间短并发访问量大的特点如果和网站原有应用部署在一起必然会对现有业务造成冲击稍有不慎可能导致整个网站瘫痪。 解决方案将秒杀系统独立部署甚至使用独立域名使其与网站完全隔离。 高并发下的应用、数据库负载 用户在秒杀开始前通过不停刷新浏览器页面以保证不会错过秒杀这些请求如果按照一般的网站应用架构访问应用服务器、连接数据库会对应用服务器和数据库服务器造成负载压力。 解决方案重新设计秒杀商品页面不使用网站原来的商品详细页面页面内容静态化用户请求不需要经过应用服务。 突然增加的网络及服务器带宽 假设商品页面大小200K主要是商品图片大小那么需要的网络和服务器带宽是2G200K×10000这些网络带宽是因为秒杀活动新增的超过网站平时使用的带宽。 解决方案因为秒杀新增的网络带宽必须和运营商重新购买或者租借。为了减轻网站服务器的压力需要将秒杀商品页面缓存在CDN同样需要和CDN服务商临时租借新增的出口带宽。 直接下单 秒杀的游戏规则是到了秒杀才能开始对商品下单购买在此时间点之前只能浏览商品信息不能下单。而下单页面也是一个普通的URL如果得到这个URL不用等到秒杀开始就可以下单了。 解决方案为了避免用户直接访问下单页面URL需要将改URL动态化即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。办法是在下单页面URL加入由服务器端生成的随机数作为参数在秒杀开始的时候才能得到。 如何控制秒杀商品页面购买按钮的点亮 购买按钮只有在秒杀开始的时候才能点亮在此之前是灰色的。如果该页面是动态生成的当然可以在服务器端构造响应页面输出控制该按钮是灰色还 是点亮但是为了减轻服务器端负载压力更好地利用CDN、反向代理等性能优化手段该页面被设计为静态页面缓存在CDN、反向代理服务器上甚至用户浏览器上。秒杀开始时用户刷新页面请求根本不会到达应用服务器。 解决方案使用JavaScript脚本控制在秒杀商品静态页面中加入一个JavaScript文件引用该JavaScript文件中包含 秒杀开始标志为否当秒杀开始的时候生成一个新的JavaScript文件文件名保持不变只是内容不一样更新秒杀开始标志为是加入下单页面的URL及随机数参数这个随机数只会产生一个即所有人看到的URL都是同一个服务器端可以用Redis这种分布式缓存服务器来保存随机数并被用户浏览器加载控制秒杀商品页面的展示。这个JavaScript文件的加载可以加上随机版本号例如xx.js?v32353823这样就不会被浏览器、CDN和反向代理服务器缓存。 这个JavaScript文件非常小即使每次浏览器刷新都访问JavaScript文件服务器也不会对服务器集群和网络带宽造成太大压力。 如何只允许第一个提交的订单被发送到订单子系统 由于最终能够成功秒杀到商品的用户只有一个因此需要在用户提交订单时检查是否已经有订单提交。如果已经有订单提交成功则需要更新 JavaScript文件更新秒杀开始标志为否购买按钮变灰。事实上由于最终能够成功提交订单的用户只有一个为了减轻下单页面服务器的负载压力 可以控制进入下单页面的入口只有少数用户能进入下单页面其他用户直接进入秒杀结束页面。 解决方案假设下单服务器集群有10台服务器每台服务器只接受最多10个下单请求。在还没有人提交订单成功之前如果一台服务器已经有十单了而有的一单都没处理可能出现的用户体验不佳的场景是用户第一次点击购买按钮进入已结束页面再刷新一下页面有可能被一单都没有处理的服务器处理进入了填写订单的页面可以考虑通过cookie的方式来应对符合一致性原则。当然可以采用最少连接的负载均衡算法出现上述情况的概率大大降低。 如何进行下单前置检查 下单服务器检查本机已处理的下单请求数目如果超过10条直接返回已结束页面给用户 如果未超过10条则用户可进入填写订单及确认页面 检查全局已提交订单数目已超过秒杀商品总数返回已结束页面给用户 未超过秒杀商品总数提交到子订单系统 秒杀一般是定时上架 该功能实现方式很多。不过目前比较好的方式是提前设定好商品的上架时间用户可以在前台看到该商品但是无法点击“立即购买”的按钮。但是需要考虑的是有人可以绕过前端的限制直接通过URL的方式发起购买这就需要在前台商品页面以及bug页面到后端的数据库都要进行时钟同步。越在后端控制安全性越高。 定时秒杀的话就要避免卖家在秒杀前对商品做编辑带来的不可预期的影响。这种特殊的变更需要多方面评估。一般禁止编辑如需变更可以走数据订正多的流程。 减库存的操作 有两种选择一种是拍下减库存 另外一种是付款减库存目前采用的“拍下减库存”的方式拍下就是一瞬间的事对用户体验会好些。 库存会带来“超卖”的问题售出数量多于库存数量 由于库存并发更新的问题导致在实际库存已经不足的情况下库存依然在减导致卖家的商品卖得件数超过秒杀的预期。方案采用乐观锁 update auction_auctions set quantity #inQuantity# where auction_id #itemId# and quantity #dbQuantity#秒杀器的应对 秒杀器一般下单个购买及其迅速根据购买记录可以甄别出一部分。可以通过校验码达到一定的方法这就要求校验码足够安全不被破解采用的方式有秒杀专用验证码电视公布验证码秒杀答题。 3 秒杀架构原则 尽量将请求拦截在系统上游 传统秒杀系统之所以挂请求都压倒了后端数据层数据读写锁冲突严重并发高响应慢几乎所有请求都超时流量虽大下单成功的有效流量甚小【一趟火车其实只有2000张票200w个人来买基本没有人能买成功请求有效率为0】。 读多写少的常用多使用缓存 这是一个典型的读多写少的应用场景【一趟火车其实只有2000张票200w个人来买最多2000个人下单成功其他人都是查询库存写比例只有0.1%读比例占99.9%】非常适合使用缓存。 4 秒杀架构设计 秒杀系统为秒杀而设计不同于一般的网购行为参与秒杀活动的用户更关心的是如何能快速刷新商品页面在秒杀开始的时候抢先进入下单页面而不是商品详情等用户体验细节因此秒杀系统的页面设计应尽可能简单。 商品页面中的购买按钮只有在秒杀活动开始的时候才变亮在此之前及秒杀商品卖出后该按钮都是灰色的不可以点击。 下单表单也尽可能简单购买数量只能是一个且不可以修改送货地址和付款方式都使用用户默认设置没有默认也可以不填允许等订单提交后修改只有第一个提交的订单发送给网站的订单子系统其余用户提交订单后只能看到秒杀结束页面。 要做一个这样的秒杀系统业务会分为两个阶段第一个阶段是秒杀开始前某个时间到秒杀开始 这个阶段可以称之为准备阶段用户在准备阶段等待秒杀 第二个阶段就是秒杀开始到所有参与秒杀的用户获得秒杀结果 这个就称为秒杀阶段吧。 4.1 前端层设计 首先要有一个展示秒杀商品的页面 在这个页面上做一个秒杀活动开始的倒计时 在准备阶段内用户会陆续打开这个秒杀的页面 并且可能不停的刷新页面。这里需要考虑两个问题 第一个是秒杀页面的展示 我们知道一个html页面还是比较大的即使做了压缩http头和内容的大小也可能高达数十K加上其他的css js图片等资源如果同时有几千万人参与一个商品的抢购一般机房带宽也就只有1G~10G网络带宽就极有可能成为瓶颈所以这个页面上各类静态资源首先应分开存放然后放到cdn节点上分散压力由于CDN节点遍布全国各地能缓冲掉绝大部分的压力而且还比机房带宽便宜~ 第二个是倒计时 出于性能原因这个一般由js调用客户端本地时间就有可能出现客户端时钟与服务器时钟不一致另外服务器之间也是有可能出现时钟不一致。客户端与服务器时钟不一致可以采用客户端定时和服务器同步时间这里考虑一下性能问题用于同步时间的接口由于不涉及到后端逻辑只需要将当前web服务器的时间发送给客户端就可以了因此速度很快就我以前测试的结果来看一台标准的web服务器2WQPS不会有问题如果100W人同时刷100W QPS也只需要50台web一台硬件LB就可以了~并且web服务器群是可以很容易的横向扩展的(LBDNS轮询)这个接口可以只返回一小段json格式的数据而且可以优化一下减少不必要cookie和其他http头的信息所以数据量不会很大一般来说网络不会成为瓶颈即使成为瓶颈也可以考虑多机房专线连通加智能DNS的解决方案web服务器之间时间不同步可以采用统一时间服务器的方式比如每隔1分钟所有参与秒杀活动的web服务器就与时间服务器做一次时间同步。 浏览器层请求拦截 1产品层面用户点击“查询”或者“购票”后按钮置灰禁止用户重复提交请求; 2JS层面限制用户在x秒之内只能提交一次请求; 4.2 站点层设计 前端层的请求拦截只能拦住小白用户不过这是99%的用户哟高端的程序员根本不吃这一套写个for循环直接调用你后端的http请求怎么整 1同一个uid限制访问频度做页面缓存x秒内到达站点层的请求均返回同一页面 2同一个item的查询例如手机车次做页面缓存x秒内到达站点层的请求均返回同一页面 如此限流又有99%的流量会被拦截在站点层。 4.3 服务层设计 站点层的请求拦截只能拦住普通程序员高级黑客假设他控制了10w台肉鸡并且假设买票不需要实名认证这下uid的限制不行了吧怎么整 1大哥我是服务层我清楚的知道小米只有1万部手机我清楚的知道一列火车只有2000张车票我透10w个请求去数据库有什么意义呢对于写请求做请求队列每次只透过有限的写请求去数据层如果均成功再放下一批如果库存不够则队列里的写请求全部返回“已售完” 2对于读请求还用说么cache来抗不管是memcached还是redis单机抗个每秒10w应该都是没什么问题的 如此限流只有非常少的写请求和非常少的读缓存mis的请求会透到数据层去又有99.9%的请求被拦住了。 用户请求分发模块使用Nginx或Apache将用户的请求分发到不同的机器上。 用户请求预处理模块判断商品是不是还有剩余来决定是不是要处理该请求。 用户请求处理模块把通过预处理的请求封装成事务提交给数据库并返回是否成功。 数据库接口模块该模块是数据库的唯一接口负责与数据库交互提供RPC接口供查询是否秒杀结束、剩余数量等信息。 用户请求预处理模块 经过HTTP服务器的分发后单个服务器的负载相对低了一些但总量依然可能很大如果后台商品已经被秒杀完毕那么直接给后来的请求返回秒杀失败即可不必再进一步发送事务了示例代码可以如下所示 package seckill; import org.apache.http.HttpRequest; /** * 预处理阶段把不必要的请求直接驳回必要的请求添加到队列中进入下一阶段. */ public class PreProcessor { // 商品是否还有剩余 private static boolean reminds true; private static void forbidden() { // Do something. } public static boolean checkReminds() { if (reminds) { // 远程检测是否还有剩余该RPC接口应由数据库服务器提供不必完全严格检查. if (!RPC.checkReminds()) { reminds false; } } return reminds; } /** * 每一个HTTP请求都要经过该预处理. */ public static void preProcess(HttpRequest request) { if (checkReminds()) { // 一个并发的队列 RequestQueue.queue.add(request); } else { // 如果已经没有商品了则直接驳回请求即可. forbidden(); } } } 并发队列的选择Java的并发包提供了三个常用的并发队列实现分别是ConcurrentLinkedQueue 、 LinkedBlockingQueue 和 ArrayBlockingQueue。 ArrayBlockingQueue是初始容量固定的阻塞队列我们可以用来作为数据库模块成功竞拍的队列比如有10个商品那么我们就设定一个10大小的数组队列。 ConcurrentLinkedQueue使用的是CAS原语无锁队列实现是一个异步队列入队的速度很快出队进行了加锁性能稍慢。 LinkedBlockingQueue也是阻塞的队列入队和出队都用了加锁当队空的时候线程会暂时阻塞。 由于我们的系统入队需求要远大于出队需求一般不会出现队空的情况所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现 package seckill; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.http.HttpRequest; public class RequestQueue { public static ConcurrentLinkedQueueHttpRequest queue new ConcurrentLinkedQueueHttpRequest(); } 用户请求模块 package seckill; import org.apache.http.HttpRequest; public class Processor { /** * 发送秒杀事务到数据库队列. */ public static void kill(BidInfo info) { DB.bids.add(info); } public static void process() { BidInfo info new BidInfo(RequestQueue.queue.poll()); if (info ! null) { kill(info); } } } class BidInfo { BidInfo(HttpRequest request) { // Do something. } } 数据库模块 数据库主要是使用一个ArrayBlockingQueue来暂存有可能成功的用户请求。 package seckill; import java.util.concurrent.ArrayBlockingQueue; /** * DB应该是数据库的唯一接口. */ public class DB { public static int count 10; public static ArrayBlockingQueueBidInfo bids new ArrayBlockingQueueBidInfo(10); public static boolean checkReminds() { // TODO return true; } // 单线程操作 public static void bid() { BidInfo info bids.poll(); while (count-- 0) { // insert into table Bids values(item_id, user_id, bid_date, other) // select count(id) from Bids where item_id ? // 如果数据库商品数量大约总数则标志秒杀已完成设置标志位reminds false. info bids.poll(); } } } 4.4 数据库设计 4.4.1 基本概念 概念一“单库” 概念二“分片” 分片解决的是“数据量太大”的问题也就是通常说的“水平切分”。一旦引入分片势必有“数据路由”的概念哪个数据访问哪个库。路由规则通常有3种方法 范围range 优点简单容易扩展 缺点各库压力不均新号段更活跃 哈希hash 【大部分互联网公司采用的方案二哈希分库哈希路由】 优点简单数据均衡负载均匀 缺点迁移麻烦2库扩3库数据要迁移 路由服务router-config-server 优点灵活性强业务与路由算法解耦 缺点每次访问数据库前多一次查询 概念三“分组” 分组解决“可用性”问题分组通常通过主从复制的方式实现。 互联网公司数据库实际软件架构是又分片又分组如下图 4.4.2 设计思路 数据库软件架构师平时设计些什么东西呢至少要考虑以下四点 如何保证数据可用性 如何提高数据库读性能大部分应用读多写少读会先成为瓶颈 如何保证一致性 如何提高扩展性 1. 如何保证数据的可用性 解决可用性问题的思路是冗余 如何保证站点的可用性复制站点冗余站点 如何保证服务的可用性复制服务冗余服务 如何保证数据的可用性复制数据冗余数据 数据的冗余会带来一个副作用引发一致性问题先不说一致性问题先说可用性。 2. 如何保证数据库“读”高可用 冗余读库 冗余读库带来的副作用读写有延时可能不一致 上面这个图是很多互联网公司MySQL的架构写仍然是单点不能保证写高可用。 3. 如何保证数据库“写”高可用 冗余写库 采用双主互备的方式可以冗余写库带来的副作用双写同步数据可能冲突例如“自增id”同步冲突,如何解决同步冲突有两种常见解决方案 两个写库使用不同的初始值相同的步长来增加id1写库的id为0,2,4,6...2写库的id为1,3,5,7... 不使用数据的id业务层自己生成唯一的id保证数据不冲突 实际中没有使用上述两种架构来做读写的“高可用”采用的是“双主当主从用”的方式 仍是双主但只有一个主提供服务读写另一个主是“shadow-master”只用来保证高可用平时不提供服务。 master挂了shadow-master顶上vip漂移对业务层透明不需要人工介入。这种方式的好处 读写没有延时 读写高可用 不足 不能通过加从库的方式扩展读性能 资源利用率为50%一台冗余主没有提供服务 那如何提高读性能呢进入第二个话题如何提供读性能。 4. 如何扩展读性能 提高读性能的方式大致有三种第一种是建立索引。这种方式不展开要提到的一点是不同的库可以建立不同的索引。 写库不建立索引 线上读库建立线上访问索引例如uid 线下读库建立线下访问索引例如time 第二种扩充读性能的方式是增加从库这种方法大家用的比较多但是存在两个缺点 从库越多同步越慢 同步越慢数据不一致窗口越大不一致后面说还是先说读性能的提高 实际中没有采用这种方法提高数据库读性能没有从库采用的是增加缓存。常见的缓存架构如下 上游是业务应用下游是主库从库读写分离缓存。 实际的玩法服务数据库缓存一套 业务层不直接面向db和cache服务层屏蔽了底层db、cache的复杂性。为什么要引入服务层今天不展开采用了“服务数据库缓存一套”的方式提供数据访问用cache提高读性能。 不管采用主从的方式扩展读性能还是缓存的方式扩展读性能数据都要复制多份主从dbcache一定会引发一致性问题。 5. 如何保证一致性 主从数据库的一致性通常有两种解决方案 1. 中间件 如果某一个key有写操作在不一致时间窗口内中间件会将这个key的读操作也路由到主库上。这个方案的缺点是数据库中间件的门槛较高百度腾讯阿里360等一些公司有。 2. 强制读主 上面实际用的“双主当主从用”的架构不存在主从不一致的问题。 第二类不一致是db与缓存间的不一致 常见的缓存架构如上此时写操作的顺序是 1淘汰cache 2写数据库 读操作的顺序是 1读cache如果cache hit则返回 2如果cache miss则读从库 3读从库后将数据放回cache 在一些异常时序情况下有可能从【从库读到旧数据同步还没有完成旧数据入cache后】数据会长期不一致。解决办法是“缓存双淘汰”写操作时序升级为 1淘汰cache 2写数据库 3在经验“主从同步延时窗口时间”后再次发起一个异步淘汰cache的请求 这样即使有脏数据如cache一个小的时间窗口之后脏数据还是会被淘汰。带来的代价是多引入一次读miss成本可以忽略。 除此之外最佳实践之一是建议为所有cache中的item设置一个超时时间。 6. 如何提高数据库的扩展性 原来用hash的方式路由分为2个库数据量还是太大要分为3个库势必需要进行数据迁移有一个很帅气的“数据库秒级扩容”方案。 如何秒级扩容 首先我们不做2库变3库的扩容我们做2库变4库库加倍的扩容未来4-8-16 服务数据库是一套省去了缓存数据库采用“双主”的模式。 扩容步骤 第一步将一个主库提升; 第二步修改配置2库变4库原来MOD2现在配置修改后MOD4扩容完成 原MOD2为偶的部分现在会MOD4余0或者2原MOD2为奇的部分现在会MOD4余1或者3数据不需要迁移同时双主互相同步一遍是余0一边余2两边数据同步也不会冲突秒级完成扩容 最后要做一些收尾工作 将旧的双主同步解除 增加新的双主双主是保证可用性的shadow-master平时不提供服务 删除多余的数据余0的主可以将余2的数据删除掉 这样秒级别内我们就完成了2库变4库的扩展。 5 大并发带来的挑战 5.1 请求接口的合理设计 一个秒杀或者抢购页面通常分为2个部分一个是静态的HTML等内容另一个就是参与秒杀的Web后台请求接口。 通常静态HTML等内容是通过CDN的部署一般压力不大核心瓶颈实际上在后台请求接口上。这个后端接口必须能够支持高并发请求同时非常重要的一点必须尽可能“快”在最短的时间里返回用户的请求结果。为了实现尽可能快这一点接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的如果有这种复杂业务的需求都建议采用异步写入。 当然也有一些秒杀和抢购采用“滞后反馈”就是说秒杀当下不知道结果一段时间后才可以从页面中看到用户是否秒杀成功。但是这种属于“偷懒”行为同时给用户的体验也不好容易被用户认为是“暗箱操作”。 5.2 高并发的挑战一定要“快” 我们通常衡量一个Web系统的吞吐率的指标是QPSQuery Per Second每秒处理请求数解决每秒数万次的高并发场景这个指标非常关键。举个例子我们假设处理一个业务请求平均响应时间为100ms同时系统内有20台Apache的Web服务器配置MaxClients为500个表示Apache的最大连接数目。 那么我们的Web系统的理论峰值QPS为理想化的计算方式 20*500/0.1 100000 10万QPS 咦我们的系统似乎很强大1秒钟可以处理完10万的请求5w/s的秒杀似乎是“纸老虎”哈。实际情况当然没有这么理想。在高并发的实际场景下机器都处于高负载的状态在这个时候平均响应时间会被大大增加。 就Web服务器而言Apache打开了越多的连接进程CPU需要处理的上下文切换也越多额外增加了CPU的消耗然后就直接导致平均响应时间增加。因此上述的MaxClient数目要根据CPU、内存等硬件因素综合考虑绝对不是越多越好。可以通过Apache自带的abench来测试一下取一个合适的值。然后我们选择内存操作级别的存储的Redis在高并发的状态下存储的响应时间至关重要。网络带宽虽然也是一个因素不过这种请求数据包一般比较小一般很少成为请求的瓶颈。负载均衡成为系统瓶颈的情况比较少在这里不做讨论哈。 那么问题来了假设我们的系统在5w/s的高并发状态下平均响应时间从100ms变为250ms实际情况甚至更多 20*500/0.25 40000 4万QPS 于是我们的系统剩下了4w的QPS面对5w每秒的请求中间相差了1w。 然后这才是真正的恶梦开始。举个例子高速路口1秒钟来5部车每秒通过5部车高速路口运作正常。突然这个路口1秒钟只能通过4部车车流量仍然依旧结果必定出现大塞车。5条车道忽然变成4条车道的感觉。 同理某一个秒内20*500个可用连接进程都在满负荷工作中却仍然有1万个新来请求没有连接进程可用系统陷入到异常状态也是预期之内。 其实在正常的非高并发的业务场景中也有类似的情况出现某个业务请求接口出现问题响应时间极慢将整个Web请求响应时间拉得很长逐渐将Web服务器的可用连接数占满其他正常的业务请求无连接进程可用。 更可怕的问题是是用户的行为特点系统越是不可用用户的点击越频繁恶性循环最终导致“雪崩”其中一台Web机器挂了导致流量分散到其他正常工作的机器上再导致正常的机器也挂然后恶性循环将整个Web系统拖垮。 5.3 重启与过载保护 如果系统发生“雪崩”贸然重启服务是无法解决问题的。最常见的现象是启动起来后立刻挂掉。这个时候最好在入口层将流量拒绝然后再将重启。如果是redis/memcache这种服务也挂了重启的时候需要注意“预热”并且很可能需要比较长的时间。 秒杀和抢购的场景流量往往是超乎我们系统的准备和想象的。这个时候过载保护是必要的。如果检测到系统满负载状态拒绝请求也是一种保护措施。在前端设置过滤是最简单的方式但是这种做法是被用户“千夫所指”的行为。更合适一点的是将过载保护设置在CGI入口层快速将客户的直接请求返回。 6 作弊的手段进攻与防守 秒杀和抢购收到了“海量”的请求实际上里面的水分是很大的。不少用户为了“抢“到商品会使用“刷票工具”等类型的辅助工具帮助他们发送尽可能多的请求到服务器。还有一部分高级用户制作强大的自动请求脚本。这种做法的理由也很简单就是在参与秒杀和抢购的请求中自己的请求数目占比越多成功的概率越高。 这些都是属于“作弊的手段”不过有“进攻”就有“防守”这是一场没有硝烟的战斗哈。 6.1 同一个账号一次性发出多个请求 部分用户通过浏览器的插件或者其他工具在秒杀开始的时间里以自己的账号一次发送上百甚至更多的请求。实际上这样的用户破坏了秒杀和抢购的公平性。 这种请求在某些没有做数据安全处理的系统里也可能造成另外一种破坏导致某些判断条件被绕过。例如一个简单的领取逻辑先判断用户是否有参与记录如果没有则领取成功最后写入到参与记录中。这是个非常简单的逻辑但是在高并发的场景下存在深深的漏洞。多个并发请求通过负载均衡服务器分配到内网的多台Web服务器它们首先向存储发送查询请求然后在某个请求成功写入参与记录的时间差内其他的请求获查询到的结果都是“没有参与记录”。这里就存在逻辑判断被绕过的风险。 应对方案 在程序入口处一个账号只允许接受1个请求其他请求过滤。不仅解决了同一个账号发送N个请求的问题还保证了后续的逻辑流程的安全。实现方案可以通过Redis这种内存缓存服务写入一个标志位只允许1个请求写成功结合watch的乐观锁的特性成功写入的则可以继续参加。 或者自己实现一个服务将同一个账号的请求放入一个队列中处理完一个再处理下一个。 6.2 多个账号一次性发送多个请求 很多公司的账号注册功能在发展早期几乎是没有限制的很容易就可以注册很多个账号。因此也导致了出现了一些特殊的工作室通过编写自动注册脚本积累了一大批“僵尸账号”数量庞大几万甚至几十万的账号不等专门做各种刷的行为这就是微博中的“僵尸粉“的来源。举个例子例如微博中有转发抽奖的活动如果我们使用几万个“僵尸号”去混进去转发这样就可以大大提升我们中奖的概率。 这种账号使用在秒杀和抢购里也是同一个道理。例如iPhone官网的抢购火车票黄牛党。 应对方案 这种场景可以通过检测指定机器IP请求频率就可以解决如果发现某个IP请求频率很高可以给它弹出一个验证码或者直接禁止它的请求 弹出验证码最核心的追求就是分辨出真实用户。因此大家可能经常发现网站弹出的验证码有些是“鬼神乱舞”的样子有时让我们根本无法看清。他们这样做的原因其实也是为了让验证码的图片不被轻易识别因为强大的“自动脚本”可以通过图片识别里面的字符然后让脚本自动填写验证码。实际上有一些非常创新的验证码效果会比较好例如给你一个简单问题让你回答或者让你完成某些简单操作例如百度贴吧的验证码。 直接禁止IP实际上是有些粗暴的因为有些真实用户的网络场景恰好是同一出口IP的可能会有“误伤“。但是这一个做法简单高效根据实际场景使用可以获得很好的效果。 6.3 多个账号不同IP发送不同请求 所谓道高一尺魔高一丈。有进攻就会有防守永不休止。这些“工作室”发现你对单机IP请求频率有控制之后他们也针对这种场景想出了他们的“新进攻方案”就是不断改变IP。 有同学会好奇这些随机IP服务怎么来的。有一些是某些机构自己占据一批独立IP然后做成一个随机代理IP的服务有偿提供给这些“工作室”使用。还有一些更为黑暗一点的就是通过木马黑掉普通用户的电脑这个木马也不破坏用户电脑的正常运作只做一件事情就是转发IP包普通用户的电脑被变成了IP代理出口。通过这种做法黑客就拿到了大量的独立IP然后搭建为随机IP服务就是为了挣钱。 应对方案 说实话这种场景下的请求和真实用户的行为已经基本相同了想做分辨很困难。再做进一步的限制很容易“误伤“真实用户这个时候通常只能通过设置业务门槛高来限制这种请求了或者通过账号行为的”数据挖掘“来提前清理掉它们。 僵尸账号也还是有一些共同特征的例如账号很可能属于同一个号码段甚至是连号的活跃度不高等级低资料不全等等。根据这些特点适当设置参与门槛例如限制参与秒杀的账号等级。通过这些业务手段也是可以过滤掉一些僵尸号。 7 高并发下的数据安全 我们知道在多线程写入同一个文件的时候会存现“线程安全”的问题多个线程同时运行同一段代码如果每次运行结果和单线程运行的结果是一样的结果和预期相同就是线程安全的。如果是MySQL数据库可以使用它自带的锁机制很好的解决问题但是在大规模并发的场景中是不推荐使用MySQL的。秒杀和抢购的场景中还有另外一个问题就是“超发”如果在这方面控制不慎会产生发送过多的情况。我们也曾经听说过某些电商搞抢购活动买家成功拍下后商家却不承认订单有效拒绝发货。这里的问题也许并不一定是商家奸诈而是系统技术层面存在超发风险导致的。 7.1 超发的原因 假设某个抢购场景中我们一共只有100个商品在最后一刻我们已经消耗了99个商品仅剩最后一个。这个时候系统发来多个并发请求这批请求读取到的商品余量都是99个然后都通过了这一个余量判断最终导致超发。 在上面的这个图中就导致了并发用户B也“抢购成功”多让一个人获得了商品。这种场景在高并发的情况下非常容易出现。 7.2 悲观锁思路 解决线程安全的思路很多可以从“悲观锁”的方向开始讨论。 悲观锁也就是在修改数据的时候采用锁定状态排斥外部请求的修改。遇到加锁的状态就必须等待。 虽然上述的方案的确解决了线程安全的问题但是别忘记我们的场景是“高并发”。也就是说会很多这样的修改请求每个请求都需要等待“锁”某些线程可能永远都没有机会抢到这个“锁”这种请求就会死在那里。同时这种请求会很多瞬间增大系统的平均响应时间结果是可用连接数被耗尽系统陷入异常。 7.3 FIFO队列思路 那好那么我们稍微修改一下上面的场景我们直接将请求放入队列中的采用FIFOFirst Input First Output先进先出这样的话我们就不会导致某些请求永远获取不到锁。看到这里是不是有点强行将多线程变成单线程的感觉哈。 然后我们现在解决了锁的问题全部请求采用“先进先出”的队列方式来处理。那么新的问题来了高并发的场景下因为请求很多很可能一瞬间将队列内存“撑爆”然后系统又陷入到了异常状态。或者设计一个极大的内存队列也是一种方案但是系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说队列内的请求会越积累越多最终Web系统平均响应时候还是会大幅下降系统还是陷入异常。 7.4 乐观锁思路 这个时候我们就可以讨论一下“乐观锁”的思路了。乐观锁是相对于“悲观锁”采用更为宽松的加锁机制大都是采用带版本号Version更新。实现就是这个数据所有请求都有资格去修改但会获得一个该数据的版本号只有版本号符合的才能更新成功其他的返回抢购失败。这样的话我们就不需要考虑队列的问题不过它会增大CPU的计算开销。但是综合来说这是一个比较好的解决方案。 有很多软件和服务都“乐观锁”功能的支持例如Redis中的watch就是其中之一。通过这个实现我们保证了数据的安全。 8 总结 互联网正在高速发展使用互联网服务的用户越多高并发的场景也变得越来越多。电商秒杀和抢购是两个比较典型的互联网高并发场景。虽然我们解决问题的具体技术方案可能千差万别但是遇到的挑战却是相似的因此解决问题的思路也异曲同工。转载于:https://www.cnblogs.com/qianzf/p/7475947.html
http://www.zqtcl.cn/news/759029/

相关文章:

  • 西安网站开发的未来发展易企网络网站建设
  • 贵州做网站怎么推广vs2012 做网站教程
  • 完全菜鸟七天学会建网站网络营销的四大基础理论
  • 东莞网站优化案例网站职业技术培训学校
  • 银川网站建设公司电话公司在百度做网站找谁
  • 交换链接适用于哪些网站网络规划与设计的目的
  • 网站做标签寺院网站模板
  • 高端h5网站柳州建站
  • 百度商桥网站郑州有做网站的公司没
  • 做专业网站济南品牌网站建设低价
  • 网站制作客户寻找数据中台厂商
  • 免费找图片素材的网站西安企业seo
  • 网站建设 名词解释国内网站建设建设
  • 文山州建设局网站域名查询seo
  • php网站模块修改太原小店区最新消息今天
  • 苏州网站优化公司seo服务合同
  • vip影视网站怎么做的辽宁建设厅网站什么时候换的
  • 搭建个网站网站维护合同模板
  • 优盖网logo在线设计南通做网站优化的公司
  • 做百度糯米网站的团队新媒体营销推广公司
  • 个人做网站的时代已经过去大连男科医院排名表
  • 天津餐饮网站建设贵港做网站化司
  • 昆山哪家做网站好猪八戒网站建设
  • 网站的静态资源服务器怎么做河北网站备案
  • php儿童摄影网站源码东莞做网站的公司哪家最好
  • 金融投资网站建设wordpress九宫格主题
  • 玉田县网站建设手机网站建设西安
  • 高质量外链网站请大学生做网站
  • 2021能看的网站不要app贴吧网站以前在百度能搜索不到了
  • 个人做网站时不要做什么样的网站百度网站排名全掉