Java多线程与高并发(六):高并发解决思路

扩容

垂直扩容(纵向扩展)

提高单个服务(服务器、数据库)自身能力

但会增大单个服务中其他软件设施的依赖与管理、服务内部复杂度

水平扩容(横向扩展)

增加更多服务成员

但会增加网络、数据库IO开销、管理多个服务器的难度

对数据库的扩容方案

确定业务类型

  • 读操作多:采用垂直扩容方案(redis、CDN)。采用水平扩容没有太大的意义,因为性能的瓶颈不在写操作,所以不需要实时去完成,用更多的服务器来分担压力性价比太低。所以针对单个系统去强化它的读性能就可以了
  • 写操作多:采用水平扩容方案(HBase、增加服务器、数据库)。也可以考虑垂直扩容提升单个数据库的性能,但会发现资金与硬盘的IO能力是有限的,所以需要增加更多数据库来分担写的压力。

缓存

应用需要支撑大量并发量,但数据库的性能有限,所以使用缓存来减少数据库压力与提高访问性能

特征

  • 命中率 = 命中数 / (命中数 + 没有命中数)
  • 最大空间:缓存最大空间
  • 清空策略:FIFO/LFU/LRU/过期时间/随机

FIFO:最先进入缓存的数据,在缓存空间不足时被清除,为了保证最新数据可用
LFU(Least Frequently Used):最近最不常用,基于访问次数,去除命中次数最少的元素 LRU(Least Recently Used):最近最少使用,基于访问时间,在被访问过的元素中去除最久未使用的元素

本地缓存Guava Cache

其实编程时候写的成员变量、静态变量、常亮也被看做缓存

分布式缓存Redis

高并发缓存问题

缓存一致性

全量、增量同步

根据业务需求决定分布式锁

缓存并发

当大量请求访问同一个没有被缓存的数据的时候,会发送大量请求给数据库,导致数据库压力过大,还会导致一致性问题,所以解决方式就是在缓存获取的时候加上针对单个数据的锁,直到缓存被重建成功得到最新数据

缓存击穿/穿透

查询一个数据库中不存在的数据,比如商品详情,查询一个不存在的ID,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成过大地压力。

解决方案:当通过某一个key去查询数据的时候,如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认的值。

缓存失效

在高并发的环境下,如果此时key对应的缓存失效,此时有多个进程就会去同时去查询DB,然后再去同时设置缓存。这个时候如果这个key是系统中的热点key或者同时失效的数量比较多时,DB访问量会瞬间增大,造成过大的压力。

解决方案:

  1. 将系统中key的缓存失效时间均匀地错开
  2. 当我们通过key去查询数据时,首先查询缓存,如果此时缓存中查询不到,就通过分布式锁进行加锁

热点key

缓存中的某些Key(可能对应用与某个促销商品)对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,该问题的挑战在于它无法通过增加机器容量来解决。

解决方案:

  1. 客户端热点key缓存:将热点key对应value并缓存在客户端本地,并且设置一个失效时间。
  2. 将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。

消息队列

消息队列是为了解决生产和消费的速度不一致导致的问题,有以下好处:

  1. 减少请求响应时间。比如注册功能需要调用第三方接口来发短信,如果等待第三方响应可能会需要很多时间
  2. 服务之间解耦。主服务只关心核心的流程,其他不重要的、耗费时间流程是否如何处理完成不需要知道,只通知即可
  3. 流量削锋。对于不需要实时处理的请求来说,当并发量特别大的时候,可以先在消息队列中作缓存,然后陆续发送给对应的服务去处理

如果想要实现一个消息队列,可以参考这里
最简单的消息队列就是一个消息转发器,基本功能只有三个:消息存储、消息发送、消息删除,可使用LinkedBlockingQueue、ConcurrentLinkedQueue实现

应用拆分

限流

限流是为了解决高并发情况下,大量请求导致数据库或服务器压力过大出现延迟或出错的方式,在图中,如果一次性将100多万数据发送给master库,那么服务器与数据库的IO性能将会被大量占用,导致其他服务对数据库的不可用,master库还需要很久的时间将数据同步给slave库

控制某段代码在一定时间内的执行次数,可通过Guava或Semaphore实现

降级与熔断

数据库切库、分库、分表

切库

切库:数据库读写分离导致的数据库切换操作

当单个数据库的读写性能达到瓶颈的时候,可根据业务来判断读与写的比重,然后通过将数据库设置为Master-Slave模式完成读写分离并配置好所有库的读写权限。
当查询业务多余读取业务的时候,通过负载均衡,将查询的操作分担给不同的从库,从而减轻主库的压力。

可以通过Spring注解来完成配置

分库分表

当单库的性能达到瓶颈,或当单表容量达到瓶颈,通过SQL与索引的优化之后还是很慢,那么就需要分表

水平分表:表结构保持不变,根据固定的ID将数据划分到不同表中,需要在写入与查询的时候进行ID的路由
垂直分表:将表结构根据数据的活跃度拆分成多个表,来分别提高不同的单表处理能力

问题:

  1. 事务问题。在执行分库之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
  2. 跨库跨表的join问题。在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。
  3. 额外的数据管理负担和数据运算压力。额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算。

PS:给大家推荐一个java资源共享,学习交流群《957734884》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 佛曰:彼岸花,花开无叶,叶生无花。花叶永不相见,生生相错,彼此思念,却不得见,独自行走在彼岸路,此时花开的艳丽,却...
    Y阿晓阅读 481评论 0 2
  • 吧啦:“哎” 寻你:“嗯” 吧啦:“你一般画星星都是几个角呀” 寻你:“五个啊” 吧啦:“你见过四个的没” 寻你:...
    思兹念兹阅读 633评论 6 1
  • 一只大肚子的螳螂在丝瓜叶上转悠。虽然经常回老家,这可爱勇敢的小东西也不常见。关于螳螂的故事,似乎都是勇而无谋不自量...
    曦华阅读 194评论 0 0