项目亮点总结归纳

项目亮点
如何挖掘项目中的亮点(多方向带案例) http://t.csdn.cn/dUS11

一般项目中有大数据量,高并发,负责业务可以说这些。三不沾的朋友不要慌,没法从底层下手,咱就往设计方案,性能调优和自定义组件上面靠。

亮点这个东西,说大可大说小可小,大到系统设计,底层优化,小也可以是业务流程优化,工具类。项目亮点,项目在前,在挖掘时肯定要结合项目现状进行描述,不然

也没啥说服力。

正因为sql优化是通用技能,所以你说你把所有sql都优化过也没人说啥。关键是说说怎么优化的。

sql优化我们可以从最基础的sql语句本身入手,并进一步从场景,表设计,数据库配置。架构四方面着手优化。

在优化之前,需要判断SQL语句是否是真的很慢。可能因为锁、刷新脏页、高并发、buffer pool设置过小导致SQL偶尔变慢,要判断也很简单,

看看是不是频繁出现在慢SQL日志里就行了。

如果确定是SQL语句的问题,那么就可以按照我独创的九步优化套路操作了。

1.一是规范字段名称,这一步是方便大家理解字段并清晰看到归属表。

2.二是排除所有的select *语句,包含子查询以及JOIN语句,这一步是减少传输数据。

3.三是小表驱动大表,这一步需要根据业务来判断是否调整。

4.四是创建索引,尽量多的使用联合索引,不要创建过多的索引,注意索引失效的情况,比如隐式类型转换、索引列使用函数或参与运算、like左模糊匹配。

5.五是利用覆盖索引优化。

6.六是使用where和group by的having来减少查询的数据。

7.七是通过explain去优化SQL,根据ref key extra等字段的信息来动态调整优化手段。

8.八是子查询可以换成连接查询,减少临时表创建。

9.九是调整where语句顺序,过滤数据多的条件放在前面。

场景优化例如深度分页、批量新增。

表设计优化例如冷热数据分离、增加冗余字段或中间表。

配置优化例如数据库的连接数,buffer pool优化。

架构优化就是读写分离、分库分表。

一般来说这么一套组合拳下去又快又准,由点及面,知识面肯定是够了,而且也有一定的深度。SQL的优化这块重点关注索引,了解下索引优化成本,简单来说

就是优化器是否选择使用非主键索引,是要考虑当前索引命中数据在全部数据的大致占比大小,占比小才走索引,否则全表查询。联合索引和覆盖索引需要清楚,

索引下推等优化可以了解。

工具组件

再来说点大众的,组件自然是spring boot starter,工具涉及方方面面。和业务强关联的没点技术性的就不用说了,适用性太低,多说点技术相关的。可以从redis

,加密解密等方向入手。

我在工作的时候自己整合了一些工具类和配置项通过spring boot starter方式集成到项目中,比如加密解密工具。该框架相比传统的加密方式更加简单易用,而且

支持配置文件加密,实现了mybatis的扩展接口typehandler。对入参和出参拦截后进行加密解密。

同事针对redis我是引入了redisson框架,封装了大量易用api,并且提供了分布式锁等工具。在此基础上我是封装了一些常用工具,基础思想是利用lua脚本将多个

命令封装在一起,好处有两个,分别是原子性操作以及汇总在一起的命令一次性发送减少了多次发送的网络开销。

平心而论,工具这一块可聊的点真的很少,java太卷了,轮子太多了,比如大名鼎鼎的hutool,以上都是一些比较常见的小东西,实在没得说了你再说这些。因为这

些东西说白了,也是应用别人的轮子,只是做了一个业务封装而已,最关键的要结合业务和你的思考有自己的沉淀。redis这块我引入lua脚本作为亮点,毕竟redisson

这样牛逼的框架内部都用的lua脚本来实现合并操作的原子性。

业务模块设计

(后端思想-如何设计一个操作和管理excel的业务模块)

和技术工具造轮子更多专注于技术不同,业务模块设计的重点在于设计,这一块我们会同时站在架构师和项目经理的角度去思考,去做一些基于业务模块深度定制的

技术选型和流程设计,技术上可能不会太深,这没关系,重点在于你对整个模块的统筹思考。在与人交流的时候,上来就挖技术深度其实不是上策,很多时候技术

一旦过深就会有种曲高和寡的感觉,要用简单易懂的语言体现出你的技术深度,对于大多八股高手并非易事,说的让人听不懂并不是一个良好的沟通方式,因此一个

