32650一次性好不好,买32650小组模一至性会不会比买单个一致性好

安全性对比分析  1.在极端情况丅的安全性对比  动力电池在车辆发生严重事故等极端条件下的安全性是人们最为关心的问题因为这直接关系到生命财产安全。圆柱電池容量小通过串并组合达到动力电池组的容量、电

1.在极端情况下的安全性比较

在车辆发生严重事故等极端条件下的安全性是人们最为關心的问题,因为这直接关系到生命财产安全圆柱电池容量小,通过串并组合达到动力组的容量、电压的要求以目前32650电池为例,电池嫆量只有5Ah而大方型电池单体容量一般都超过几十安时,有的达到100Ah以上在电池出现碰撞、挤压等极端危险情况下,圆柱型小电池其释放嘚能量要远远小于大方型电池单体目前沃特玛5Ah电池的电解液只有20克,而大方型电池如50Ah单体,其电解液量要超过200克该方型单体电池的電解液量是小型圆柱电池的10倍以上。一旦在事故中某个单体电芯出现漏液则因电解液泄漏而引起的燃烧程度也会是小型圆柱电池的10倍以仩。从这方面来讲小型圆柱电池的安全性比大电池要好很多。当小型圆柱电池遭到破坏其燃烧的威力要远远小于大的方型电池。通过對单个电池的分离保护某一单体电池出现问题,不会波及其他电池通过将能量分散的方式,使电池的安全性极大提高

在承受撞击方媔,圆柱型电池和方型电池表现差别较大圆柱型电池相关于方型电池具有较好的抗形变能力,各个方向上受力均匀形变保持能力是目湔所有电芯工艺中很优秀的,配合自主研发的安全组合盖帽安全性得到了极大的提高。即使在高速冲撞挤压过程中圆柱形电芯有一定嘚变形,但也不会起火燃烧关于方型电池,面积较大的一面容易形变在高速冲撞挤压过程中,电芯外壳不能很好的保证电芯内部结构很容易导致内部正负极片的错位短路;关于这种瞬间的冲击,方型电芯无法迅速做出反应

另外,关于大的方型电芯由于其侧面面积較大,承受到其他物体撞击的概率要高得多因此在安全事故中,单体电芯被撞坏而造成短路的可能性要比小的圆柱电芯大很多而关于尛型圆柱电池组合,一旦电池箱受到猛烈撞击小型圆柱电池首先断开的地方可能是各个单体电芯的铆接点,而由于电芯体积较小较大嘚可能性是被撞散,电池组失效这对提高动力锂电池组的安全性具有重大意义。因此采用小容量的圆柱型电池组合的电池组在车辆出现倳故时能够供应更长的逃生时间。根据沃特玛的测试电池在烈火中焚烧,电解液喷出引发剧烈燃烧的时间在10分钟后2.散热方面的比较

茬单体散热方面,由于圆柱型电池和方型电池的形状不同散热效果表现差别较大。以50Ah方型电池为例其表面积容量比大约在1x10-3m2/Ah;而32650-5Ah圆柱电池嘚表面积容量比约为1.6x10-3m2/Ah;相比之下大了60%。在外界条件完全相同的情况下圆柱型小电池在散热方面具有天然的优势。

圆柱型电池在组合时电池之间有纵向间隙,这为电池的散热供应天然的散热途径理论上散热截面积至少在15.9%(紧密排列)和21.9%(立方排列)。图3为沃特玛圆柱电池嘚组合结构实物图可以看出组合后具有良好的散热通道。圆柱电池组合的天然的散热通道保证了电池的散热效果提高了电芯安全性。

兩种电池结构都具有防爆安全阀方型电池的安全阀一般位于端侧,阀面积要大于圆柱电池的安全阀但是假如考虑到电池的容量,即单位容量的阀面积方型电池要远远小于圆柱电池。一旦电池出现失效情况特别是极端的撞击情况,方型电池安全阀的有效性要落后于小型圆柱电池圆柱电池组合盖帽兼具防爆安全阀和电流切断装置CID(CurrenTInterruptDevice),如图4所示这一点在方型电池上很少应用。当出现外部短路或当电池内压达到1.2MPa安全警戒值时首先CID装置启动,正负极之间断开主动切断电流自行保护,电池内部回路断开;当电池内压到1.8MPa安全警戒值时泄压构件安全阀会打开,气体排出防止爆炸风险。目前安全型组合盖帽工艺成熟,使圆柱型电芯的安全性得到了很好的保证

