首页 > 其他 > 详细

系统的讲一讲 怎么设计一个高并发的系统

时间:2020-06-06 15:19:59      阅读:47      评论:0      收藏:0      [点我收藏+]

那抽奖为例吧 

首先是整体设计

抽奖一般不会作为独立的业务出现,而是作为某个系统的某个业务出现, 一般而言系统越简单 性能越好,为了降低业务耦合度可以把抽奖拆分为一个子系统来处理,也方便扩容。

前端:动静分离  , 尽量不要动态获取数据 , 如奖品的基本信息等可以写死 , 静态页面上CDN 。

后端:基于nginx做负载均衡 分布式集群部署 (当然nginx也是可以做集群的)

存储:缓存 + 数据库(数据库读写分离 , 分库 ,分表)

那具体怎么做呢  接下来讲一下细节吧

首先是动静分离和分布式部署就不用再说了,先讲一下缓存 , 一般而言,redis的读取性能大于数据库,而接口缓存在内存中,性能比redis要高,

数据是不是应该缓存以及应该缓存在哪里,缓存多长时间要是业务场景来定,比如说用户的基本信息和奖品的基本信息,对于抽奖系统来说,这些信息是不变的 ,完全可以缓存在内存中,而且缓存时间可以设置的稍微长一点;

抽奖避不开的两个强数据一致性关键数据是抽奖的次数和库存,

先说一下抽奖次数,首先这个数据会随时间快速增长,查询和插入成本会迅速增加,我认为比较好的方式是把抽奖的次数记在用户信息内,一般而言用户可以抽多次将,那抽奖的记录数就是用户数的N呗,用户信息本要查询,

放到一起减少了一次查询而且减少了查询数据量,但是这又会返回来影响用户缓存数据的管理,方案有两个,一用户请求hash,保证某个用户的请求落到某一个特定的机器上,这样就避免了用户信息缓存在多台服务器而造成的数据一致性问题,

当然用memeryCahe这样的集中式缓存来解决也行,第二种方式是把用户信息缓存在redis来解决缓存数据一致性问题,当然,性能肯定要比在内存中差一些 ;

虽然用到了缓存,但是肯定有需要访问数据库的时候,数据库可以做哪些优化呢,首先是分库,抽奖可以单独使用一个数据库实例,然后读写分离,分表,分表的规则有很多,采用哪种规则取决于业务场景,

比如用户信息,可以采用用户id来HASH来分,如抽奖记录我们这边一般是每天多少次抽奖机会,所以特别适合按时间分表,当然用户用户Hash也是可以的。

此外就是索引,把常用查询字段加上索引,提升查询效率,适当的数据冗余,比如中奖纪录可以把用户基本信息冗余进去,减少连表查询等等常规操作。

然后再讲一下库存,库存对数据一致性要求极高,而且读写频繁,并发读很容易造成库存判断错误。我认为比较好的解决方案有两种,第一种方式是加锁:当其中一个线程抽中了奖品时,将此商品锁住,处理完前不让其他线程进入此商品的抽奖环节或等待,

加锁肯定会影响性能,但是考虑到抽奖是一个漏斗模型,抽中奖品的人毕竟很少,对整体的性能影响不大。

但是如果中奖概率需求高时怎么办呢 , 有个办法就是分库存,如果一个奖品有1万个,可以分成100组100个库存,这样就等于把单线程抽奖分成了一百个线程抽奖,至于怎么分,把单个奖品当初一类奖品就行了,库存放到redis和数据库都行。

是不是这样做就万事大吉了呢 ,还可以优化,那就是奖品预设,简单的说,比如有一万个奖品,预先生成一万条中奖纪录,用户抽中奖品后只是关联用户和抽奖纪录而不是写一条数据,这样就避免了超写。

最后补充一个小技巧,比如100万人竞争10个奖品,实际上没有必要100%的用户都参与抽奖,可以让99% 的用户直接返回不中奖,降低计算成本,相当两次抽奖,第一次是抽取实际抽奖资格。

 

系统的讲一讲 怎么设计一个高并发的系统

原文:https://www.cnblogs.com/du1216/p/13054646.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!