百万级qps系统的实现

常规的缓存系统的设计

缓存系统大概分为2种:

1:数据量不大,拉取全量的数据,缓存在本地。

2:数据量很大,根据二八定理,只拉取活跃的数据缓存在本地。

下面我主要说下第一种方案,我们的系统主要是第一种方案,如果有时间会说下第二种。

缓存中心的设计

1:缓存中心采用一主多从的架构

2:主节点检测到数据的更新,会扫描库里全部的数据,更新到缓存里

3:数据库做了读写分离,扫描的也只是从库

4:为了避免太大的数据库压力,只有主节点拉取数据库的数据

5:从节点只拉取主节点的缓存数据,不再扫描数据库

6:并且只有从节点提供读服务,避免主节点压力过大。

主从选举怎么实现?

1:借助zookeeper的能力,

2:节点注册EPHEMERAL_SEQUENTIAL,第一个注册上的就是主节点

3:主节点失去会话或者重连会触发选举

4:这种方式和kafka基本一致

前端应用承载流量

 1:前端应用会根据缓存是否更新去拉取缓存中心的数据

2:这里只拉取从节点数据

3:本地会保存一份全量的数据

4:所有的请求都只在本地内存里响应

压测

前端要求的sla,购物车要求的是tp99:10ms,tp999:20ms,想要实现这种情况,设计上满足了是不够的,还需要做大规模的压测

1:确认系统是cpu密集型,还是io密集型

2:确保压测数据足够的大,足够的全,覆盖大部分的情况

3:明确sla

4:cpu监控和性能监控

 遇到的问题

1:性能怎么压测都压不上去?

大量的监控点和日志占用了大量的cpu,导致单机的性能上不去,通过减少监控点和调高日志级别解决

2:瞬时流量的冲击,导致tp波动?

根本原因在线程池的扩容有个过程,通过压测调节线程池大小,其根本原因系统是还有rpc,属于io密集型,通过压测找到最佳线程数

3:优化gc,年轻代大小?

当时的年轻代是1个g,大约30秒左右发生一次ygc,对于大并发的应用,最终优化的一般是年轻代,当然老年代优化也有,年轻代的gc的时间主要分为标记和复制,标记的时间影响不大,复制的影响不小,单纯的扩大年轻代的大小,如果大多数对象不需要复制,整体的时间不会增大太多,把年轻代改为3个g,系统的gc时间只增加了3ms左右,系统的tp99更稳定,吞吐也更高

4:初始加载,系统tp99性能指标剧烈波动

系统初始化,会加载大量的缓存到系统,这块的缓存,会由年轻代到老年代转换,由于存在动态年龄计算,如果连续几代超过一半,就会晋升到老年代,通过观察各代对象的大小,让一定对象提前进入到老年代,而不是让大批量的对象一块进入老年代,也避免对象一直复制,影响时间比较长。

仍然存在问题

1:系统本身并没有做增量更新,缓存更新都是更新全部的缓存,这块还有优化空间

2:并没有分为堆外内存和堆内存二部分,有好处有坏处吧,坏处就是系统可能会出现一定次数的cmsgc,好处就是数据结构更多,使用起来更方便,也更快一点

3:如果做堆内存和堆外内存,必须要做增量更新,否则内存会爆

最终在满足sla的前提下,系统单机的qps是3000以上,大促需要1000+的机器,当然增加新功能,每次大促都要重新进行压测,有时候还需要合并接口的访问,水桶能装多少水,依赖于最短的那个木板。

如果数据量很大,采用第二种方案,设计会简单不少,缓存中心就主要是redis,如果对于缓存使用的中间件感兴趣,可以搜索下caffeien,好吧,总觉得还少点什么,不够细,等我有时间想想怎么说,到此结束。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值