众所周知,单体电池的一致性对电池组的寿命、安全性等各个方面指标具有较大的影响大方型电池生产工艺的复杂性决定了目前单体电池的一致性较差。在成组后电池的一致性问题直接对安全性造成影响因为容量少,内阻高的电池更多的面对过充过放带来的风险圆柱电池生產工艺成熟,电池一致性较高在电池组合后,低容量电池出现的几率较低即使出现低容量电池,由于多个并联通过自均衡的方式最夶程度上消除了不一致的影响。

为了验证圆柱电池的安全性对圆柱单体电池及电池组进行了安全测试。图5为圆柱型电池组针刺实验照片当钢钉穿透电池时,电池内电解液泄露电池表面温度急剧升高,电压缓慢下降电解液汽化冒出少量白烟,包裹电池用的绝缘塑料胶套被高温熔化过程持续大约10min后现象消失,最终短路电池电压降为零过程最高温度上升到141℃。电池不爆炸不燃烧。完全符合UL2580(及SAEJ2464)标准图6为圆柱型电池组撞击测试前后的照片。电池组在遭到重物撞击后电池明显受损,但电池无起火、无漏液、无冒烟或爆炸电池电壓基本无变化。符合UL1642标准表2为电池组进行的安全测试项目。从实测结果看圆柱型电池表现出良好的安全性能。图7为更为苛刻的焚烧测試过程照片从实测结果看,电池的防爆片开启的电池表面温度在240℃左右电池释放出气体,电解液局部燃烧不出现爆炸现象。火焰熄滅后电池壳体结构也并未遭到破坏根据UL1642要求实验过程中单体电池的全部和部分不应该穿透钢丝网,从实验结果标明安全性达到UL标准

目湔小型圆柱电池已经大量应用于电动汽车中,为了验证电池在汽车事故中的安全性对整车进行了碰撞测试。碰撞标准按C-NCAP进行对该车分別进行时速50公里与刚性固定障碍100%重叠率正面碰撞,时速56公里对可变形障碍40%重叠率的正面偏置碰撞可变形移动障碍时速50公里与车辆的侧面碰撞。图8为整车碰撞后的照片从碰撞后车辆取下电池进行检测,电池组基本完好无冒烟,无燃烧整车碰撞实验验证了小型圆柱电池應用于电动汽车的安全优势。

用来拼电动车电池的你能告诉峩那个型号是多少V,AH长宽,重量么那种型号和牌子号?要的是业内实际AH不是虚报夸大的。答好了追加奖励... 用来拼电动车电池的。伱能告诉我那个型号是多少VAH,长宽重量么?
那种型号和牌子号要的是业内实际AH,不是虚报夸大的

我准备将电瓶车96V普通电瓶换成锂電池,能否还用原来96充电器! 保护板怎么加装

你对这个回答的评价是


推荐于 · TA获得超过362个赞

你好,我是江西省福斯特新能源集团的技术員我以专业的角度来告诉你

拼电动车现在世面上只有18650的电池来拼,其它的三种用的很少市面上的电动画几乎是没有的

我们公司品牌是長江,比如18650的型号中分数码类和动力类电动车都是用的动力电池,用的最多的也就是动力2000mah和动力2500mah的自己拼装看你要多大电压,多大容量我来给你报价。

本回答被提问者和网友采纳

你对这个回答的评价是

本回答由东莞市恩康电子科技有限公司提供


请问你电话多少好和伱联系?

你对这个回答的评价是

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案

(4)一般是定时上架;
(5)时间短、瞬时并发量高;

假设某网站秒杀活动只推出一件商品预计会吸引1万人参加活动,也就说最大并发请求数是10000秒杀系统需要面对的技術挑战有:

1.对现有网站业务造成冲击

秒杀活动只是网站营销的一个附加活动,这个活动具有时间短并发访问量大的特点

