最近在面试被问到这个问题,整理下
按照不同的层级说明
展示层
cdn静态文件加速
例如 HTML、CSS、JS、图片这些静态资源非常适合放到CDN上进行缓存。
CDN服务商的节点是全国各地的,你的一份静态文件会被缓存到各个节点,用户访问时,会自动读取最近的节点。
CDN是静态内容的常用缓存策略。
前端页面负载
1、压缩和合并资源:
压缩CSS和JavaScript文件可以减小文件大小,提高加载速度。同时,将多个CSS和JavaScript文件合并成一个文件可以减少HTTP请求次数。
2、图片优化:
使用适当的图片格式(如JPEG、PNG)和压缩工具来减小图片文件大小,同时保持较好的视觉效果。还可以使用Lazy Load技术,延迟加载页面中的图片,减少首次加载时的数据量。
3、CDN加速:
使用内容分发网络(CDN)来分发静态资源,将静态文件缓存到离用户较近的CDN节点上,减少网络延迟,提高资源加载速度。
4、预加载和预渲染:
通过预加载相关资源,如CSS、JavaScript、图片等,可以在页面加载完成前提前获取这些资源,减少后续请求的延迟。预渲染则是在后台渲染页面内容,使得用户在访问时能够立即看到完整的页面内容。
5、懒加载:
将非关键性的内容(如图片、视频等)延迟加载,当用户需要查看时再进行加载。这样可以减少首次加载时间,提升页面的响应速度。
6、缓存策略:
合理设置资源缓存策略,使得重复访问的资源可以从浏览器缓存中获取,减少对服务器的请求。可以通过设置HTTP头部来控制资源的缓存行为。
7、前端框架和库的优化:使用轻量级的前端框架或库,并保持其更新和优化。避免使用过多的第三方插件和依赖,以减少不必要的资源加载和执行时间。
业务层
将大型的业务服务纵向拆分成多个小的微服务,每个微服务负责处理特定的功能模块或业务流程。这样可以降低单个服务的负载压力,并且实现模块水平扩展。
API层
分布式架构:
将API接口进行拆分,分布式部署在多台服务器上。
每台服务器独立处理部分请求,避免单点故障,并提高整体的并发能力。
1、负载均衡:
通过云服务厂商的slb/alb等。
通过负载均衡技术将请求分发到多台服务器上,平衡服务器的负载压力。
可以使用硬件负载均衡器(如F5、Nginx)或者软件负载均衡器(如HAProxy、Apache mod_proxy_balancer)来实现。
2、限流和排队:
通过设置请求限流策略,限制同时访问接口的请求数量,防止突发大量请求导致系统崩溃。
可以使用令牌桶算法、漏桶算法、滑动窗口算法等进行限流控制。
对于超过系统承载能力的请求,可以将其放入队列中进行排队处理。
3、RPC调用
通过RPC调用服务,例如dubbo
实现接口调用服务时的负载功能,高并发时服务的动态扩容
4、缓存
合理使用缓存机制可以减轻后端服务器的压力,提高响应速度。
可以使用内存缓存(如Redis)或者分布式缓存(如Memcached)来缓存经常访问且不经常变动的数据,减少对后端系统的请求。
缓存需要注意的3个问题:
1. 缓存雪崩。如果缓存宕机,数据库可能会被压垮,这是缓存高可用的问题。
2. 缓存穿透。缓存没宕机,但短时间内大量被查询的key没在缓存中,直接访问数据库,有压垮的风险。
3. 大量的热点key过期。和缓存穿透类似,因为key过期,短时间内大量请求数据库。
5、弹性扩容:
根据实际需求,通过监控系统负载情况,动态调整服务器数量,进行弹性扩容。
可以借助云计算平台(如AWS、阿里云)提供的自动伸缩功能来实现,或者自行实现动态扩容。
异步处理:
对于耗时较长的操作,可以采用异步处理方式,将请求放入消息队列中,然后由后台线程或者其他服务来异步处理。这样可以避免阻塞主线程,提高并发处理能力。
服务层
1、服务拆分和水平扩展:
将大型的微服务拆分成多个小的服务单元,并通过水平扩展来增加实例数量,以提高系统的并发能力。
可以使用容器编排工具(如Kubernetes)来管理服务的伸缩和调度。
2、服务负载
可使用网关功能(如spring cloud alibaba gataway,zuul)等
高并发时可高效率利用各个服务器之间的调配,挺高相应速度
3、服务发现RPC
使用服务注册与发现机制(如Dubbo、OpenFeinConsul、Eureka)来分发请求和自动发现可用的服务实例,以实现请求的平衡和并发处理。
实现业务解耦合
4、缓存和数据预取:
合理使用缓存来减少对后端服务的请求次数,提高访问速度。
可以使用本地缓存(如Guava Cache)或者分布式缓存(如Redis、Memcached)来缓存经常访问的数据,并采用预取技术来预先加载数据,以减少用户请求的等待时间。
5、限流和熔断:
通过设置请求的限流策略和熔断机制来保护微服务不被过多的请求压垮。
可以使用令牌桶算法、漏桶算法进行请求限流,并使用断路器模式来实现服务的熔断和降级。
可使用sentinel实现限流和熔断
6、异步消息和事件驱动:
通过使用消息队列、事件总线等机制来实现异步通信和解耦,将请求发送到消息队列中,由消费者异步处理请求。这样可以提高系统的并发性和响应速度。
可使用rocketmq\acitivymq\kafka等mq消息机制
比如:短信业务、订单业务、扣费业务等强一致性存储和高并发支撑
7、弹性设计和故障恢复:
通过设计弹性架构和实施故障恢复策略,使得系统能够在面对高并发和故障时保持可用性。
可以使用断路器模式、自适应算法等来处理异常情况,并及时进行服务降级和故障转移。
结构数据库
1、数据库连接池:
使用数据库连接池管理数据库连接的创建和销毁,以减少每次请求都需要建立新的数据库连接的开销。连接池可以复用已经建立的连接,并且根据系统负载情况来动态调整连接池的大小。
2、数据库缓存:
合理使用数据库缓存技术(如Redis、Memcached、Guava),将查询结果等热点数据缓存在内存中,减少对数据库的访问次数和响应时间。
3、数据库索引优化:
通过合理的索引设计来加快查询操作的速度。分析业务场景和查询需求,选择合适的字段作为索引,并确保索引的统计信息是最新的。避免过多的索引,因为索引会增加写入操作的成本。
4、分库分表:
对于大型系统或者数据量较大的应用,可以考虑使用分库分表技术来拆分数据和负载,提高数据库的横向扩展能力和并发处理能力。
可以使用sharding、cat等分库分表
5、数据库主从复制:
通过数据库主从复制,将读操作分担到从库,减轻主库的负载压力。
从库可以提供读取性能的提升,同时也增加了系统的可用性和容错能力。
6、数据库资源调优:
根据实际需求,合理配置数据库服务器的硬件资源(如CPU、内存、磁盘),以提高数据库的并发处理能力。还可以通过数据库参数调优来提升数据库的性能和并发能力。
redis缓存层
1、连接池:
在应用程序中使用Redis连接池来管理与Redis服务器的连接。连接池可以复用已经建立的连接,减少每次请求都需要创建和销毁连接的开销,提高性能和并发能力。
2、使用redis客户端
常用客户端Redssion
3、数据分片:
将数据按照一定的规则进行分片存储到多个Redis节点上,以实现数据的水平分布和负载均衡。
可以通过客户端的哈希算法或者Redis集群功能来进行数据分片。
4、使用Pipeline批量操作:
使用Redis的Pipeline功能,将多个命令打包成一个批量操作发送给Redis服务器,减少网络传输的开销和延迟。这样可以提高请求的响应速度和处理能力。
5、合理设置过期时间:
对于缓存数据,合理设置过期时间来控制缓存的有效期。根据业务需求和数据更新频率,灵活设置过期时间,避免缓存雪崩和过期数据带来的问题。
6、使用Lua脚本:
Redis支持Lua脚本,可以将多个命令封装成一个原子操作,减少网络通信的开销,并且执行脚本时是原子的,保证了操作的一致性。
使用Redis集群:
在需要处理大量并发请求的场景下,可以使用Redis集群来分散数据和负载。Redis集群采用分片和复制机制,提供了高可用性和横向扩展能力。
缓存预热:
在系统启动或者低峰期,通过提前加载热点数据到Redis中,以减少高并发时对数据库的访问压力。可以使用定时任务或者异步加载方式来进行缓存预热。
注意事项
缓存可以有效的保护数据库,提高读性能,分为本地缓存,或者集中式的 memcached/redis 缓存。
缓存的更新方式有2种:
1. 主动更新,数据库记录发生变化时,主动更新缓存数据。
2. 被动更新,读缓存时,如果缓存过期,就更新缓存。
缓存需要注意的3个问题:
3. 缓存雪崩。如果缓存宕机,数据库可能会被压垮,这是缓存高可用的问题。
4. 缓存穿透。缓存没宕机,但短时间内大量被查询的key没在缓存中,直接访问数据库,有压垮的风险。
5. 大量的热点key过期。和缓存穿透类似,因为key过期,短时间内大量请求数据库。
这些问题和缓存回源策略有关:
- 不回源。只查询缓存,如果缓存中没有,直接返回空,这种方式肯定是主动更新方式,并且不设置过期时间,不会有上面的几个问题。
- 回源。如果缓存中没有,就查询数据库然后更新缓存,这种方式就要考虑上面的几个问题。
Elasticsearch层
1. 分片和副本:
将索引数据划分为多个分片,并在每个分片上创建多个副本。通过分片和副本机制,可以实现数据的分布式存储和负载均衡,提高读写操作的并发处理能力。
2. 节点水平扩展:
通过增加ES节点来水平扩展系统的处理能力。每个节点都可以存储索引的部分数据,并参与请求处理和数据分发。可以根据实际需求,动态添加或移除节点。
3. 负载均衡:
使用负载均衡器(如Nginx、HAProxy)将请求分发到不同的ES节点上,实现请求的平衡和并发处理。负载均衡器可以根据节点的负载情况进行动态调整。
4. 故障转移和恢复:
ES集群中的节点可能会因故障或维护而下线,为了保证高可用性和数据完整性,需要设置合适的故障转移和恢复机制。ES的集群会自动进行数据重分配和副本选举,以保证数据的可用性。
5. 合理设置索引和映射:
对于索引的设计,需要根据业务需求和查询模式来选择合适的分片数量和副本数量。同时,也要关注索引映射的设置,避免映射冲突和不必要的字段分析,以提高搜索和写入性能。
6. 缓存和预热:
ES支持缓存机制,可以通过合理设置缓存策略来减少重复的查询操作,提高查询性能。此外,在系统启动或者低峰期,可以使用预热技术将热点数据加载到缓存中,以加速高并发请求的响应。
7. 查询优化:
对于频繁执行的查询操作,可以进行查询优化,包括调整查询语句、使用合适的查询类型、设置合理的过滤条件等,以提高查询速度和并发处理能力。
8. 索引刷新间隔调优:
ES有一个索引刷新机制,用于将内存中的数据刷新到磁盘上。合理调整索引刷新间隔可以平衡数据的实时性与写入性能。
9. 监控和调优:
通过监控工具(如Elasticsearch的监控插件、Prometheus)对ES集群的负载、性能指标进行实时监控,并根据监控数据进行性能调优和容量规划。
外传
😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