最全面试笔记 (ㄒoㄒ) ~~

cat /proc/cpuinfo

查看系统位数

getconf LONG_BIT

查看本机ip地址

ip addr  

路径跳转

cd 所要跳转的路径

创建目录

mkdir 目录名称     

创建多层目录

mkdir  -p(小写的) 

显示当前工作目录

pwd -P(大写的) 

显示当前目录下隐藏文件

ls -a

删除空文件夹

rmdir 想要删除的空目录路径 

创建文件

touch  文件名.文件类型

显示指定文件或文件夹的详细信息

stat  文件路径     

获取指定文件的类型

file  文件路径  

查看当前账户/其他账户 uid/gid

id

id  账户名

查看当前文件夹下文件及文件夹所属账户

ll

查看进程列表

ps aux|less

创建用户

useradd  用户名 //会默认创建一个和用户名一样的组
useradd 用户名 -G 组名  //前提是已经创建分组了   //往主组之后添加新组
useradd 用户名 -d 文件夹路径   //给新创建的用户指定操作目录   
默认生成的uid是在现有最大id的基础上+1
useradd 用户名 -u 指定用户编号(编号只能为数字且不可重复)
useradd 用户名 -g 指定用户主组编号/名称      //直接替换主组,只保留一个组


创建组

groupadd  组名
groupadd  组名  -g  编号(gid)//创建指定编号的组

组的作用:

可以更方便的对部分用户做权限操作

例如

ss01用户  刚开始只是普通权限,由于工作需要,需要对权限进行调整

那么可以直接把ss01加入该权限的组中即可,不用再单独设置权限。

给账户添加组

gpasswd -a  yangyang01 dcc01
//yangyang01是要修改的账户名
//dcc01是要添加进的组名(只能是组名不能是gid)

查看组的信息

tail /etc/group
//新创建的组会在文件的最下面显示

删除用户

userdel  用户名

userdel  -r  用户名    //删的更彻底

修改用户密码

passwd 用户名

普通用户获取管理员权限

sudo su

修改某一个文件或文件夹的属主/属组

chown 所要修改的账户名 修改的文件/文件夹路径
//如果要同时修改属主和属组则
chown 所要修改的账户名.所修改的组名 修改的文件/文件夹路径

修改文件属组

chgrp 所修改的组名 修改的文件/文件夹路径
//若要修改该文件夹下所有文件的属组则
chgrp -R 所修改的组名 修改的文件/文件夹路径 
//-R为递归参数

修改文件权限

chmod 对象+权限 文件/文件夹路径
//删除所有对象的权限
chmod a=- 文件/文件夹路径
//同时给不同身份修改权限 不同身份操作之间用,隔开
chmod u=r,g=rx,o+w 文件/文件夹路径

15.docker的常用命令

1、Docker创建并启动容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG…]

--name="容器新名字":为容器指定一个名称;
-i:以交互模式运行容器,通常与-t或者-d同时使用;
-t:为容器重新分配一个伪输入终端,通常与-i同时使用;
-d: 后台运行容器,并返回容器ID;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口

启动普通容器: docker run --name 别名 镜像ID (不常用)
启动交互式容器: docker run -it --name 别名 镜像ID 来运行一个容器,取别名,交互模式运行,以及分配一个伪终端,并且进入伪终端;
实例:
docker run -it --name mycentos03 67fa590cfc1c

注意:

1、启动普通容器的方式基本不用,没有伪终端,没有太大价值;
2、启动交互式容器的方式,容器一创建完毕,立即进入伪终端

守护式方式创建并启动容器
docker run -di --name 别名 镜像ID
实例:
docker run -di --name mycentos02 67fa590cfc1c

2、Docker列出容器

OPTIONS说明:
-a :显示所有的容器,包括未运行的。
-f :根据条件过滤显示的内容。
--format :指定返回值的模板文件。
-l :显示最近创建的容器。
-n :列出最近创建的n个容器。
--no-trunc :不截断输出。
-q :静默模式,只显示容器编号。
-s :显示总的文件大小。