如果和网站原有應用部署在一起,必然会对现有业务造成冲击稍有不慎可能导致整个网站瘫痪。

解决方案:将秒杀系统独立部署甚至使用独立域名,使其与网站完全隔离

2.高并发下的应用、数据库负载

用户在秒杀开始前,通过不停刷新浏览器页面以保证不会错过秒杀这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库会对应用服务器和数据库服务器造成负载压力。

解决方案:重新设计秒杀商品页媔不使用网站原来的商品详细页面,页面内容静态化用户请求不需要经过应用服务。

3.突然增加的网络及服务器带宽

假设商品页面大小200K(主要是商品图片大小)那么需要的网络和服务器带宽是2G(200K×10000)

这些网络带宽是因为秒杀活动新增的,超过网站平时使用的带宽

解决方案:因为秒杀新增的网络带宽,必须和运营商重新购买或者租借

为了减轻网站服务器的压力,需要将秒杀商品页面缓存在CDN同样需要囷CDN服务商临时租借新增的出口带宽。

秒杀的游戏规则是到了秒杀才能开始对商品下单购买在此时间点之前,只能浏览商品信息不能下單。

而下单页面也是一个普通的URL如果得到这个URL,不用等到秒杀开始就可以下单了

解决方案:为了避免用户直接访问下单页面URL,需要将妀URL动态化即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。

办法是在下单页面URL加入由服务器端生成的随机数作为参数在秒殺开始的时候才能得到。

5.如何控制秒杀商品页面购买按钮的点亮

购买按钮只有在秒杀开始的时候才能点亮在此之前是灰色的。

如果该页媔是动态生成的当然可以在服务器端构造响应页面输出,控制该按钮是灰色还是点亮

但是为了减轻服务器端负载压力更好地利用CDN、反姠代理等性能优化手段,该页面被设计为静态页面缓存在CDN、反向代理服务器上,甚至用户浏览器上

秒杀开始时,用户刷新页面请求根本不会到达应用服务器。

解决方案:使用JavaScript脚本控制在秒杀商品静态页面中加入一个JavaScript文件引用,该JavaScript文件中包含秒杀开始标志为否;

当秒殺开始的时候生成一个新的JavaScript文件(文件名保持不变只是内容不一样),更新秒杀开始标志为是加入下单页面的URL及随机数参数

(这个随機数只会产生一个,即所有人看到的URL都是同一个服务器端可以用redis这种分布式缓存服务器来保存随机数)

然后被用户浏览器加载,控制秒殺商品页面的展示这个JavaScript文件的加载可以加上随机版本号(例如xx.js?v=),这样就不会被浏览器、CDN和反向代理服务器缓存


这个JavaScript文件非常小,即使每次浏览器刷新都访问JavaScript文件服务器也不会对服务器集群和网络带宽造成太大压力

6.如何只允许第一个提交的订单被发送到订单子系统

由於最终能够成功秒杀到商品的用户只有一个,因此需要在用户提交订单时检查是否已经有订单提交。

如果已经有订单提交成功则需要哽新 JavaScript文件,更新秒杀开始标志为否购买按钮变灰。

事实上由于最终能够成功提交订单的用户只有一个,为了减轻下单页面服务器的负載压力可以控制进入下单页面的入口,只有少数用户能进入下单页面其他用户直接进入秒杀结束页面。

解决方案:假设下单服务器集群有10台服务器每台服务器只接受最多10个下单请求。

在还没有人提交订单成功之前如果一台服务器已经有十单了,而有的一单都没处理可能出现的用户体验不佳的场景是用户第一次点击购买按钮进入已结束页面,再刷新一下页面有可能被一单都没有处理的服务器处理,进入了填写订单的页面可以考虑通过cookie的方式来应对,符合一致性原则

当然可以采用最少连接的负载均衡算法,出现上述情况的概率夶大降低

7.如何进行下单前置检查

下单服务器检查本机已处理的下单请求数目:

  • 如果超过10条,直接返回已结束页面给用户;

  • 如果未超过10条则用户可进入填写订单及确认页面;

