专栏名称: 狗厂
目录
相关文章推荐
51好读  ›  专栏  ›  狗厂

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

狗厂  · 掘金  ·  · 2018-05-17 02:24

正文

本系列的最后一篇,现在草草地把这个系列结束了,期待日后对内容的丰富。

扩容

垂直扩容(纵向扩展)

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

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

水平扩容(横向扩展)

增加更多服务成员

但会增加网络、数据库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是一样的。

消息队列

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







请到「今天看啥」查看全文