3、Docker退出容器

exit 容器停止退出
ctrl+P+Q 容器不停止退出

4、Docker进入容器

a、docker attach 容器ID or 容器名

实例:
docker attach ce6343ee288f
不能进入停止的状态的容器
You cannot attach to a stopped container, start it first

b、Docker进入容器执行命令
docker exec -it 容器名称 或者 容器ID 执行命令
实例:
docker exec -it tomcat02 ls -l /root/webapp02

直接操作容器,执行完 回到 宿主主机终端;

我们一般用于 启动容器里的应用 比如 tomcat nginx redis elasticsearch等等

5、Docker启动容器

docker start 容器ID or 容器名

实例:
docker start mycentos00

6、Docker重启容器

docker restart 容器ID or 容器名

实例:
docker restart f9cadea1a5e7

7、Docker停止容器

docker stop 容器ID or 容器名

实例:
docker stop 865b755cd0b2

暴力删除,直接杀掉进程 (不推荐)
docker kill 容器ID or 容器名

8、Docker删除容器
docker rm 容器ID

如果删除正在运行的容器,会报错,我们假如需要删除的话,需要强制删除;
强制删除docker rm -f 容器ID

删除多个容器
docker rm -f 容器ID1 容器ID2 中间空格隔开
实例:
docker rm 865b755cd0b2 ce6343ee288f

删除所有容器
docker rm -f $(docker ps -qa)

9、Docker容器日志

$ docker logs [OPTIONS] CONTAINER
  Options:
        --details        显示更多的信息
    -f, --follow         跟踪实时日志
        --since string   显示自某个timestamp之后的日志,或相对时间,如42m(即42分钟)
        --tail string    从日志末尾显示多少行日志, 默认是all
    -t, --timestamps     显示时间戳
        --until string   显示自某个timestamp之前的日志,或相对时间,如42m(即42分钟)

16.redis

问:如果做秒杀功能需要使用什么数据类型

list可用于秒杀抢购场景

在商品秒杀场景最怕的就是商品超卖,为了解决超卖问题,我们经常会将库存商品缓存到类似MQ的队列中,多线程的购买请求都是从队列中取,取完了就卖完了,但是用MQ处理的化有点重,这里就可以使用redis的list数据类型来实现,在秒杀前将本场秒杀的商品放到list中因为list的pop操作是原子性的,所以即使有多个用户同时请求,也是依次pop,list空了pop抛出异常就代表商品卖完了。

问:如果做排行榜功能需要使用什么数据类型

用Zset数据类型

一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。

17.redis AOF,RDB 等持久化方式

RDB在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上。(默认的持久化方式)

AOF,将redis执行的所有指令记录下来,下次重新启动redis时,只要把这些写指令从前到后重新执行一遍,就可以实现数据恢复了。

两种方式可以同时使用,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。

18.kafka为什么吞吐量高

1.顺序读写

Kafka是将消息记录持久化到本地磁盘中的,一般人会认为磁盘读写性能差,可能会对Kafka性能如何保证提出质疑。实际上不管是内存还是磁盘,快或慢关键在于寻址的方式,磁盘分为顺序读写与随机读写,内存也一样分为顺序读写与随机读写。基于磁盘的随机读写确实很慢但磁盘的顺序读写性能却很高,一般而言要高出磁盘随机读写三个数量级,一些情况下磁盘顺序读写性能甚至要高于内存随机读写。

磁盘的顺序读写是磁盘使用模式中最有规律的,并且操作系统也对这种模式做了大量优化,Kafka就是使用了磁盘顺序读写来提升的性能。Kafka的message是不断追加到本地磁盘文件末尾的,而不是随机的写入,这使得Kafka写入吞吐量得到了显著提升 。

2.Page Cache