检查全局已提交订单数目:

  • 已超过秒杀商品总数,返回已结束页面给用户;

  • 未超过秒杀商品总数提交到子订单系统;

8.秒杀一般是定时上架

该功能实现方式很多。不过目前比较好的方式是:提前设定好商品的上架时间用户可以在前台看到该商品,但是无法点击“立即购买”的按钮

但是需要考虑的是,有人可以绕过前端的限制直接通过URL的方式发起购买,这就需要在湔台商品页面以及bug页面到后端的数据库,都要进行时钟同步越在后端控制,安全性越高

定时秒杀的话,就要避免卖家在秒杀前对商品做编辑带来的不可预期的影响这种特殊的变更需要多方面评估。一般禁止编辑如需变更,可以走数据订正的流程

有两种选择,一種是拍下减库存 另外一种是付款减库存;目前采用的“拍下减库存”的方式拍下就是一瞬间的事,对用户体验会好些

10.库存会带来“超賣”的问题:售出数量多于库存数量

由于库存并发更新的问题,导致在实际库存已经不足的情况下库存依然在减,导致卖家的商品卖得件数超过秒杀的预期方案:采用乐观锁

还有一种方式,会更好些叫做尝试扣减库存,扣减库存成功才会进行下单逻辑:

秒杀器一般下單个购买及其迅速根据购买记录可以甄别出一部分。可以通过校验码达到一定的方法这就要求校验码足够安全,不被破解采用的方式有:秒杀专用验证码,电视公布验证码秒杀答题。

1.尽量将请求拦截在系统上游

传统秒杀系统之所以挂请求都压倒了后端数据层,数據读写锁冲突严重并发高响应慢,几乎所有请求都超时流量虽大,下单成功的有效流量甚小

【一趟火车其实只有2000张票200w个人来买,基夲没有人能买成功请求有效率为0】

2.读多写少的常用多使用缓存

这是一个典型的读多写少的应用场景【一趟火车其实只有2000张票,200w个人来买最多2000个人下单成功,其他人都是查询库存写比例只有0.1%,读比例占99.9%】非常适合使用缓存。

秒杀系统为秒杀而设计不同于一般的网购荇为,参与秒杀活动的用户更关心的是如何能快速刷新商品页面

在秒杀开始的时候抢先进入下单页面而不是商品详情等用户体验细节,洇此秒杀系统的页面设计应尽可能简单

商品页面中的购买按钮只有在秒杀活动开始的时候才变亮,在此之前及秒杀商品卖出后该按钮嘟是灰色的,不可以点击

下单表单也尽可能简单,购买数量只能是一个且不可以修改送货地址和付款方式都使用用户默认设置,没有默认也可以不填允许等订单提交后修改;

只有第一个提交的订单发送给网站的订单子系统,其余用户提交订单后只能看到秒杀结束页面

要做一个这样的秒杀系统,业务会分为两个阶段:

  • 第一个阶段是秒杀开始前某个时间到秒杀开始 这个阶段可以称之为准备阶段,用户茬准备阶段等待秒杀;

  • 第二个阶段就是秒杀开始到所有参与秒杀的用户获得秒杀结果 这个就称为秒杀阶段吧。

首先要有一个展示秒杀商品的页面在这个页面上做一个秒杀活动开始的倒计时,在准备阶段内用户会陆续打开这个秒杀的页面 并且可能不停的刷新页面。这里需要考虑两个问题:

第一个是秒杀页面的展示

我们知道一个html页面还是比较大的即使做了压缩,http头和内容的大小也可能高达数十K

加上其他嘚css js,图片等资源如果同时有几千万人参与一个商品的抢购,一般机房带宽也就只有1G10G

网络带宽就极有可能成为瓶颈所以这个页面上各類静态资源首先应分开存放,然后放到cdn节点上分散压力

由于CDN节点遍布全国各地能缓冲掉绝大部分的压力,而且还比机房带宽便宜

出于性能原因这个一般由js调用客户端本地时间就有可能出现客户端时钟与服务器时钟不一致,另外服务器之间也是有可能出现时钟不一致

客戶端与服务器时钟不一致可以采用客户端定时和服务器同步时间。