大家都能听懂而且能拿得出手的业务模块设计才是上上之选。
性能优化

(性能优化-如何爽玩多线程来开发)

性能优化这一块绝对是走向大佬的敲门砖,能结合理论和实践讲一个好的案例出来无疑是大大的加分项,我直接叫你大佬。因为我个人对调优这块了解不透,比如服务

器调优、中间件或者程序调优都是有一定的理论,但是实践比较少,动态调优对我来说还是比较困难。目前我对JVM、Kafka、ES有一定的调优经验,对性能优化的理

论也有一定了解,但为了避免误人子弟,我还是从常见且相对简单的多线程说起。

我在项目中是大量的用到了多线程编码来提升运行效率。主要运用场景就是并行聚合处理数据,这里是用到了CompletableFuture.allOf()方法,将原本串行运行

的业务逻辑改为并行处理,比如处理A逻辑开启线程1,处理B逻辑时开启线程2,等1234所有线程都执行完毕后再汇总数据进行下一步处理,这一块思路类似于CountDownLatch。

应用相同的思路,我也可以修改for循环为并行操作,这一步借鉴parallelStream的分治法思想,将list切分成多个小list,然后开启对应数量的线程,最后还是

使用CompletableFuture.allOf()方法聚合数据。同理,将Map切成List,也能修改为并行操作,提高循环效率。

除此之外,还有一些小技巧,比如List转Map用空间换时间破解双层循环。常见的场景有,外来数据ListA对比数据库数据ListB,根据唯一值对比,常规做法是A循

环嵌套B循环,根据唯一值找匹配数据,这样就是双层循环。我们可以将ListB转换为Map,然后用唯一值做Key,那么只需要一层循环即可。

多线程这个相对说的比较简单,但是非常实用,而且大多数情况下,开发并不会或者说懒得应用这样的技巧。由此也可以引申一些知识点,比如线程池如何配置的,

你就可以说大致分为两种情况。

IO密集型的就是多开线程,小队列,因为IO不占用CPU。

CPU密集型则是要少线程,避免频繁上下文切换,队列要大,避免高并发的时候任务丢失。

技术模块设计

(Filebeat+Kafka+数据处理服务+Elasticsearch+Kibana+Skywalking日志收集系统)

技术模块这么说呢,主要是和业务模块区分开,和常规的业务开发肯定是有区别的。一说这种,肯定能联想到常规的Seata分布式事务、Kafka消息队列、

Prometheus监控、Redis等等中间件,当然做成这种肯定是大牛中的大牛了,咱不考虑这种情况。在技术深度暂时达不到那种高度的时候,学习国内手机厂商的做法,

做一个方案整合商呗,本地化改造或者整合封装都可以,得有你自己的思考。

整个日志收集系统,我是先描述了下目前的使用情况,然后聊了下技术栈以及整个日志收集的流程。接下来说了下,整个架构设计以及迭代过程,复盘了下迭代的好处。

最后聊了聊整个模块优化的部分,从技术选型应用到性能优化都有涉及,还是比较完整的一次设计过程。

补充知识点:

(io密集型任务该如何设置线程池线程数 http://t.csdn.cn/VlAxc)

合理配置线程池核心线程数(io密集型和cpu密集型)

  1. 代码查看服务器的核心数

要合理配置线程数首先要知道公司服务器是几核的

代码查看服务器核数:System.out.println(Runtime.getRuntime().availableProcessors());

  1. 合理线程数配置之CPU密集型

CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行。

CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程),而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力

就那些。PU密集型任务配置尽可能少的线程数量:一般公式:CPU核数+1个线程的线程池

  1. 合理线程数配置之IO密集型

IO包括:数据库交互,文件上传下载,网络传输等

方法一:由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数*2

方法二:IO密集型,即该任务需要大量的IO,即大量的阻塞。

在单线程上运IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待。所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速

主要就是利用了被浪费掉的阻塞时间。IO密集型时,大部分线程都阻塞,故需要多配置线程数:参考公式:CPU核数 /(1 - 阻系数)

比如8核CPU:8/(1 - 0.9)=80个线程数,阻塞系数在0.8~0.9之间
项目中遇到的问题:

接口响应超时问题排查

慢sql优化,mysql主从复制,数据延迟问题的排查:

主从复制(一主两从架构),从节点延迟超过1800s问题排查,

在DBaas上查询异常报告,并没有找到时哪句sql导致了这个问题,经过寻求总行老师的帮助,发现是delete语句

导致的,继续排查发现,导致delete出现搞延迟的原因是因为建表的时候没有增加索引,该库的结构是一主一从结构,