为了优化读写性能,Kafka利用了操作系统本身的Page Cache,就是利用操作系统自身的内存而不是JVM空间内存。这样做的好处有:

1避免Object消耗:如果是使用 Java 堆,Java对象的内存消耗比较大,通常是所存储数据的两倍甚至更多。

2避免GC问题:随着JVM中数据不断增多,垃圾回收将会变得复杂与缓慢,使用系统缓存就不会存在GC问题

相比于使用JVM或in-memory cache等数据结构,利用操作系统的Page Cache更加简单可靠。首先,操作系统层面的缓存利用率会更高,因为存储的都是紧凑的字节结构而不是独立的对象。其次,操作系统本身也对于Page Cache做了大量优化,提供了 write-behind、read-ahead以及flush等多种机制。再者,即使服务进程重启,系统缓存依然不会消失,避免了in-process cache重建缓存的过程。

通过操作系统的Page Cache,Kafka的读写操作基本上是基于内存的,读写速度得到了极大的提升。

3.零拷贝

通过这种 “零拷贝” 的机制,Page Cache 结合 sendfile 方法,Kafka消费端的性能也大幅提升。这也是为什么有时候消费端在不断消费数据时,我们并没有看到磁盘io比较高,此刻正是操作系统缓存在提供数据。

4.分区分段+索引

Kafka的message是按topic分类存储的,topic中的数据又是按照一个一个的partition即分区存储到不同broker节点。每个partition对应了操作系统上的一个文件夹,partition实际上又是按照segment分段存储的。这也非常符合分布式系统分区分桶的设计思想。

通过这种分区分段的设计,Kafka的message消息实际上是分布式存储在一个一个小的segment中的,每次文件操作也是直接操作的segment。为了进一步的查询优化,Kafka又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也提高了数据操作的并行度。

5.批量读写

Kafka数据读写也是批量的而不是单条的。

除了利用底层的技术外,Kafka还在应用程序层面提供了一些手段来提升性能。最明显的就是使用批次。在向Kafka写入数据时,可以启用批次写入,这样可以避免在网络上频繁传输单个消息带来的延迟和带宽开销。假设网络带宽为10MB/S,一次性传输10MB的消息比传输1KB的消息10000万次显然要快得多。

6.批量压缩

在很多情况下,系统的瓶颈不是CPU或磁盘,而是网络IO,对于需要在广域网上的数据中心之间发送消息的数据流水线尤其如此。进行数据压缩会消耗少量的CPU资源,不过对于kafka而言,网络IO更应该需要考虑。

  • 如果每个消息都压缩,但是压缩率相对很低,所以Kafka使用了批量压缩,即将多个消息一起压缩而不是单个消息压缩
  • Kafka允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩
  • Kafka支持多种压缩协议,包括Gzip和Snappy压缩协议

Kafka速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗,通过mmap提高I/O速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。

19.kafka如何保证消息的有序性

1. 消息有序性

我们需要从2个方面看待消息有序性

  • 第一,发送端能否保证发送到服务器的消息是有序的
  • 第二,接收端能否有序的消费服务器中的数据

发送端一般通过同步发送实现,即一次仅发送一条,等返回成功后,再发送下一条,接收端一般仅通过一个消费者参与消费实现

2. 发送端消息有序性

2.1 Kafka如何保证单partition有序?

**Kafka分布式的单位是partition,同一个partition用一个write ahead log组织,所以可以保证FIFO的顺序。不同partition之间不能保证顺序。**但是绝大多数用户都可以通过message key来定义,因为同一个key的message可以保证只发送到同一个partition,比如说key是user id,table row id等等,所以同一个user或者同一个record的消息永远只会发送到同一个partition上,保证了同一个user或record的顺序。

也就说通过队列,保证partition上的数据元素是有序的。通过设置相同的路由,让多个数据被路由到同一个partition即可。

2.2 client消息发送原理

下面,我们要如何保证数据从client发送到服务器上的partition是有序的?

先阅读 深入图解Kafka producer 发送过程