这里考虑一下性能问题用于同步时间的接口由于不涉及到后端逻辑,呮需要将当前web服务器的时间发送给客户端就可以了因此速度很快

就我以前测试的结果来看,一台标准的web服务器2W+QPS不会有问题如果100W人同时刷,100W QPS也只需要50台web一台硬件LB就可以了~。

并且web服务器群是可以很容易的横向扩展的(LB+DNS轮询)这个接口可以只返回一小段json格式的数据

而且可以优囮一下减少不必要cookie和其他http头的信息,所以数据量不会很大

一般来说网络不会成为瓶颈即使成为瓶颈也可以考虑多机房专线连通,加智能DNS嘚解决方案;

web服务器之间时间不同步可以采用统一时间服务器的方式比如每隔1分钟所有参与秒杀活动的web服务器就与时间服务器做一次时間同步。

  • 产品层面用户点击“查询”或者“购票”后,按钮置灰禁止用户重复提交请求;

  • JS层面,限制用户在x秒之内只能提交一次请求;

前端层的请求拦截只能拦住小白用户(不过这是99%的用户哟),高端的程序员根本不吃这一套写个for循环,直接调用你后端的http请求怎么整?

  • 同一个uid限制访问频度,做页面缓存x秒内到达站点层的请求,均返回同一页面

  • 同一个item的查询例如手机车次,做页面缓存x秒内到达站点层的请求,均返回同一页面

如此限流又有99%的流量会被拦截在站点层。

站点层的请求拦截只能拦住普通程序员,高级黑客假设他控制了10w台肉鸡(并且假设买票不需要实名认证),这下uid的限制不行了吧怎么整?

  • 大哥我是服务层,我清楚的知道小米只有1万部手机峩清楚的知道一列火车只有2000张车票,我透10w个请求去数据库有什么意义呢

    对于写请求,做请求队列每次只透过有限的写请求去数据层,洳果均成功再放下一批如果库存不够则队列里的写请求全部返回“已售完”;

  • 对于读请求,还用说么cache来抗,不管是memcached还是redis单机抗个每秒10w应该都是没什么问题的;

如此限流,只有非常少的写请求和非常少的读缓存mis的请求会透到数据层去,又有99.9%的请求被拦住了

  • 用户请求汾发模块:使用Nginx或Apache将用户的请求分发到不同的机器上。

  • 用户请求预处理模块:判断商品是不是还有剩余来决定是不是要处理该请求

  • 用户請求处理模块:把通过预处理的请求封装成事务提交给数据库,并返回是否成功

  • 数据库接口模块:该模块是数据库的唯一接口,负责与數据库交互提供RPC接口供查询是否秒杀结束、剩余数量等信息。

经过HTTP服务器的分发后单个服务器的负载相对低了一些,但总量依然可能佷大

如果后台商品已经被秒杀完毕那么直接给后来的请求返回秒杀失败即可,不必再进一步发送事务了

示例代码可以如下所示:

 

Java的并发包提供了三个常用的并发队列实现分别是:


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

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

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

 
由于我们的系统入队需求要远大于出队需求,一般不会出现队涳的情况所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现:
 
 

数据库主要是使用一个ArrayBlockingQueue来暂存有可能成功的用户请求。
 
 





分片解决的是“数据量呔大”的问题也就是通常说的“水平切分”。
一旦引入分片势必有“数据路由”的概念,哪个数据访问哪个库路由规则通常有3种方法:

优点:简单,容易扩展
缺点:各库压力不均(新号段更活跃)
2、哈希:hash 【大部分互联网公司采用的方案二:哈希分库哈希路由】
优點:简单,数据均衡负载均匀
缺点:迁移麻烦(2库扩3库数据要迁移)

优点:灵活性强,业务与路由算法解耦
缺点:每次访问数据库前多┅次查询


分组解决“可用性”问题分组通常通过主从复制的方式实现。
互联网公司数据库实际软件架构是:又分片又分组(如下图)


數据库软件架构师平时设计些什么东西呢?至少要考虑以下四点:
  • 如何提高数据库读性能(大部分应用读多写少读会先成为瓶颈);

 
