高并发 - 扩容
垂直扩容(纵向扩展) : 提高系统部件能力
比如:增加内存垂直扩容的主要是提高系统部件的能力,但会增大单个服务中其他软件设施的依赖与管理、服务内部复杂度
水平扩容(横向扩展) : 增加更多系统成员来实现
比如:加服务器实现水平扩容主要是增加更多的成员来分担压力,但会增加网络、数据库 IO 开销、管理多个服务器的难度
扩容 - 数据库
读操作扩展
加缓存,结合 memcathe、redis、CDN 等构建一个健壮的缓存系统。如果系统超负荷运行,将更多的数据放在缓存中来缓解系统的读压力。采用水平扩容没有太大的意义,因为性能的瓶颈不在写操作,所以不需要实时去完成,用更多的服务器来分担压力性价比太低。所以针对单个系统去强化它的读性能就可以了
写操作扩展
如 Cassandra、Hbase 等。和大多数的关系型数据库不同,这种数据存储会随着增长增加更多的节点。也可以考虑垂直扩容提升单个数据库的性能,但会发现资金与硬盘的 IO 能力是有限的,所以需要增加更多数据库来分担写的压力。
高并发 - 缓存
缓存特征
1.命中率 : 命中数/(命中数+未命中数)
2.最大元素(最大空间)
3.清空策略
缓存分类
1.本地缓存
2.分布式缓存:Memcache,redis
缓存常见问题
1.缓存一致性
数据库的数据和缓存中的数据保持一致.
2.缓存并发问题
获取缓存的时候加锁,获取完释放锁
3.缓存穿透
一般的缓存系统,都是按照 key 去缓存查询,如果不存在对应的 value,就应该去后端系统查找(比如 DB)。一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
3-1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。
3-2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。
4.缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
如何避免?
4-1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
4-2:做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期
4-3:不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
高并发 - 消息队列
消息队列特征
1.与业务无关,只做消息分发
2.FIFO.先投递先到达
3.容灾,节点的动态增删和消息的持久化
4.性能,吞吐量提升,系统内部效率提高
消息队列的好处
1.解耦
2.削峰,流量控制
3.异步,最终一致性
4.广播
高并发 - 应用拆分
拆分原则:
1.业务优先,确定业务边界
2.循序渐进,边拆分边测试
3.兼顾技术:重构,分层
4.可靠测试
拆分的思考:
1.应用之间的通信:RPC(dubbo 等)、消息队列
消息传输适用于传输数据包小但是数据量大,对实时性要求不高的场景。比如下单成功后通过短信通知用户。而选用 RPC 框架实时性更高一些。你应该知道的 RPC 原理
2.应用之间的数据库设计:每个应用都有独立的数据库
3.避免事务操作跨应用,分布式事务是一个非常消耗资源的问题。这样应用和应用的耦合度降低。
应用服务化(Dubbo RPC,Spring Cloud 微服务)