消息发送对于用户线程有同步和异步之分

同步能保证逐条发送消息,并保证是有序的

异步通常也是有序的,因为tcp长连接方式 按序读取InFlightRequests队列并发送至服务器上,tcp保证是有序的。但是如果开启了重试机制,可能会导致乱序。

后台的发送线程只有异步方式

异步场景下开启重试策略时:

max.in.flight.requests.per.connection=5 默认值,控制发送窗口的大小,即连续发送次数

如果把 retries 设为非零整数,同时把 max.in.flight.requests.per.connection 设为比 1 大的数,那么,如果第一个批次消息写入失败,而第二个批次写入成功,broker 会重试写入第一个批次。如果此时第一个批次也写入成功,那么两个批次的顺序就反过来了。

如果发送端配置了重试机制,kafka不会等之前那条消息完全发送成功才去发送下一条消息,这样可能会出现,发送了1,2,3条消息,第一条超时了,后面两条发送成功,再重试发送第1条消息,这时消息在broker端的顺序就是2,3,1了

一般来说,如果某些场景要求消息是有序的,那么消息是否写入成功也是很关键的,所以不建议把retries设为 0。可以把 max.in.flight.requests.per.connection 设为 1,这样在生产者尝试发送第一批消息时,就不会有其他的消息发送给broker。不过这样会严重影响生产者的吞吐量,所以只有在对消息的顺序有严格要求的情况下才能这么做。

3. 接收端消息有序性

kafka保证全链路消息顺序消费,需要从发送端开始,将所有有序消息发送到同一个分区,然后用一个消费者去消费,但是这种性能比较低,可以在消费者端接收到消息后将需要保证顺序消费的几条消费发到内存队列(可以搞多个) ,一个内存队列开启一个线程顺序处理消息。

仅有一个消费者访问一个分区,可以保证有序,但是效率低。当有多个消费者时,通过新增业务队列,让所有数据都发到业务队列中,排序后再进行业务处理.

20.kafka幂等和 什么时候提交

21. BIO,NIO,AIO 有什么区别?

BIO同步阻塞,传统并发处理能力低

NIO 同步非阻塞,客户端和服务器通过Channel通讯实现了多路复用

AIO Asynchronized 实现了异步非堵塞IO,基于事件和回调机制

22.类的加载过程

当Java程序需要使用某个类时,如果该类还未被加载到内存中,JVM会通过加载、连接(验证、准备和解析)、初始化三个步骤来对该类进行初始化。

类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:

1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;

2)如果类中存在初始化语句,就依次执行这些初始化语句。

23.静态代码和构造方法的执行顺序

静态代码先执行,随着类的加载进行执行

构造方法在对象创建的时候执行

24.双亲委派机制的作用

24.1、什么是双亲委派机制

当某个类加载器需要加载某个.class文件时,它首先把这个请求任务委托给它的上级类加载器,递归这个操作,如果上级类加载器都没有加载,自己才会去加载这个类。

24.2、作用:

1、防止重复加载同一个.class文件。通过委托去向上面问一问,加载过了,就不用再加载一遍了,保证数据安全。

2、保证核心 .class文件 不被篡改。通过向上委托的方式,不会去篡改核心 .class 文件,即使篡改也不会去加载,即使加载也不会是同一个 .class对象 。不同的类加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。

自己写个String类不会被加载,因为被篡改了

25.springCloud的五大组件都有什么

注册中心,网关,熔断器,配置中心,负载均衡,远程调用

25.1gateway网关都用来做什么

过滤器,对请求或者响应进行拦截,完成一些通用操作

  • 请求接入

作为所有API接口服务请求的接入点

  • 业务聚合

作为所有后端业务服务的聚合点

  • 中介策略

实现安全,验证,路由,过滤,流控等策略

  • 统一管理

对所有API服务和策略进行统一管理

25.2Hystrix哪个注解进行熔断或者降级的