1.如哬保证数据的可用性?
解决可用性问题的思路是=>冗余

如何保证站点的可用性复制站点,冗余站点


如何保证服务的可用性复制服务,冗餘服务


如何保证数据的可用性复制数据,冗余数据

 
数据的冗余会带来一个副作用=>引发一致性问题(先不说一致性问题,先说可用性)
2.如何保证数据库“读”高可用?


冗余读库带来的副作用
读写有延时,可能不一致
上面这个图是很多互联网公司mysql的架构,写仍然是单點不能保证写高可用。
3.如何保证数据库“写”高可用


采用双主互备的方式,可以冗余写库带来的副作用双写同步,数据可能冲突(唎如“自增id”同步冲突)如何解决同步冲突,有两种常见解决方案:
  • 两个写库使用不同的初始值相同的步长来增加id:1写库的id为0,2,4,6…;2写庫的id为1,3,5,7…;

 
  • 不使用数据的id,业务层自己生成唯一的id保证数据不冲突;

 
实际中没有使用上述两种架构来做读写的“高可用”,采用的是“雙主当主从用”的方式:

仍是双主但只有一个主提供服务(读+写),另一个主是“shadow-master”只用来保证高可用,平时不提供服务
master挂了,shadow-master顶仩(vip漂移对业务层透明,不需要人工介入)
 
  • 不能通过加从库的方式扩展读性能;

  • 资源利用率为50%,一台冗余主没有提供服务;

 
那如何提高读性能呢进入第二个话题,如何提供读性能

提高读性能的方式大致有三种:
第一种是建立索引。这种方式不展开要提到的一点是,不同的库可以建立不同的索引

线上读库建立线上访问索引,例如uid;
线下读库建立线下访问索引例如time;

 
第二种扩充读性能的方式是,增加从库这种方法大家用的比较多,但是存在两个缺点:
  • 同步越慢,数据不一致窗口越大(不一致后面说还是先说读性能的提高);

 
实际中没有采用这种方法提高数据库读性能(没有从库),采用的是增加缓存常见的缓存架构如下:

上游是业务应用,下游是主库從库(读写分离),缓存实际的玩法:服务+数据库+缓存一套。

业务层不直接面向db和cache服务层屏蔽了底层db、cache的复杂性。
为什么要引入服务層今天不展开,采用了“服务+数据库+缓存一套”的方式提供数据访问用cache提高读性能。
不管采用主从的方式扩展读性能还是缓存的方式扩展读性能,数据都要复制多份(主+从db+cache),一定会引发一致性问题

主从数据库的一致性,通常有两种解决方案:


如果某一个key有写操莋在不一致时间窗口内,中间件会将这个key的读操作也路由到主库上
这个方案的缺点是,数据库中间件的门槛较高(百度腾讯,阿里360等一些公司有)


上面实际用的“双主当主从用”的架构,不存在主从不一致的问题第二类不一致,是db与缓存间的不一致:

常见的缓存架构如上此时写操作的顺序是:
(1)淘汰cache;
(2)写数据库;

(1)读cache,如果cache hit则返回;
(2)如果cache miss则读从库;
(3)读从库后,将数据放回cache;
茬一些异常时序情况下有可能从【从库读到旧数据(同步还没有完成),旧数据入cache后】数据会长期不一致。解决办法是“缓存双淘汰”写操作时序升级为:
(1)淘汰cache;
(2)写数据库;
(3)在经过“主从同步延时窗口时间”后,再次发起一个异步淘汰cache的请求;
这样即使有脏数据如cache,一个小的时间窗口之后脏数据还是会被淘汰。带来的代价是多引入一次读miss(成本可以忽略)。
除此之外最佳实践之┅是:建议为所有cache中的item设置一个超时时间。
3.如何提高数据库的扩展性
原来用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.1、请求接口的合理设计
一个秒殺或者抢购页面,通常分为2个部分一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口
通常静态HTML等内容,是通过CDN的部署一般壓力不大,核心瓶颈实际上在后台请求接口上
这个后端接口,必须能够支持高并发请求同时,非常重要的一点必须尽可能“快”,茬最短的时间里返回用户的请求结果
为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点
仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求都建议采用异步写入。

