中石油智能文传项目

我要开发同款
proginn15392452602022年10月17日
274阅读

作品详情

中石油智能文传项目项目背景:为100多万中石油员工提供智能办公服务,可以快速高效的线上完成公文、督办、信息、会议等业务项目职责:4个系统以及三个关联方的整体计划、协调工作,并独立完成一级督办系统从0到1的DDD建模设计、开发、部署以及上线工作工作业绩:采用RocketMQ实现一级督办、二级督办、日常催办、统推督办系统解耦、异步、一致性,极大的缩短了接口的运行时间项目时间:2019.1-2020.10项目问题:1. 督办信息发布频繁Full GC技术挑战:高并发情况下一级督办发布督办信息后通知二级督办接收数据,由于对象太大导致新生代占满大量零时存活对象进入老年代 ,导致JVM每隔一小时执行一次Full GC,影响系统性能解决方案:我们机器是8核16G的,JVM参数:-Xms8g -Xmx8g -Xmn4g -XX:SurvivorRatio=6 -XX:MaxTenuringThreshold=15 -XX:PretenureSizeThreshold=3145728 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log,设计堆内存为8G,新生代为4G,Eden和Survivor的占比为6:1:1,每个Survivor区大概占600M,保证每次young GC的时候存活对象进入Survivor,减少Full GC实现效果:调高Survivor区大小后,Full GC保持在每月执行一次的概率,极大提高了系统性能2. 一级督办和二级督办强一致性分布式事务问题技术挑战:一级督办发布督办信息后需要通知二级督办接收因为接收的二级单位是多选,在下发的时候同步下发,一般情况下需要下发几百个二级、三级单位,每次下发在二级督办系统就要执行600ms以上的时间,如果单位上千则时间就会达到秒级以上,极大影响了系统性能解决方案:为了提高系统性能设计用RocketMQ异步调用二级督办,但是采用MQ会导致消息丢失、消息重复消0mG3pcQS202210101022费等问题,所以我采用RocketMQ的分布式事务机制发送half消息保证一级督办发送消息到RocketMQ解决消息丢失问题,在二级督办采用Redis nx特性保证不重复消费这个消息,采用zookeeper保证数据一致性实现效果:保证一级督办、二级督办数据最终一致性,系统间解耦,增大了系统运行效率3. 基于 nginx + redis + ehcache 3层缓存架构的缓存雪崩问题技术挑战:因为一级督办在每月1号并发量在五千以上,必须保证多级缓存的高可用,因为一些不可抗力尤其是redis全体宕机,则并发全部打到数据库,直接把数据库打死解决方案:缓存雪崩可能会导致整个系统崩溃,因此考虑了比较完善的方案,分为事前、事中、事后三个层面来应对缓存雪崩的场景。事前:确保Redis本身的高可用性,数据恢复备份、主从架构+哨兵,Redis cluster,一旦主节点挂了,从节点跟上事中:当redis不可用时,少量请求可以走缓存生产服务的本地缓存ehcache获取数据,基于hystrix对商品服务和redis操作做限流保护 配置降级、超时、熔断策略;从而保证发生缓存雪崩时缓存生产服务不会被拖死事后:基于redis的数据备份,快速将redis重新跑起来对外提供服务实现效果:使用事前,事中,事后一整套方案确保了系统的的高可用性4. 分布式缓存重建并发冲突解决方案技术挑战:在特殊场景下数据在所有的缓存中都不存了,就需要重新查询数据写入缓存、重建缓存、分布式重建缓存在不同的机器上,不同的服务实例中,去做上面的事情,就会导致多个机器分布式重建去读取相同的缓存,再写入缓存,可能导致旧数据覆盖掉新数据解决方案:基于zookeeper分布式锁的解决方案变更缓存重建以及空缓存请求重建,更新redis之前,都需要先获取商品id的分布式锁拿到分布式锁之后,需要根据时间版本比较一下,如果自己的版本新于redis中的版本,那么就更新,否则就不更新。如果拿不到分布式锁,那么就等待,直到自己获取到分布式锁实现效果:使同服务的不同实例强制按顺序去更新缓存,杜绝了旧数据覆盖新数据的问题5. 获取督办信息时缓存穿透导致的MySQL压力倍增问题技术挑战:在并发较高时,大量的请求没有命中缓存,可能导致大量流量全打在商品服务的MySQL上,导致MySQL压力过大,有随时被打死的风险。解决方案:使用hystrix线程池对商品服务进行限流,正常情况下,设置10个线程,并设置等待队列。实现效果:避免了MySQL被打死的风险,确保了MySQL的可用性。6. Nginx缓存命中率低问题技术挑战:用户流量是均匀打落到各个nginx上去的,实际上每个nginx都会发送请求去redis上获取缓存数据,放到自己的本地,缓存命中率很低而且导致redis的压力暴增。解决方案:双层nginx部署架构 + lua脚本实现一致性hash流量分发策略实现效果实现效果:Nginx缓存命中率提升了,降低了redis的压力7. 数据库分库分表技术挑战:随着时间的推移数据库每张表中的数据量越来越大,尤其是督办信息表,单表数据量太大导致sql执行效率降低解决方案:使用sharding-jdbc,将数据库水平拆分为16个库,每个库16张表,将之前的单表分成了256张表,部署2台数据库物理服务器,数据库服务器配置为8核32G,每台物理服务器上放8个逻辑库,分库分表完成后订单表单表数据量在120万左右。最开始采用程序对数据进行双写不停机迁移,之后如果数据量再过大直接成倍扩容物理数据库服务器数量即可。实现效果:将数据均匀的分到了各个库的各个表里,减少了单表数据量,提高了sql查询效率,同时实现了动态的缩容和扩容8. 督办信息创建等核心接口的幂等性保障技术挑战:服务之间的重试调用,服务重复调用会导致重复创建督办信息,从而导致系统数据出现混乱。解决方案:在开始业务逻辑处理之前,首先使用接口类名称+接口方法名称+订单唯一标识拼接这个请求对应的唯一标识,然后基于Redis nx特性插入这个key查看是否创建督办信息的幂等性。实现效果:通过Redis nx特性,保障了督办信息创建数据的正确性。
查看全文
声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论