关键点和注意事项-思路-高并发系统设计 (关键点和注意点的区别)
高并发系统是一种可以同时处理大量并发请求的系统。设计高并发系统需要考虑以下几个方面:
- 系统架构设计
- 数据库设计
- 缓存设计
- 负载均衡设计
- 高可用性设计
- 监控与调优
系统架构设计
系统架构设计是高并发系统设计的基础。在设计系统架构时,需要考虑以下几点:
- 系统的业务需求
- 系统的并发处理能力要求
- 系统的可扩展性要求
- 系统的安全性要求
根据业务需求和技术选型,可以采用不同的系统架构设计,例如:单体架构、微服务架构、分布式架构等。
数据库设计
数据库设计是高并发系统设计中的另一个关键方面。在设计数据库时,需要考虑以下几点:
- 数据库类型(如关系型数据库、NoSQL数据库等)的选择
- 数据库表的结构设计
- 数据库索引的建立
- 数据库连接池的配置
对于高并发系统,通常会使用关系型数据库或NoSQL数据库。关系型数据库具有事务支持和数据一致性保证,而NoSQL数据库具有高性能和可扩展性。
缓存设计
缓存设计可以有效提高高并发系统的性能。在设计缓存时,需要考虑以下几点:
- 缓存类型(如内存缓存、分布式缓存等)的选择
- 缓存数据的有效期
- 缓存的淘汰策略
- 缓存的并发控制
对于高并发系统,通常会使用内存缓存或分布式缓存。内存缓存具有高性能,而分布式缓存具有可扩展性。
负载均衡设计
负载均衡设计可以将请求均匀地分发到多个服务器上,从而提高系统的并发处理能力。在设计负载均衡时,需要考虑以下几点:
- 负载均衡算法的选择
- 负载均衡器的配置
- 负载均衡器的健康检查
- 负载均衡器的容错机制
对于高并发系统,通常会使用硬件负载均衡器或软件负载均衡器。硬件负载均衡器具有高性能,而软件负载均衡器具有可配置性和灵活性。
高可用性设计
高可用性设计可以保证系统在出现故障时仍能继续提供服务。在设计高可用性时,需要考虑以下几点:
- 系统冗余的设计
- 故障转移和恢复机制的设计
- 容错机制的设计
- 灾难恢复措施的设计
对于高并发系统,通常会采用集群部署、多机房部署或异地多活部署等方式来提高系统的可用性。
监控与调优
监控与调优是高并发系统运维的重要环节。在监控与调优时,需要考虑以下几点:
- 系统性能指标的监控
- 系统资源利用率的监控
- 系统故障的报警
- 系统性能调优的措施
对于高并发系统,通常会使用监控系统和调优工具来对系统进行监控和调优。
关键点说明
- 可扩展性:高并发系统需要具有良好的可扩展性,以适应业务需求的增长。
- 性能:高并发系统需要具有良好的性能,以满足业务对并发处理能力的需求。
- 安全性:高并发系统需要具有良好的安全性,以保护系统和数据免受攻击。
- 灵活性:高并发系统需要具有良好的灵活性,以应对业务需求的变化。
注意事项
- 设计高并发系统需要综合考虑系统的可扩展性、性能、安全性、灵活性等因素。
- 高并发系统的设计需要结合实际需求和技术选型,合理设计系统架构和实现方案。
- 高并发系统的运维需要持续的监控和调优,以保证系统的正常运行。
大数据量高并发访问数据库结构的设计
大数据量高并发访问数据库结构的设计如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能。 所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的。 在一个系统分析、设计阶段,因为数据量较小,负荷较低。 我们往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程。 所以在考虑整个系统的流程的时候,我们必须要考虑,在高并发大数据量的访问情况下,我们的系统会不会出现极端的情况。 (例如:对外统计系统在7月16日出现的数据异常的情况,并发大数据量的的访问造成,数据库的响应时间不能跟上数据刷新的速度造成。 具体情况是:在日期临界时(00:00:00),判断数据库中是否有当前日期的记录,没有则插入一条当前日期的记录。 在低并发访问的情况下,不会发生问题,但是当日期临界时的访问量相当大的时候,在做这一判断的时候,会出现多次条件成立,则数据库里会被插入多条当前日期的记录,从而造成数据错误。 ),数据库的模型确定下来之后,我们有必要做一个系统内数据流向图,分析可能出现的瓶颈。 为了保证数据库的一致性和完整性,在逻辑设计的时候往往会设计过多的表间关联,尽可能的降低数据的冗余。 (例如用户表的地区,我们可以把地区另外存放到一个地区表中)如果数据冗余低,数据的完整性容易得到保证,提高了数据吞吐速度,保证了数据的完整性,清楚地表达数据元素之间的关系。 而对于多表之间的关联查询(尤其是大数据表)时,其性能将会降低,同时也提高了客户端程序的编程难度,因此,物理设计需折衷考虑,根据业务规则,确定对关联表的数据量大小、数据项的访问频度,对此类数据表频繁的关联查询应适当提高数据冗余设计但增加了表间连接查询的操作,也使得程序的变得复杂,为了提高系统的响应时间,合理的数据冗余也是必要的。 设计人员在设计阶段应根据系统操作的类型、频度加以均衡考虑。 另外,最好不要用自增属性字段作为主键与子表关联。 不便于系统的迁移和数据恢复。 对外统计系统映射关系丢失(******************)。 原来的表格必须可以通过由它分离出去的表格重新构建。 使用这个规定的好处是,你可以确保不会在分离的表格中引入多余的列,所有你创建的表格结构都与它们的实际需要一样大。 应用这条规定是一个好习惯,不过除非你要处理一个非常大型的数据,否则你将不需要用到它。 (例如一个通行证系统,我可以将USERID,USERNAME,USERPASSWORD,单独出来作个表,再把USERID作为其他表的外键)表的设计具体注意的问题:1、数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率。 2、能够用数字类型的字段尽量选择数字类型而不用字符串类型的(电话号码),这会降低查询和连接的性能,并会增加存储开销。 这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。 3、对于不可变字符类型char和可变字符类型varchar都是8000字节,char查询快,但是耗存储空间,varchar查询相对慢一些但是节省存储空间。 在设计字段的时候可以灵活选择,例如用户名、密码等长度变化不大的字段可以选择CHAR,对于评论等长度变化大的字段可以选择VARCHAR。 4、字段的长度在最大限度的满足可能的需要的前提下,应该尽可能的设得短一些,这样可以提高查询的效率,而且在建立索引的时候也可以减少资源的消耗。 5、基本表及其字段之间的关系, 应尽量满足第三范式。 但是,满足第三范式的数据库设计,往往不是最好的设计。 为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。 6、若两个实体之间存在多对多的关系,则应消除这种关系。 消除的办法是,在两者之间增加第三个实体。 这样,原来一个多对多的关系,现在变为两个一对多的关系。 要将原来两个实体的属性合理地分配到三个实体中去。 这里的第三个实体,实质上是一个较复杂的关系,它对应一张基本表。 一般来讲,数据库设计工具不能识别多对多的关系,但能处理多对多的关系。 7、主键PK的取值方法,PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串, 由程序自动加1来实现。 也可以是有物理意义的字段名或字段名的组合。 不过前者比后者好。 当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引占用空间大,而且速度也慢。 8、主键与外键在多表中的重复出现, 不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。 非键字段的重复出现, 才是数据冗余!而且是一种低级冗余,即重复性的冗余。 高级冗余不是字段的重复出现,而是字段的派生出现。 〖例4〗:商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,而且是一种高级冗余。 冗余的目的是为了提高处理速度。 只有低级冗余才会增加数据的不一致性,因为同一数据,可能从不同时间、地点、角色上多次录入。 因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。 9、中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓库除外)。 临时表是程序员个人设计的,存放临时记录,为个人所用。 基表和中间表由DBA维护,临时表由程序员自己用程序自动维护。 10、防止数据库设计打补丁的方法是“三少原则” (1) 一个数据库中表的个数越少越好。 只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计; (2) 一个表中组合主键的字段个数越少越好。 因为主键的作用,一是建主键索引,二是做为子表的外键,所以组合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间; (3) 一个表中的字段个数越少越好。 只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许多空余的字段。 所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。 这个方法很简单,有的人就是不习惯、不采纳、不执行。 数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点。 “三少”是一个整体概念,综合观点,不能孤立某一个原则。 该原则是相对的,不是绝对的。 “三多”原则肯定是错误的。 试想:若覆盖系统同样的功能,一百个实体(共一千个属性) 的E--R图,肯定比二百个实体(共二千个属性)的E--R图,要好得多。 提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。 数据集成的步骤是将文件系统集成为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。 集成的程度越高,数据共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。 提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意设计数据库表的“废品堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。 “三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。 “三少”原则是少而精的原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。 11、在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是: (1) 在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。 (2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方式用编程语言计算处理完成之后,最后才入库追加到表中去。 (3) 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。 水平分割的做法是,以该表主键PK的某个值为界线,将该表的记录水平分割为两个表。 若发现某个表的字段太多,例如超过八十个,则垂直分割该表,将原来的一个表分解为两个表。 (4) 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。 (5) 在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。 总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三个层次上同时下功夫。 主键设计:1、不建议用多个字段做主键,单个表还可以,但是关联关系就会有问题,主键自增是高性能的。 2、一般情况下,如果有两个外键,不建议采用两个外键作为联合住建,另建一个字段作为主键。 除非这条记录没有逻辑删除标志,且该表永远只有一条此联合主键的记录。 3、一般而言,一个实体不能既无主键又无外键。 在E—R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 主键与外键的设计,在全局数据库的设计中,占有重要地位。 当全局数据库的设计完成以后,有个美国数据库设计专家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核心(数据模型)的高度抽象思想。 因为:主键是实体的高度抽象,主键与、外键的配对,表示实体之间的连接。
(二)微信红包高并发系统设计方案(1)
2017年1月28日,正月初一,微信公布了用户在除夕当天收发微信红包的数量——142亿个,而其收发峰值也已达到76万每秒。 百亿级别的红包,如何保障并发性能与资金安全?这给微信带来了超级挑战。 面对挑战,微信红包在分析了业界“秒杀”系统解决方案的基础上,采用了 SET化、请求排队串行化、双维度分库表 等设计,形成了独特的高并发、资金安全系统解决方案。 实践证明,该方案表现稳定,且实现了除夕夜系统零故障运行。 概要: 一、业务 特点 :海量的并发要求;严格的安全级别 二、技术 难点 :并发请求抢锁;事务级操作量级大;事务性要求严格 三、解决高并发问题 通常 使用的 方案 : 1.使用内存操作替代实时的DB事务操作(优点:内存操作替代磁盘操作,提高了并发性能。 ) 2使用乐观锁替代悲观锁。 应用于微信红包系统,则会存在下面三个问题:滚并返回失败;并发大失败,小成功。 DB压力大。 四、微信 红包 系统的高并发解决 方案 : 1.系统垂直SET化,分而治之。 2.逻辑Server层将请求排队,解决DB并发问题。 3.双维度库表设计,保障系统性能稳定 类似“秒杀”活动,群里发一个红包=“秒杀”商品上架;抢红包的动作=“秒杀”的查询库存;拆红包=“秒杀” 同一时间有10万个群里的用户同时在发红包,那就相当于同一时间有10万个“秒杀”活动发布出去。 10万个微信群里的用户同时抢红包,将产生海量的并发请求。 微信红包是微信支付的一个商户,提供资金流转服务。 用户发红包=购买一笔“钱”(在微信红包这个商户上),并且收货地址是微信群。 当用户支付成功后,红包“发货”到微信群里,群里的用户拆开红包后,微信红包提供了将“钱”转入折红包用户微信零钱的服务。 资金交易业务比普通商品“秒杀”活动有更高的安全级别要求。 普通的商品“秒杀”商品由商户提供,库存是商户预设的,“秒杀”时可以允许存在“超卖”、“少卖”的情况。 但是对于微信红包,100元不可以被拆出101元;领取99元时,剩下的1元在24小时过期后要精确地退还给发红包用户,不能多也不能少。 在介绍微信红包系统的技术难点之前,先介绍下简单的、典型的商品“秒杀”系统的架构设计,如下图所示。 该系统由接入层、逻辑服务层、存储层与缓存构成。 Proxy处理请求接入,Server承载主要的业务逻辑,Cache用于缓存库存数量、DB则用于数据持久化。 一个“秒杀”活动,对应DB中的一条库存记录。 当用户进行商品“秒杀”时,系统的主要逻辑在于DB中库存的操作上。 一般来说,对DB的操作流程有以下三步:a. 锁库存 b. 插入“秒杀”记录 c. 更新库存 a.锁库存是为了 避免 并发请求时出现“ 超卖 ”情况。 同时要求这 三步操作 需要在 一个事务 中完成(难点:并发请求抢锁)。 第一个事务完成提交之前这个锁一直被第一个请求占用,后面的所有请求需要 排队等待 。 同时参与“秒杀”的用户越多,并发进DB的请求越多,请求 排队越严重 。 红包系统的设计上, 除了并发请求抢锁之外,还有以下两个突出难点 :首先,事务级操作量级大 。 上文介绍微信红包业务特点时提到,普遍情况下同时会有数以万计的微信群在发红包。 这个业务特点映射到微信红包系统设计上,就是有数以万计的“并发请求抢锁”同时在进行。 这使 得DB的压力 比普通单个商品“库存”被锁要大很多倍。 其次,事务性要求严格 。 微信红包系统本质上是一个资金交易系统,相比普通商品“秒杀”系统有更高的事务级别要求。 普通商品“秒杀”活动系统,解决高并发问题的方案,大体有以下几种: 如图2所示,将“实时扣库存”的行为上移到 内存Cache中操作 ,内存Cache操作成功直接给Server返回成功,然后 异步落DB持久化 。 优点:提高了并发性能。 缺点: 在内存操作 成功 但 DB持久化失败 ,或者内存 Cache故障 的情况下,DB持久化会 丢数据 ,不适合微信红包这种资金交易系统。 商品“秒杀”系统中,乐观锁的具体应用方法,是在DB的“库存”记录中维护一个版本号。 在更新“库存”的操作进行前,先去DB获取当前版本号。 在更新库存的事务提交时,检查该版本号是否已被其他事务修改。 如果版本没被修改,则提交事务,且版本号加1;如果版本号已经被其他事务修改,则回滚事务,并给上层报错。 这个方案解决了“并发请求抢锁”的问题,可以提高DB的并发处理能力。 应用于微信红包系统,则会存在下面三个问题 : 1.在并发抢到相同版本号的拆红包请求中, 只有一个能拆红包成功 , 其他的请求 将事务回滚并返回失败,给用户 报错 ,用户体验完全不可接受。 2.将会导致 第一时间 同时拆红包的用户有一部分直接 返回失败 ,反而那些“ 手慢 ”的用户,有可能因为 并发减小 后拆红包 成功 ,这会带来用户体验上的负面影响。 3.会带来 大数量 的 无效 更新 请求 、事务 回滚 ,给 DB 造成不必要的额外 压力 。 微信红包用户发一个红包时,微信红包系统生成一个ID作为这个红包的唯一标识。 接下来这个红包的所有发红包、抢红包、拆红包、查询红包详情等操作,都根据这个ID关联。 红包系统根据这个红包ID,按一定的规则(如按ID尾号取模等),垂直上下切分。 切分后,一个垂直链条上的逻辑Server服务器、DB统称为一个SET。 各个SET之间相互独立,互相解耦。 并且同一个红包ID的所有请求,包括发红包、抢红包、拆红包、查详情详情等,垂直stick到同一个SET内处理,高度内聚。 通过这样的方式,系统将所有红包请求这个巨大的洪流分散为多股小流,互不影响,分而治之,如下图所示。 这个方案解决了同时存在海量事务级操作的问题,将海量化为小量。 红包系统是资金交易系统,DB操作的事务性无法避免,所以会存在“并发抢锁”问题。 但是如果到达DB的事务操作(也即拆红包行为)不是并发的,而是串行的,就不会存在“并发抢锁”的问题了。 按这个思路,为了使拆红包的事务操作串行地进入DB,只需要将请求在 Server层以FIFO ( 先进先出 )的方式排队,就可以达到这个效果。 从而问题就集中到Server的FIFO队列设计上。 微信红包系统设计了分布式的、轻巧的、灵活的FIFO队列方案。 其具体实现如下:首先,将同一个红包ID的所有请求stick到同一台Server。 上面SET化方案已经介绍,同个红包ID的所有请求,按红包ID stick到同个SET中。 不过在同个SET中,会存在多台Server服务器同时连接同一台DB(基于容灾、性能考虑,需要多台Server互备、均衡压力)。 为了使同一个红包ID的所有请求,stick到同一台Server服务器上,在SET化的设计之外,微信红包系统添加了一层基于红包ID hash值的分流,如下图所示。 其次,设计单机请求排队方案。 将stick到同一台Server上的所有请求在被接收进程接收后,按红包ID进行排队。 然后 串行地进入worker进程 (执行业务逻辑)进行处理,从而达到 排队 的效果,如下图所示。 最后,增加memcached控制并发。 为了 防止 Server中的请求队列过载导致队列被降级,从而所有请求 拥进DB ,系统增加了与Server服务器同机部署的 memcached ,用于控制拆同一个红包的 请求并发数 。 具体来说,利用memcached的 CAS原子累增操作 ,控制同时进入 DB执行拆红包事务的请求数 ,超过预先设定数值则 直接拒绝服务 。 用于 DB负载升高时的降级 体验。 通过以上三个措施,系统有效地 控制了DB的“并发抢锁” 情况。 红包系统的分库表规则,初期是根据 红包ID的hash值 分为多库多表。 随着红包数据量逐渐增大,单表数据量也逐渐增加。 而DB的性能与单表数据量有一定相关性。 当单表数据量达到一定程度时,DB性能会有大幅度下降,影响系统性能稳定性。 采用 冷热分离 ,将历史冷数据与当前热数据分开存储,可以解决这个问题。 系统在以 红包ID维度 分库表的基础上,增加了以 循环天分表的维度 ,形成了 双维度分库表 的特色。 具体来说,就是分库表规则像db_xx.t_y_dd设计,其中,xx/y是红包ID的 hash值后三位 ,dd的取值范围在01~31,代表一个月天数最多 31 天。 通过这种双维度分库表方式,解决了DB单表数据量膨胀导致性能下降的问题,保障了系统性能的稳定性。 同时,在热冷分离的问题上,又使得数据搬迁变得简单而优雅。 综上所述,微信红包系统在解决高并发问题上的设计,主要采用了SET化分治、请求排队、双维度分库表等方案,使得单组DB的并发性能 提升了8倍 左右,取得了很好的效果。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。