主表在删除数据时,不会影响,但是从表在删除数据时,由于没有建立索引,导致从表需要进行全表扫描进行删除,700

多万条数据需要全表扫描700多万次,导致了高延迟问题的出现(为什么从库是一条一条执行?因主库每删除一条数据,从库为了保证

数据的一致性,需要去找到对应的那条数据进行删除,因此触发了全盘扫描)

线程池高并发场景下的性能优化 http://t.csdn.cn/vpsAX

(线程池基本工作原理复习)

问题:线程池没用好,不小心把系统搞蹦了!

背景介绍:在生产环境繁忙时期,线程池此时正在运行多个定时RPC调用(耗时较长),定时大数据量处理的任务(耗时较长),这些任务又特别的耗时,导致很多线程都是忙碌状态,

少数线程是空闲状态,然后这个时候,系统刚好面向c端用户提供的接口有的接口有高并发访问的场景,大量http请求过来,每个请求都要提交多个任务给线程池

并发运行,导致线程池的少数空闲线程快速的跑满,然后接着大量的任务进入了线程池的队列开始排队等待。这个时候必然会导致大量http请求出现hang死的问题,

因为很多http请求的任务都是在线程池里阻塞队列排队等待,他们没法运行,http请求也就没法返回响应,给用户的感觉就是点击app/网页一类的前端,点来点去

没反应,系统出现卡顿问题。

问题剖析:

解决方法:把各种不同的任务从一个线程池里分离出来,让他们互相之间不要影响。也就是说定时RPC任务就放一个线程池里去,定时db大量数据处理任务就放另一个线程池去,

然后http请求多任务并发处理放一个独立的线程池,大家各自用自己的线程池和资源,互相之间不影响。

总结:如果线程池不区分业务隔离,有可能核心业务被边缘业务拖垮。

如果依然想只使用一个线程池,如果线程打满了,会导致接口都在等待,如果是高并发场景,我们需要接入限流,把多余的请求拒绝掉。

从20s优化到500ms,我用了这三招 http://t.csdn.cn/EPGvY

问题:在应用开发过程中,我优化了一个线上批量查询的接口,将接口性能从最初的20s,优化到目前的500ms以内。总的来说,用三招就搞定了

背景介绍:我们每天早上上班之前,都会受到一封线上慢查询接口汇总邮件,邮件中会展示接口地址,调用次数,最大耗时,平均耗时和tranceId等信息,

我看到其中有一个批量评分查询接口,最大耗时达到了20s,平均耗时也有2s。

将一个接口响应时间从2s优化到200ms以内的一个案例 http://t.csdn.cn/0JZ5o

背景介绍:在开发联调阶段发现一个接口响应时间特别长,经常超时。

问题剖析:

定位:定位性能瓶颈有两个思路,一个是通过工具去监控,一个是通过经验去猜想。

工具监控:就工具而言,推荐使用arthas,用到的是trace命令

定位到最影响性能瓶颈的函数上,继续往下跟。最后发现造成性能瓶颈的是一个网络请求,单次请求大概100多毫秒。为了避免调用的数据量太大,项目中采用分批调用的

方式,但是每个批次太小,导致请求次数过多。

假设请求n次,每次请求m毫秒(假如200ms),总耗时就是n*m毫秒(2000ms)

猜想:

常见的有:

1.慢sql会是性能瓶颈,主要原因是没有命中索引。

2.发送远程数据请求(RPC远程调用,http远程调用)

3.i/o操作等

最常见的是在循环中执行sql或者网络请求。然后审查一下自己的代码发现sql查询部分都可以命中索引,调用链路上有一个函数最终会调用http请求,而且是在一个循环里

因此最有可能造成接口延迟的是底层依赖的http请求。

解决方法:

1.既然http请求是性能瓶颈,那么尽量减少请求,或者让请求由串行改为多线程并发/并行。将串行改为并行可以使用completableFuture来实现,具体使用方式自己研修

2.减少网络请求的次数,可以将多个请求合并成一个批量接口(或者增加批量请求的每个批次的大小,批次设置可以动态配置,根据情况动态修改)

总结:

1.不去学习arthas这个新的东西,如果不去学习不了解,晕倒可以用上的场景都想不起起来去用。

2.积累在开发过程中常见的性能瓶颈的原因,以便未来遇到性能瓶颈是可以快速排查和解决问题

3.在开发阶段或者测试阶段,多看错误日志,多关注接口的响应时长等,尽早排除问题,尽早做优化
项目亮点:

分布式事务最终一致性的实现(本地消息表,基于mq的实现)

TCC分布式事务

缓存延迟双删

优化了接口响应时间st

优化了下单,支付接口的TPS和QPS

开发的应用的日活多少?系统注册用户几十万,系统日活几千的用户量,压根儿没有什么并发可言,高峰期qps每秒最多一二十并发请求罢了

qps(query per second服务器在单位时间(一秒内)处理的查询请求速率)

TPS(transaction per second 服务器在一秒内可以完成的事务数量,跑完一次完整的链路,咱们可以认为是一个TPS,每秒钟可以跑完多少次这个链路,那就是TPS了)

你做性能优化的接口 qps,tps,ts优化前是多少,优化后是多少?

系统的TPS不达标,此时如何优化 http://t.csdn.cn/B86E6

对系统进行压测,比如每秒压个几百请求到几千请求,甚至几万请求,此时发现死活压不上去,压来压去,你的系统最多每秒就处理几百个请求,压根到不了

几千个请求,此时就发现系统的TPS不达标。通常说明你的系统肯定是每个请求处理时间太长了,所以就导致你单位时间内,在有限的线程数量下,能处理的TPS

就少了,这个时候往往要先优化性能,再提TPS.

假设你一共200个线程,结果你每个请求要耗费500ms,每个线程每秒(1000ms)就只能处理2个请求(tps),200个线程每秒只能处理2*200=400个请求,

比期望的单机处理500到600个请求要少了很多。

要优化性能,那就得通过打日志的方式,或者是监控的方式,检查你服务的每个环节的性能开销,通常来说用打日志方式会细化一些,要考监控把每个细节摸清楚,也挺

难的,毕竟很多是代码细节。

把系统里的一个请求过来,每一次数据库,缓存,ES之类的操作的耗时都记录在日志里面,把你的每个请求执行链路里的每个耗时小环节,都记录清楚他,比如说一个

请求过来一共500ms,此时你发现就是某个sql语句一下子耗时了300多ms,其实其他的操作都在正常范围内。优化一下sql语句呢?这个sql语句搞了一个全表扫描,

因为写sql的时候没有考虑到索引,所以此时可以建立新的索引,或者是改写sql语句,让他可以使用到你建立好的索引,sql语句优化到100ms。

每个请求只要300ms就可以了,每个线程每秒可以处理三个请求,200个线程每秒就可以处理600个请求。

可以检查核心服务的每个环节的性能,针对性的做优化,把每个请求的时间降到最低,这样单位时间内的TPS绝对就提高了。

其次就是增加机器数量,线性扩容,比如说服务层面,每个服务单机最多抗800个请求,那扩容到部署10台机器,就可以抗8000请求,但是又得考虑依赖的数据库,MQ

,redis能不能抗下那么多的并发。

【性能优化】每秒上万并发下的springcloud参数优化实战 http://t.csdn.cn/H7bd3

一个服务A的实例里,专门调用服务B的那个线程池里的线程,总共可能就几十个。每个线程调用服务B都会卡住5秒钟。

那如果每秒钟过来几百个请求这个服务实例呢?一下子那个线程池里的线程就全部hang死了,没法再响应任何请求了。

如果对Spring Cloud没有高并发场景的真实经验,确实可能会跟这帮兄弟一样,搞出些莫名其妙的问题。

比如这个公司,明明应该去优化服务接口性能,结果硬是调大了超时时间。结果导致并发量高了,对那个服务的调用直接hang死,系统的核心页面刷不出来,

影响用户体验了,这怪谁呢?

第一步

关键点,优化图中核心服务B的性能。互联网公司,核心业务逻辑,面向C端用户高并发的请求,不要用上百行的大SQL,多表关联,那样单表几百万行数据量的话,

会导致一下执行好几秒。其实最佳的方式,就是对数据库就执行简单的单表查询和更新,然后复杂的业务逻辑全部放在java系统中来执行,比如一些关联,

或者是计算之类的工作。这一步干完了之后,那个核心服务B的响应速度就已经优化成几十毫秒了,是不是很开心?从几秒变成了几十毫秒!

第二步

那个超时的时间,也就是上面那段ribbon和hystrix的超时时间设置。奉劝各位同学,不要因为系统接口的性能过差而懒惰,搞成几秒甚至几十秒的超时,

一般超时定义在1秒以内,是比较通用以及合理的。为什么这么说?因为一个接口,理论的最佳响应速度应该在200ms以内,或者慢点的接口就几百毫秒。如果一个