//@HystrixCommand默认开启线程池隔离方式(不同线程池),服务降级(默认开启服务降级执行方法)、服务熔断; 

//fallbackMethod:服务降级执行

@HystrixCommand(fallbackMethod = "getOrderHystrixFallBack")
    @RequestMapping("/getOrderHystrix")
    
    public String getOrderHystrix(){
        System.out.println(Thread.currentThread().getName());
        return memberApiFegin.getMember();
    }    

public String getOrderHystrixFallBack(){
    System.out.println(Thread.currentThread().getName());----------线程池名称不一样
    return "服务降级,服务器忙,请稍后重试.";
}

1.你有使用过线程池吗?线程池的使用场景?使用中需要注意哪些事项?

1.1原理

使用一个容器(集合)存储一些线程
当我们要使用线程的时候,从容器中取出
使用完毕线程,把线程在归还给线程池
可以提高程序的效率,避免了频繁的创建线程和销毁线程

1.2使用场景

大型系统,建议不论何种场景,都直接使用线程池。(异步发送邮件)

1)高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换
(2)并发不高、任务执行时间长的业务要区分开看:
a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以加大线程池中的线程数目,让CPU处理更多的业务
b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换
(3)并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦

1.3使用中需要注意事项

2.spring自动装配原理

核心注解:@EnableAutoConfiguration

具体过程:

启动类上加的注解@SpringBootApplication,这是一个复合注解,内部包含了@EnableAutoConfiguration

@EnableAutoConfiguration内部有一个@Impor注解,这个注解才是完成自动装配的关键

@Import导入一个类(AutoConfigurationImporSelector),这个类内部提供了一个方法(selectImports).这个方法会扫描导入的所有jar包下的spring.factories文件,解析文件中自动配置类key-value,将列表中的类创建,并放到Spring容器中。

3.如何得到Ribbon的负载节点方法

4.Feign使用的话会用到什么注解?怎么用?

Feign组件继承了Ribbon负载均衡策略(默认开启的,使用轮询机制),Hystrix熔断器(默认关闭的,需要通过配置文件进行配置开启)

被调用的微服务需要提供一个接口,加上@FeignClient(“url”)注解

调用方需要在启动类上家@EnableFeignClients,开启Feign组件功能

5.redis双写一致性的解决方案

5.1为什么要使用缓存?

因为数据库的数据是写在硬盘上的,缓存则是存在于内存中。

5.2解决方案

  • 1.先更新数据库,再更新缓存

线程A更新数据库为4,还没有来得及更新缓存时。

线程B更新数据库为5,并更新了缓存为5。

最后线程A更新缓存为4.

导致了线程B对缓存的更新丢失,造成了数据不一致

  • 2.先删除缓存,再更新数据库

数据库 和 缓存的值 为3

线程A删除了缓存,还没来得及更新数据库为4。

线程B读取缓存没读取到,去读取数据库的值为3,并更新了缓存。

线程A去更新数据库为4

又出现了数据库和缓存不一致的情况

解决的话延双删,就是在一段时间后,再次删除缓存

需要:延时时间>一次读操作的时间

  • 3.先更新数据库,再删除缓存

缓存中没数据,线程A读取数据库,还没来得及更新缓存

线程B更更新里数据库,并删除了缓存

线程A更新缓存

又出现了数据库和缓存不一致的情况

出现概率低,因为写操作耗时大于读操作

解决的话延双删,就是在一段时间后,再次删除缓存

需要:延时时间>一次读操作的时间

  • 4.订阅mysql的binlog文件,文件增量形式

来进行数据同步,cancl框架的底层就是这样实现的

5.3延时双删的问题

比如删除缓存失败了应该怎么办

循环删除!!!

删除失败后,将要删除的Key放入队列,重复尝试删除,直到删除成功

6.Mysql什么情况下会导致行锁和表锁?

只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!!!

6.1遇到行锁或者表锁的解决方案

7.git的工作原理