当然也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果一段时间后才可以从页面中看到用户是否秒杀成功。
但是这种属于“偷懒”行为,同时给用户的体验也不好容易被用户认為是“暗箱操作”。
5.2 高并发的挑战:一定要“快”
我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second每秒处理请求数)
解决每秒数万次的高并發场景,这个指标非常关键
举个例子,我们假设处理一个业务请求平均响应时间为100ms同时,系统内有20台Apache的Web服务器配置MaxClients为500个(表示Apache的最夶连接数目)。
那么我们的Web系统的理论峰值QPS为(理想化的计算方式):
 
咦?我们的系统似乎很强大1秒钟可以处理完10万的请求,5w/s的秒杀姒乎是“纸老虎”哈
实际情况,当然没有这么理想在高并发的实际场景下,机器都处于高负载的状态在这个时候平均响应时间会被夶大增加。
就Web服务器而言Apache打开了越多的连接进程,CPU需要处理的上下文切换也越多额外增加了CPU的消耗,然后就直接导致平均响应时间增加
因此上述的MaxClient数目,要根据CPU、内存等硬件因素综合考虑绝对不是越多越好。可以通过Apache自带的abench来测试一下取一个合适的值。
然后我們选择内存操作级别的存储的Redis,在高并发的状态下存储的响应时间至关重要。
网络带宽虽然也是一个因素不过,这种请求数据包一般仳较小一般很少成为请求的瓶颈。负载均衡成为系统瓶颈的情况比较少在这里不做讨论哈。
那么问题来了假设我们的系统,在5w/s的高並发状态下平均响应时间从100ms变为250ms(实际情况,甚至更多):
 
于是我们的系统剩下了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的
秒杀和抢购的场景中,还有另外一个问题就是“超发”,如果在这方面控制不慎会产苼发送过多的情况。
我们也曾经听说过某些电商搞抢购活动,买家成功拍下后商家却不承认订单有效,拒绝发货
这里的问题,也许並不一定是商家奸诈而是系统技术层面存在超发风险导致的。

假设某个抢购场景中我们一共只有100个商品,在最后一刻我们已经消耗叻99个商品,仅剩最后一个
这个时候,系统发来多个并发请求这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断最终導致超发。

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

解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论
悲观锁,也就是在修改数据的时候采用锁定状态,排斥外部请求的修妀遇到加锁的状态,就必须等待

虽然上述的方案的确解决了线程安全的问题,但是别忘记,我们的场景是“高并发”
也就是说,會很多这样的修改请求每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”这种请求就会死在那里。
同时这種请求会很多,瞬间增大系统的平均响应时间结果是可用连接数被耗尽,系统陷入异常

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

然后,我们现在解决了锁的问题全部请求采用“先进先出”的队列方式来处理。
那么新的问题来了高并发嘚场景下,因为请求很多很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态
或者设计一个极大的内存队列,也是一种方案但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比
也就是说,队列内的请求会越积累越多最终Web系統平均响应时候还是会大幅下降,系统还是陷入异常

这个时候,我们就可以讨论一下“乐观锁”的思路了
乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制大都是采用带版本号(Version)更新。
实现就是这个数据所有请求都有资格去修改,但会获得一个该数据的版本號只有版本号符合的才能更新成功,其他的返回抢购失败
这样的话,我们就不需要考虑队列的问题不过,它会增大CPU的计算开销但昰,综合来说这是一个比较好的解决方案。

有很多软件和服务都“乐观锁”功能的支持例如Redis中的watch就是其中之一。通过这个实现我们保证了数据的安全。
 
互联网正在高速发展使用互联网服务的用户越多,高并发的场景也变得越来越多
电商秒杀和抢购,是两个比较典型的互联网高并发场景虽然我们解决问题的具体技术方案可能千差万别,但是遇到的挑战却是相似的因此解决问题的思路也异曲同工。


作者:石杉的架构笔记
链接:https://juejin.im/post/5d407cb7f265da03d1552d5f
来源:掘金
著作权归作者所有商业转载请联系作者获得授权,非商业转载请注明出处

我要回帖

 

随机推荐