接口响应时间达到1秒+,建议考虑用缓存、索引、NoSQL等各种你能想到的技术手段,优化一下性能。

否则你要是胡乱设置超时时间是几秒,甚至几十秒,万一下游服务偶然出了点问题响应时间长了点呢?那你这个线程池里的线程立马全部卡死!

具体hystrix的线程池以及超时时间的最佳生产实践,请见下一篇文章:《微服务架构如何保障双11狂欢下的99.99%高可用》

这两步解决之后,其实系统表现就正常了,核心服务B响应速度很快,而且超时时间也在1秒以内,不会出现hystrix线程池频繁卡死的情况了。

第三步

事儿还没完,你要真觉得两步就搞定了,那还是经验不足。如果你要是超时时间设置成了1秒,如果就是因为偶然发生的网络抖动,导致接口某次调用就是在1.5秒呢?

这个是经常发生的,因为网络的问题,接口调用偶然超时。所以此时配合着超时时间,一般都会设置一个合理的重试次数,相对应的服务B的接口也需要做幂等处理。

java下单接口性能优化实战TPS性能提高10倍 http://t.csdn.cn/TAmtU

高并发场景下的数据库连接池应该如何进行优化?http://t.csdn.cn/wkAPE

连接不是越多越好,数据库连接太多了,会导致cpu负载很高,可能反而会导致性能降低,所以这个参数你一般设置个20个,最多加到个几十,其实就差不多了,更多

的,你反而应该是优化你每个请求的性能,别让一个请求占用连接太长时间。

性能测试中TPS上不去的几种原因浅浅析 http://t.csdn.cn/rwti1

下面就说说压测中为什么TPS上不去的原因:

1、网络带宽

在压力测试中,有时候要模拟大量的用户请求,如果单位时间内传递的数据包过大,超过了带宽的传输能力,那么就会造成网络资源竞争,间接导致服务端接收到的

请求数达不到服务端的处理能力上限。

2、连接池

可用的连接数太少,造成请求等待。连接池一般分为服务器连接池(比如Tomcat)和数据库连接池(或者理解为最大允许连接数也行)。

(关于连接池的具体内容,可参考之前的博客:性能测试:连接池和线程)

3、垃圾回收机制

从常见的应用服务器来说,比如Tomcat,因为java的的堆栈内存是动态分配,具体的回收机制是基于算法,如果新生代的Eden和Survivor区频繁的进行Minor GC,

老年代的full GC也回收较频繁,那么对TPS也是有一定影响的,因为垃圾回收其本身就会占用一定的资源。

4、数据库配置

高并发情况下,如果请求数据需要写入数据库,且需要写入多个表的时候,如果数据库的最大连接数不够,或者写入数据的SQL没有索引没有绑定变量,抑或没有

主从分离、读写分离等,就会导致数据库事务处理过慢,影响到TPS。

5、通信连接机制

串行、并行、长连接、管道连接等,不同的连接情况,也间接的会对TPS造成影响。(关于协议的连接,可参考之前的博客:HTTP协议进阶:连接管理)

6、硬件资源

包括CPU(配置、使用率等)、内存(占用率等)、磁盘(I/O、页交换等)。

7、压力机

比如jmeter,单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会间接影响TPS(这个时候就需要进行分布式压测来解决其单机负载的问题)。

8、压测脚本

还是以jemter举个例子,之前工作中同事遇到的,进行阶梯式加压测试,最大的模拟请求数超过了设置的线程数,导致线程不足。提到这个原因,想表达意思是:

有时候测试脚本参数配置等原因,也会影响测试结果。

9、业务逻辑

业务解耦度较低,较为复杂,整个事务处理线被拉长导致的问题。

10、系统架构

比如是否有缓存服务,缓存服务器配置,缓存命中率、缓存穿透以及缓存过期等,都会影响到测试结果。

PS:性能瓶颈分析不能单从局部分析,要综合起来,多维度分析问题原因。上面列出的几点,可能有描述不当或者遗漏的,仅供参考。。

光用是不行的,你平时得考虑好,假设你的项目的用户量有百万级别,然后每天有几千万请求,高峰期每秒好几千请求,那么这个时候,你的每个服务会有多高QPS?

每个服务需要部署多少台机器才可以抗住?机器的配置是多高?然后系统会对背后的mysql,redis,es,rabbitmq等数据库以及中间件,产生多高的qps?

这些中间件需要部署多少台机器,用多高配置的机器?这些东西其实是非常重要的,也是你学习了n多技术之后,把技术真正转化为自己的东西需要做的很多消化性的东西。