7.1git的常用命令

查看远程仓库:$ git remote -v

添加远程仓库:$ git remote add [name] [url]

删除远程仓库:$ git remote rm [name]

8.常用的Lambda表达式

1.代替匿名内部类

​ 创建线程使用到,替代new Runnable接口


//before
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("123");
    }
}).start();
 
//after
new Thread(() -> System.out.println("456")).start();

2.forEach:循环List


List<String> list = Arrays.asList("2", "b", "10", "4", "6", "aa", "b", "ccdf");
 
//before
for (String str : list) {
    System.out.println(str);
}
 
//after
list.forEach((str) -> System.out.println(str));
 
// double colon operator
list.forEach(System.out::println);
 
System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*");
 
//before
for (String str : list) {
    if (str.equals("a")) {
        System.out.println(str);
    }
}
 
//after
list.forEach((str) -> {
    if (str.equals("a")) {
        System.out.println(str);
    }
});

3.sort : 对List进行排序

List<String> list = Arrays.asList("2", "b", "10", "4", "6", "aa", "b", "ccdf");

//before
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});

//after
Comparator<String> sortByName = ((String s1, String s2) -> (s1.compareTo(s2)));
list.sort(sortByName);

//or
list.sort((String s1, String s2) -> s1.compareTo(s2));

4.map : 它的作用就是把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素。

List<String> list = Arrays.asList("a", "a", "b", "c", "d", "g", "a", "z", "c");

//转换成大写
List<String> output = list4=
    ''.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());
System.out.println(output);

//每个元素 都 加上"字母"
List<String> collect = list
        .stream()
        .map(s -> s + "字母")
        .collect(Collectors.toList());
System.out.println(collect);

5.reduce : 依照运算规则把 Stream 里所有的元素组合起来

List<String> list = Arrays.asList("a", "a", "b", "c", "d", "g", "a", "z", "c");

// 把字符串都连接在一起
String reduce = list.stream().reduce("",String::concat);
System.out.println(reduce);

// 求最小值
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX\_VALUE, Double::min);
System.out.println(minValue);

// 求和,有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(10, Integer::sum);
System.out.println(sumValue);

// 求和,无起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
System.out.println(sumValue);

9.MQ的理解

做异步处理的操作,接口是属于http协议接口的,同步调用过程当中,如果接口响应比较慢的情况下,会导致客户端超时。

有些业务执行时间比较耗时,他响应比较慢的情况下,会导致客户端同步进行阻塞等待,容易引发客户端超时,会导致客户端出发一些重试的策略

触发重试的策略过程当中会导致,业务有可能会重复执行所以需要注意一些幂等性问题

将一些执行比较耗时的业务通过MQ去实现,能提高我们的http协议接口的响应速度
分布式系统中一个子系统,异步消息传递机制。
作用:应用解耦 流量削峰

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

cat);
System.out.println(reduce);

// 求最小值
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
System.out.println(minValue);

// 求和,有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(10, Integer::sum);
System.out.println(sumValue);

// 求和,无起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
System.out.println(sumValue);


## 9.MQ的理解


做异步处理的操作,接口是属于http协议接口的,同步调用过程当中,如果接口响应比较慢的情况下,会导致客户端超时。


有些业务执行时间比较耗时,他响应比较慢的情况下,会导致客户端同步进行阻塞等待,容易引发客户端超时,会导致客户端出发一些重试的策略


触发重试的策略过程当中会导致,业务有可能会重复执行所以需要注意一些**幂等性问题**


**将一些执行比较耗时的业务通过MQ去实现,能提高我们的http协议接口的响应速度**  
 **分布式系统中一个子系统,异步消息传递机制。  
 作用:应用解耦 流量削峰**


[外链图片转存中...(img-2zqqVWqj-1714817086211)]
[外链图片转存中...(img-hauomwmR-1714817086212)]
[外链图片转存中...(img-yLbERLoL-1714817086212)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值