优化的思考:代码方面优化,同步改为异步,单线程改为多线程(线程池),队列解耦,缓存,sql索引,SQL语句优化,数据库连接池参数修改(数据库连接满了),

主从复制,读写分离,分库分表,架构方面的思考

线程池最大线程数怎么设置?参考标准是什么?

线程数究竟设多少合理 https://www.cnblogs.com/jajian/p/10862365.html

从11s到17ms,同事提出的18种接口优化技巧,那叫一个优雅 http://t.csdn.cn/ZPuhD

后端性能差,该从哪些方面进行优化? http://t.csdn.cn/gpvRo

接口优化的18种方案:

1.批量思想:批量操作数据库(避免在for循环中进行rpc调用)

2.异步思想:耗时操作,考虑放到异步执行

3.空间换时间思想:恰当使用缓存

4.预取思想:提前初始化到缓存

5.池化思想:预分配与循环等待

6.事件回调思想:拒绝阻塞等待

7.远程调用有串行改为并行

8.锁粒度避免过粗

9.切换存储方式:文件中转暂存数据

10.索引

11.优化sql(sql比较复杂不好优化则使用java代码来实现对应的逻辑)

12.避免大事务问题

13.优化深分页问题

14.优化程序结构

15.压缩传输内容

16.海量数据处理

17.线程池设计要合理

18.机器问题(fullGC,线程池打满,太多io资源没关闭等)

接口突然超时10宗罪(苏三)

1.网络异常(网络抖动,带宽被占满)

2.线程池满了

3.数据库死锁

4.传入参数太多

5.超时时间设置过短

6.一次性返回数据太多

7.死循环(普通死循环,无限递归)

8.sql语句没走索引

9.服务OOM

10.在debug

系统设计类问题:

如果1分钟内要支持抢购10w个口罩,你该如何设计系统架构?

公司重用我独立负责一个核心系统,我该怎么设计系统的高可用架构?

被面试官问到项目中的难点?http://t.csdn.cn/aDrPz

项目介绍

此项目提供了小组成员共享任务提醒的功能。

具体功能为:

管理员对任务或事件的创建,以及对任务的分配。

定时给任务执行人发送提醒。

任务执行人完成任务。

额外说明:

小组中最少有一个管理员,最多有两个管理员。

成员数量不做限制,但根据场景不建议超过10个。

除管理员外普通成员没有创建和修改任务的权限。

任务:固定时间点给执行人提醒要做的事情。

事件:所有成员都可以看到的有时间段的事件,事件本身不具备提醒功能,可以添加关联的任务给相应的执行人发送提醒,比如在事件开始的时候关联一个事件开始的

任务,在事件结束的时候关联事件结束的任务,事件创建时可以选择是否同步创建关联任务,任务创建时可以选择是否关联已存在的事件。

1、设计任务和事件的规则计算及存储方式

设计方案

首先pass掉子任务全量落表的方式(无限重复规则的按时间落表往后半年或1年的数据),此方式对数据库的压力太大。

采用存储任务规则的方式,对已经发生的任务落历史表,未发生的任务使用规则计算发生时间,未发生已修改的存特殊(special)表。

问题

开发时间成本问题:任务规则引擎设计,人力成本及时间成本太大。

计算性能问题:考虑到规则解析计算的性能可能会出现瓶颈,提出此问题。

解决方案:

1)使用rfc-2445标准规范,选用开源项目组件。寻找可靠的开源组件并测试其性能表现,最终经过Jmeter压力测试发现其性能瓶颈出现在http的并发请求上,

规则计算不是其性能瓶颈,为减少网络开销,最终对接口进行封装,采用一次请求计算多条规则的方式设计接口。

2)对入口服务的接口采用redis缓存进一步缓解服务器压力,对常用接口的结果进行缓存,如首页的接口,由于其参数一天才变动一次,所以完全可采用缓存的方式存储数据

项目问题总结:

2、数据库与redis缓存的数据一致性(数据库和缓存双写一致性)

问题

在使用了缓存的业务场景中,例如查询用户的可访问资源,在修改数据库中的这些数据时,可能导致用户查出的缓存数据还是旧数据。

(在并发读写访问的时候,缓存和数据相互交叉执行)

解决方式

设置redis缓存数据过期时间,修改数据时清除对应的缓存,使用户下次查询直接使用数据库的数据。

(采用先更新数据库,再删除缓存的方式,实现延迟双删,对第二次删除不成功的情况使用mq或者本地记录删除失败数据定时任务执行,

构建重试机制,重试删除三次不成功,记录到数据库,发短信给人工处理)

3、缓存穿透(补充缓存击穿,缓存雪崩的问题和解决方案)

问题

恶意用户发起攻击,查询一个缓存和数据库中都不存在的数据,造成一直查询数据库导致数据库压力飙升甚至垮掉。

解决方案

1) 接口增加用户权限校验,id做校验,例如 id<0 的直接拦截。

2) 在数据库中取不到的数据存一个空值到Redis,设置缓存有效时间较短,例如30秒后过期。

3) 使用布隆过滤器,布隆过滤器可以做到的效果:一个一定不存在的数据会被拦截掉,可能存在的数据才会去查数据库。因为这个特性,只要设置合理的参数就可以

极大的缓解缓存穿透问题。

了解更多:缓存穿透、缓存击穿、缓存雪崩区别和解决方案
4、分布式事务解决方案

问题

微服务架构的系统中总会出现分布式事务的问题,例如:任务服务和事件服务为两个单独的服务,而任务与事件又有关联的操作,修改一条事件需要修改所有与此事件

关联的任务,这就涉及到数据的一致性了,需要使用分布式事务来解决问题。

解决方式

解决分布式事务有很多方法,例如:基于可靠消息的最终一致性方案、TCC事务补偿型方案、最大努力通知型。

经过讨论,最终选用了最大努力通知型。详细设计方案为:调用对方服务时,判断是否成功,成功则流程继续,失败就把调用信息存入重试表中,然后继续下面的流程。

最后使用定时扫描的方式重新发起接口的调用,重试调用一定次数,如果成功则结束,如果一直未成功则通知管理员处理此信息。

补充:

你们公司是如何处理分布式事务的?

如果你真的被问到,可以这么说,我们某某特别严格的场景(例如资金交易)用的是TCC来保证强一致性,然后其他的一些场景基于阿里的RocketMQ来实现分布式事务。

你找一个严格资金要求绝对不能错的场景,你可以说你是用TCC方案,如果是一般的分布式事务场景,订单插入之后要调用库存服务更新库存,库存数据没有资金那么的敏感,

可以用可靠消息最终一致性方案。

5、分布式锁

问题:

本系统功能允许一个家庭组中存在多名管理员,所以存在多名管理员同时操作一条数据的可能性,为保证数据的一致性,需要对操作进行加锁处理,微服务中每个服务

可能有多个实例,所以存在多个进程的线程操作同一条数据的情况,于是普通单机系统的应用使用的java内存锁不再可靠。

解决方案

分布式锁提供了分布式系统中跨JVM的互斥机制的实现,常用的分布式锁的实现方式有三种:

1、基于数据库实现分布式锁

2、基于缓存(Reids等)实现分布式锁

3、基于Zookeeper实现分布式锁

其中基于数据库的分布式锁实现方式最为简单,但是太过依赖数据库。Redis和Zookeeper中,因为Redis已在本系统中有集成,而且实现起来简单,只要注意Redis

实现分布式锁的方式中的几个问题就能做出来一个相对完善的方案。

PS:SpringBoot中使用Redis实现分布式锁

6、消息延迟推送

问题:系统中一条消息推送给客户之后,如果客户没有以及处理需要在间隔一段时间后再发送一次。

解决方案:

使用RabbitMQ的死信队列实现消息的延迟发送,其实现方式是设置第一个队列的消息存活时间(TTL),此队列不设置消费者,配置交换机,将过期的消息交换

(死信交换DLX)到另一个队列,消费者消费此队列,此时距离消息产生就已经过了一段时间,实现了消息的延迟推送。

PS:RabbitMQ的死信队列实现消息的延时消费

你负责的模块:微服务网关项目复盘http://t.csdn.cn/sQHSq

1.项目背景:

顺应时代背景,规划对公司内部多个项目进行微服务化改造,需要一个统一的接口管理服务,因此安全网关项目于被提上日程。

2.业务目标

基础目标:路由转发,负载均衡

进阶目标:参数安全校验,限流,微服务认证授权,参数的加解密,后端服务的灰度环境快速切换等

3.系统架构方案:

由于网关是一个业务网关,需要处理很多耗费性能的功能,因此安全网关采用集群化部署,前面再加一层nginx作为流量网关,提供业务网关层的负载均衡。

4.开发计划

项目调研-》需求提取-》功能设计-》代码实现-》系统对接

5.预期目标

网关基本功能:路由转发,负载均衡,限流

安全认证相关功能:URL重放,参数安全校验(http host,XSS,SSRF),签名验证,参数加解密

权限验证相关功能:微服务认证授权,单点登录

服务接入:spring boot微服务,传统web服务

聊聊问服务架构中的用户认证方案!

一个开放平台解决方案项目SOP

消息推送平台http://t.csdn.cn/3dncq

日志处理,性能收集

实战!工作中常用哪些设计模式

策略模式

责任链模式

模板方法模式

观察者模式

工厂模式

单例模式

建造者模式

装饰者模式

适配器模式

代理模式

10道BAT大厂海量数据面试题

1.如何从大量的url中找出相同的url?

2.如何从大量数据中找出高频词?

3.如何找出某一天访问百度网站最多的ip?

4.如何在大量的数据中找出不重复的整数?

5.如何在大量的数据中判断一个数是否存在?

6.如何查询最热门的查询串?

7.如何统计不同电话号码的个数?

8.如何从 5 亿个数中找出中位数?

9.如何按照 query 的频度排序?

10.如何找出排名前 500 的数?

10题面试100%会手撕的代码题!必须拿捏!

十道题分别

1、翻转链表【美团、字节、百度等】

2、设计LRU【蔚来、猿辅导、字节等】

3、环形链表【美团、字节等】

4、两个栈实现队列【字节、蔚来、阿里等】

5、二叉树层次遍历【好未来、美团、Shopee、快手等】

6、二叉树非递归遍历【腾讯、阿里等】

7、经典爬楼梯【腾讯等】

8、Topk问题【百度、腾讯等】

9、最长重复子串【字节、腾讯等】

10、排序【百度、字节、阿里、美团、快手等】

10道腾讯算法真题解析

1.重排链表

2.最长递增子序列

3.环形链表

4.反转链表

5.最长回文子串

6.全排列

7.LRU 缓存

8.合并K个升序链表

9.无重复字符的最长子串

10.删除链表的倒数第 N 个结点

我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。

举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时, 系统内有20台Apache的Web服务器,配置MaxClients为500个(表示Apache的最大连接数目)。

那么,我们的Web系统的理论峰值QPS为(理想化的计算方式):20*500/0.1 = 100000 (10万QPS)

咦?我们的系统似乎很强大,1秒钟可以处理完10万的请求,5w/s的秒杀似乎是“纸老虎”哈。实际情况,当然没有这么理想。在高并发的实际场景下,机器都处于

高负载的状态,在这个时候平均响应时间会被大大增加。

就Web服务器而言,Apache打开了越多的连接进程,CPU需要处理的上下文切换也越多,额外增加了CPU的消耗,然后就直接导致平均响应时间 增加。因此上述的

MaxClient数目,要根据CPU、内存等硬件因素综合考虑,绝对不是越多越好。可以通过Apache自带的abench来测试一 下,取一个合适的值。然后,我们选择内存

操作级别的存储的Redis,在高并发的状态下,存储的响应时间至关重要。网络带宽虽然也是一个因素,不过,这种 请求数据包一般比较小,一般很少成为请求的瓶颈。

负载均衡成为系统瓶颈的情况比较少,在这里不做讨论哈。

那么问题来了,假设我们的系统,在5w/s的高并发状态下,平均响应时间从100ms变为250ms(实际情况,甚至更多):20*500/0.25 = 40000 (4万QPS)

于是,我们的系统剩下了4w的QPS,面对5w每秒的请求,中间相差了1w。

然后,这才是真正的恶梦开始。举个例子,高速路口,1秒钟来5部车,每秒通过5部车,高速路口运作正常。突然,这个路口1秒钟只能通过4部车,车流量仍然依旧,

结果必定出现大塞车。(5条车道忽然变成4条车道的感觉)

同理,某一个秒内,20*500个可用连接进程都在满负荷工作中,却仍然有1万个新来请求,没有连接进程可用,系统陷入到异常状态也是预期之内。

其实在正常的非高并发的业务场景中,也有类似的情况出现,某个业务请求接口出现问题,响应时间极慢,将整个Web请求响应时间拉得很长,逐渐将Web服务器的可用

连接数占满,其他正常的业务请求,无连接进程可用。

更可怕的问题是,是用户的行为特点,系统越是不可用,用户的点击越频繁,恶性循环最终导致“雪崩”(其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,

再导致正常的机器也挂,然后恶性循环),将整个Web系统拖垮。

一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在200ms以内完成,对用户几乎是无感知的。

  • 16
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值