- 博客(124)
- 收藏
- 关注
原创 123、对表结构操作的SQL?delete、truncate、drop的区别?char和varchar的区别?
③char存储的是定长字符串,如果实际长度小于指定长度,那么末尾会用空格填充,如果实际长度大于指定长度,那么会对数据进行截取。而varchar存储的是变长字符串,如果实际长度小于指定长度,不会使用空格填充,如果实际长度大于指定长度,那么也会对数据进行截取,不过varchar会额外使用1或2个字节存储长度信息。char适用于存储长度固定的字符串,此时就不需要额外的字节来维护长度信息,而varchar适用于存储长度不固定的字符串,此时就不需要空格填充,更加节省空间。②delete用于删除表中符合指定条件的行。
2024-05-13 21:01:51
423
原创 122、CAP理论和BASE理论?
理论是对CAP中的一致性和可用性权衡的结果,它的核心思想是即使无法实现强一致性,但每个应用都可以根据自身业务的特点,采用合适的方式来保证系统能够达到最终一致性。BASE是基本可用、软状态、最终一致性这三个短语的英文缩写,基本可用指的是在系统出现故障时,允许损失部分可用性,但仍然能够保证系统的基本功能可用,比如延长请求的处理时间或暂停某些非核心功能。中的C指的是一致性,表示在分布式系统中的所有节点上,对同一个数据的读操作,都能获取到最新的数据副本。
2024-05-04 00:51:59
194
原创 120、项目中订单如何保证幂等性的?登录流程?MD5盐值?
在我们的项目中,用户点击课程的购买按钮后,后端会创建一个防重令牌token返回给前端并存入到Redis中,key是用户id,value是token,然后前端跳转到交易页面点击支付按钮后,后端会根据用户id去查询Redis中是否存在对应的token,若存在则对比Redis中的token和前端发送的token是否相同,相同的话就删除Redis中的token,这个步骤就相当于获取锁,成功删除token的线程才允许去创建订单。
2024-04-25 23:39:33
317
原创 119、网络模型有哪几层?TCP序列号和确认号是如何变化的?
如果上一次收到的是SYN报文或FIN报文,则 确认号 = 上一次收到的报文中的序列号 + 1,如果是其它报文,则 确认号 = 上一次收到的报文中的序列号 + 数据长度。②如果上一次发送的是SYN报文或FIN报文,则 序列号 = 上一次发送的序列号 + 1,如果是其它报文,则 序列号 = 上一次发送的序列号 + 数据长度。①OSI七层网络模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。互联网实际采用的五层网络模型:应用层、传输层、网络层、数据链路层、物理层。
2024-04-24 22:15:00
182
原创 118、从输入URL到页面展示,期间发生了什么?
第三步,浏览器收到HTTP响应报文后,会解析响应体中的HTML代码,然后渲染网页的结构和样式,同时会根据HTML中的其他资源的URL再次发起HTTP请求,获取这些资源的内容,比如图片、CSS和JS的URL,直到网页完全加载显示。第二步,TCP连接建立完成后,浏览器会在TCP连接上向服务器发送一个HTTP请求报文,用来请求获取网页的内容。第一步,在浏览器中输入指定网页的URL后,浏览器会根据DNS协议获取域名对应的IP地址,然后会根据IP地址和端口号向目标服务器发起一个TCP连接请求。
2024-04-08 21:28:03
347
原创 117、TCP和UDP的区别?TCP三次握手和四次挥手?TCP为什么是三次握手,不是两次、四次握手?
比如客户端发送了SYN报文给服务端后,客户端宕机了,而且这个SYN报文还被网络阻塞了,服务端并没有收到SYN报文,接着客户端重启后,又重新向服务端发送了SYN报文,旧SYN报文比新SYN报文更早到达服务端,然后服务端就会发送一个SYN + ACK报文给客户端,那么此时建立的连接就是一个旧连接。而在三次握手的情况下客户端会发现服务端发送的确认号不对,然后给服务端发送RST报文让服务端断开旧的连接,但两次握手的情况下服务端接收不到RST报文也就不能断开旧的连接,这就会导致重复地建立连接,造成资源浪费。
2024-04-05 00:31:10
213
原创 116、HTTP和HTTPS的区别?GET和POST的区别?HTTP/1.1和HTTP/2.0的区别?HTTP缓存?
而HTTP/2.0引入了Steam概念,多个Steam可以复用在同一个TCP连接上,每个Stream中又可以包含多个Message,而Message对应的是HTTP/1.0中的请求与响应,这种并行处理的能力让HTTP/2.0在处理多个请求时更加高效。当资源过期时客户端会向服务端发起请求,其中请求头字段If-None-Match的值会被设置为ETag的值,然后服务端会比较ETag来判断资源是否更新了,如果ETag相同则返回304状态码,如果ETag不同,则返回200状态码和新的资源和更新后的ETag。
2024-04-05 00:31:06
183
原创 115、HTTP常见的状态码有哪些?HTTP报文?Cookie和Session的区别?
而Session的存储大小只受服务器内存限制,通常可以存储更大的数据,并且Session支持存储对象类型的数据,具有更高的灵活性。201 表示服务端成功处理了请求,并在在服务端中创建了一个新的资源,比如通过Post请求创建了一个新用户。204 表示服务端成功处理了请求,但并没有返回实际的响应数据,比如删除操作就不需要返回数据。400 表示服务端不理解客户端发送的请求,这是个通用的错误码,通常是因为请求存在语法错误。200 是最常见的一个状态码,表示服务端成功处理了请求,并返回了相应的数据。
2024-04-05 00:31:01
322
原创 114、Linux常用命令和用法
只有当链接计数为0时,文件才会被真正删除。sed -i '2s/hello/world/g' file 不加-i,只会显示修改后的内容,不会真正修改源文件;加-i,会真正修改源文件。cp abc.txt /dir/def.txt 将abc.txt复制到/dir目录下,并重命名为def.txt。mv abc.txt /dir/def.txt 将abc.txt移动到/dir目录下,并重命名为def.txt。sed '2s/hello/world/g' file 将第2行hello替换为world,模糊匹配。
2024-04-05 00:30:55
128
原创 113、设计模式
如果没有使用volatile关键字,那么会先将instance指向分配的内存地址,然后再初始化instance,如果在这两步之间有一个线程调用了getInstance方法,那么该线程拿到的是一个尚未完成初始化的instance,会导致该线程在使用instance时发生错误。懒汉采用了延迟加载的方式,在需要使用实例时才去创建,既有线程不安全的实现方式也有线程安全的实现方式,优点是延迟加载节约了系统资源,缺点是对于线程安全的实现,性能比饿汉低,因为在创建实例时会加锁。
2024-04-04 20:03:52
354
原创 112、Java基础汇总
第一是因为String类源码中的字符数组是被private final修饰的,并且Stirng类也没有暴露修改这个字符数组的方法,这意味着我们不能从外部修改String对象内部的字符数组。第二是因为String类自己是被final修饰的,这意味着它不能被子类继承和修改。这两点共同确保了String的不可变性。
2024-04-04 12:51:01
2013
1
原创 111、RPC项目总结
被@RpcReference标注的接口对象,我们都会在postProcessAfterInitialization方法中创建出它的代理对象,当调用目标对象的方法时,会调用代理对象的invoke方法,先将接口名、方法名、参数、分组名、版本号等信息封装成RpcRequest对象,并给RpcRequest设置一个唯一的请求id,以便在处理响应结果时,能分辨出是哪个请求的响应结果。它有两个属性group和version,当一个接口有多个实现类时,可以根据分组名和版本号找到具体的实现类。
2024-04-03 17:18:56
416
原创 110、EventloopGroup和EventLoop?
在服务端中通常会创建两个EventLoopGroup,分别是BossGroup和WorkerGroup,其中BossGroup负责接收客户端的连接请求,WorkerGroup负责处理网络通信过程中的读写操作。而客户端通常只需要与服务端建立一个或少量的连接,所以一个EventLoopGroup就能满足客户端的需求。EventLoop是事件循环,它里面绑定了一个线程和一个Selector,它可以通过Selector处理多个Channel的IO操作,但一个Channel只会被一个EventLoop所处理。
2024-04-03 17:18:04
163
原创 108、Netty长连接、心跳机制了解么?
在Netty中我们可以通过ChannelOption的keepalive选项来实现长连接,当启用了keepalive选项后,即使客户端和服务端之间没有数据传输,它俩之间的连接也会自动保持一段时间,如果在这段时间内仍然没有数据传输,它俩才会断开连接。我们还可以配合Netty的心跳机制来检测和保持连接的状态,在没有数据传输时,心跳机制会让客户端定期发送一个无用的消息给服务端,然后服务端作出响应,从而保持它俩之间的长连接,还可以用来检测连接是否正常,如果服务端在一段时间内没有收到任何消息,就认为连接已经断开。
2024-04-03 17:15:20
266
原创 107、Netty的核心组件?
Netty主要是由三层结构构成的,分别是网络通信层、事件调度层和服务编排层,网络通信层有三个核心组件Bootstrap、ServerBootstrap和Channel,事件调度层有两个核心组件EventLoopGroup和EventLoop,服务编排层有三个核心组件ChannelPipeline、ChannelHandler和ChannelHandlerContext(保存ChannelHandler的上下文信息)。
2024-04-03 17:10:51
227
原创 106、Netty的线程模型?
BossGroup专门负责接收客户端的连接请求,它里面通常只包含一个NioEventLoop,NioEventLoop里面又包含了一个线程和一个Selector,它会通过Selector监听绑定在其身上的ServerSocketChannel,当有新的连接请求到达时,会生成一个NioSocketChannel,并将其注册到WorkerGroup中的某个NioEventLoop的Selector上。
2024-04-03 17:10:20
174
原创 105、Netty是什么?为什么要用Netty?
①Netty是一个基于NIO模型的高性能网络通信框架,其实可以认为它是对NIO网络模型的一个封装,它提供了一套简单易用的api,我们可以利用这些封装好的api去快速开发自己的网络程序。Netty封装了底层的网络通信细节,提供了一种简化的方式来处理网络通信,使开发人员能够专注于业务逻辑的实现,而无需过多关注底层的网络编程细节。第三点,Netty封装了NIO操作的很多细节,提供了一套简单易用的api,我们可以利用这些封装好的api去快速开发自己的网络程序。
2024-04-03 17:09:47
189
原创 103、Netty中的ByteBuf是什么?ByteBuf的优势?
①Netty的ByteBuf是一个可扩展的字节容器,用于在网络通信过程中存储和操作字节数据,它是对Java NIO中的ByteBuffer进行了增强和优化。ByteBuf的很多地方都体现了零拷贝,比如slice方法、duplicate方法、CompositeByteBuf类。ByteBuf支持池化,可以重用池中的ByteBuf实例,更节约内存,降低了内存溢出的风险。ByteBuf的读写指针是分离的,不需要像ByteBuffer那样切换读写模式。②ByteBuf可以看作是ByteBuffer的升级版,
2024-04-03 17:07:39
265
原创 102、如何解决粘包半包问题?如何自定义协议?为什么要自定义协议传输对象?
①我是使用Netty提供的基于长度的帧解码器来解决粘包半包问题的,通过给该解码器的构造函数传入合适的参数,它就能够识别出消息头的长度以及消息体的长度,从而能够正确的识别消息。我配置的最大数据帧接收长度是8兆字节,长度字段的偏移量是12个字节并且长度字段占4个字节。③第一是为了提高数据传输效率,自定义协议可以更高效地传输数据,像常见的HTTP协议的请求头中包含了大量信息,它的使用范围更广泛,但其中的很多信息是我们的RPC框架用不到的,这些信息会在数据传输过程中增加不必要的开销。
2024-03-28 23:15:20
145
原创 101、粘包和半包是什么?产生原因?
②本质上是因为TCP是以“流”的形式传输数据的,而“流”数据是没有明确边界的,所以就会导致粘包半包问题。半包指的是在数据传输时,接收端只收到了一条消息部分数据而非完整的数据,类似于一条消息被切分成了两段。①粘包指的是在数据传输时,在一条消息中读取到了另一条消息的部分数据,类似于两条消息粘合在了一起。
2024-03-28 23:13:04
190
原创 100、数据该如何序列化和反序列化?几种常用序列化方式比较?
①首先需要类实现了Serializable接口,然后我使用了二进制序列化框架Kryo,配合ByteArrayOutputStream实现序列化将对象转化为字节数组,配合ByteArrayInputStream实现反序列化将字节数组转化为java对象。Kryo相比于Hessian的优点是速度快、序列化后体积小,但Kryo只兼容Java语言,而Hessian提供了跨语言支持。②Kryo和Hessian是二进制序列化框架,而Gson是一个基于JSON格式的序列化框架。
2024-03-28 23:12:02
131
原创 99、服务端如何处理请求?为什么要通过反射的方式执行远程调用?
①首先使用基于长度的帧解码器解决粘包半包问题,然后使用自定义的编解码器解析出ByteBuf中的数据,并将其封装为RpcMessage对象,接着在下一个Handler的channelRead方法中判断是否是心跳请求,如果是的话就将RpcMessage中data属性的值设为pong,如果不是的话就通过反射的方式执行方法调用,得到结果后写回给客户端。
2024-03-28 23:10:49
186
原创 98、RPC原理?
首先服务消费者会以本地调用的方式调用远程服务,然后客户端代理对象接收到调用后会将接口名、方法名、参数等信息封装成消息体RpcRequest对象并进行序列化,然后找到远程服务的地址并将消息发送给服务端。服务端接收到消息后先将消息反序列化为RpcRequest对象,并获取其中的接口名、方法名、参数等信息,然后拿着这些信息通过反射的方式调用本地方法,得到方法执行结果后会将其封装成RpcResponse对象并进行序列化,然后发送给客户端。
2024-03-28 23:09:39
204
原创 97、RPC是什么?为什么要用RPC?既然有HTTP协议,为什么还要有RPC?
②RPC可以帮助我们调用远程服务器上某个服务的方法就像调用本地方法一样简单,当我们想要调用远程服务器上的方法时,由于两个不同服务器上的服务提供的方法不在一个内存空间中,所以需要通过网络编程才能传递方法调用所需要的参数,并且方法执行的结果也需要通过网络编程来接收。③HTTP协议的请求头中包含了大量信息,它的使用范围更广泛,但其中的很多信息是我们的RPC框架用不到的,这些信息会在数据传输过程中增加不必要的开销。为了实现不同公司之间的通信,需要有一个统一的标准,HTTP就是为了满足这个需求而诞生的。
2024-03-28 23:08:18
280
原创 96、NIO的核心组件有哪些?
第一个是Buffer,NIO读写数据都是通过Buffer进行操作的,读数据时会将Channel中的数据读入到Buffer中,写数据时会将Buffer中的数据写入到Channel中。第三个是Selector,它能让一个线程处理多个Channel,所有的Channel都可以注册到Selector上,由Selector来分配线程去处理事件。第二个是Channel,它是一个双向的、可读可写的数据传输通道,NIO通过Channel来实现数据的输入和输出。
2024-03-28 23:07:13
140
原创 95、IO模型有几种?BIO、NIO、AIO 有什么区别?
同步非阻塞IO模型的最大缺点是应用程序会不断地发起IO调用,去询问内核是否把数据准备好了,这个过程是非常消耗CPU资源的。不过NIO可以通过Selector组件实现基于事件驱动的IO多路复用模型,从而解决这个问题,用户线程首先会发起select调用去询问内核是否把数据准备好了,内核把数据准备好了后会通知用户线程,用户线程此时再发起read调用。AIO属于异步IO模型,它是基于事件和回调机制实现的,应用程序发起read调用后不会阻塞在那里,当内核处理完成后,操作系统会通知相应的线程进行后续的操作。
2024-03-28 23:05:52
315
原创 94、什么是IO?
IO是Input和Output,也就是输入和输出 ,数据输入到计算机内存的过程是输入,反之输出到外部存储的过程是输出。数据的传输过程类似于水流,因此也称为IO流。
2024-03-28 23:04:52
256
原创 93、Java 中的IO流分为几种?
InputStream和Reader是所有的输入流的基类,前者是字节输入流,后者是字符输入流。OutputStream和Writer是所有输出流的基类,前者是字节输出流,后者是字符输出流。按照操作单元划分,可以划分为字节流和字符流。按照流的流向划分,可以分为输入流和输出流。
2024-03-28 23:04:20
132
原创 92、RabbitMQ的延时队列?
首先在RabbitMQ的管理界面中创建一个特定的队列,根据参数指定此队列的死信交换机和死信路由键,并设置消息的过期时间是30分钟,同时不让任何消费者监听此队列,那么这个队列就成为了延时队列。当订单创建成功后会将订单消息投递给延时队列,30分钟后这个订单消息就会变为死信,然后由死信交换机根据死信路由键重新投递给新的消息队列,消费者拿到新队列中的消息后,会先判断此订单是否已经支付了,如果未支付的话会关闭订单,并设置订单的状态为取消。
2024-03-28 09:45:48
134
1
原创 91、RabbitMQ如何避免消息的重复投递、重复消费?
第二种方案,其实这个就是典型的幂等性问题,我们可以使用Reids的分布式锁来保证幂等性,在消费者处理消息前,先使用setnx命令向Reids中插入一条数据,key是消息id,这个步骤就相当于获取锁,成功获取锁的消费者才允许去处理消息。第一种方案,如果消息体中存在业务的唯一标识并且要执行的是插入操作,那么在消费者处理消息前,先判断数据库中是否已经存在对应地数据,如果存在的话就说明这个消息已经被消费过了,不需要被再次消费,如果不存在的话我们再处理这条消息。
2024-03-28 09:21:23
627
原创 90、在RabbitMQ中,如何保证消息不丢失(消息的可靠性)?
第三是要设置消费者的ack确认机制是manual,也就是消费者在处理完消息后,由消费者自己完成ack,比如调用channel的basicAck方法手动删除消息,或者调用channel的basicReject方法将消息重新放回队列。第一是要开启生产者确认机制,当MQ成功接收到生产者的消息时,会回调ConfirmCallback接口的confirm方法,告诉生产者它收到消息了。第四是MQ自身要开启持久化功能,确保消息在未被消费之前,在队列中不会丢失,其中交换机、队列和消息都要开启持久化。
2024-03-28 09:20:36
215
原创 89、MQ常用场景?几种MQ组件比较?
第二个是应用解耦,生产者将消息投递给消息队列,无需关心这些消息的消费者是谁,同样的,消费者从消息队列中接收并处理消息,也无需关心这些消息的生产者是谁,这种解耦使得系统中的各个部分可以更加独立地开发和部署,提高了系统的可扩展性。RabbitMQ的吞吐量较低但具有非常高的可靠性,支持消息确认、消息持久化、消息路由等特性,适用于对可靠性要求比较高的场景。第三个是异步任务,可以将耗时的任务放入到消息队列中,然后由消费者去异步处理,从而加快系统的响应速度。
2024-03-28 09:20:14
227
原创 88、RabbitMQ是什么?RabbitMQ核心概念?RabbitMQ的特点?
①RabbitMQ是一个简单易用、稳定可靠的消息队列系统,实现了AMQP协议,相比于其他的消息队列系统,RabbitMQ提供了更加可靠的消息传递机制和灵活的路由机制,更适用于异步地处理任务。Exchange交换机,负责接收生产者的消息,并根据路由键把消息路由到相应的消息队列中,有4种类型的交换机,分别是direct(默认)、topic、fanout和headers。②Producer生产者,负责生产消息并将消息投递给指定的交换机,并指定相应的路由键。Consumer消费者,负责从消息队列中接收并处理消息。
2024-03-27 21:24:41
235
原创 87、什么是双亲委派模型?双亲委派模型的好处?
①它是这样的,当一个类加载器收到加载请求后,它不会立即去尝试加载该类,而是会将请求委派给它的父加载器,父加载器同样也会向上委派,直到到达顶层的启动类加载器。如果父加载器能够完成类的加载,那么会将加载成功的类返回给子加载器,如果父加载器不能完成类的加载,那么子加载器才会尝试自己去加载。②主要有两个原因,第一个是避免重复加载,当父加载器已经完成类的加载后,不需要子加载器重复加载,保证了类的唯一性。第二个是为了安全,确保了核心Java类总是由启动类加载器加载,从而防止这些类被恶意篡改。
2024-03-27 21:15:00
218
原创 86、什么是类加载器?类加载器有哪些?类加载过程?方法的调用和执行过程?
符号引用是编译时的引用,不指向具体的内存地址,而是使用符号来标识目标,比如在编译阶段,我么可以使用方法名引用目标方法,方法名就是符号引用。在解析阶段,JVM会将符号引用转换为直接引用,直接引用指向方法的具体内存地址,从而使得JVM能够正确调用该方法。第四步,方法执行完后会返回一个结果,这个结果可以是一个值或者是一个对象引用或者是void。④第一步,将方法的符号引用转换为直接引用,定位到方法的具体内存地址(位于方法区中)第五步,从虚拟机栈中清除此方法的栈帧,同时会将方法的返回结果传递给上层方法。
2024-03-27 21:10:34
186
原创 85、JVM的垃圾回收算法?YoungGC、MajorGC、FullGC?垃圾回收器?
在并发标记阶段会开启用户线程,用户线程可以和GC线程一起并发运行,GC线程会并发标记出所有可达对象,但由于用户线程会不断的更新引用域,所以GC线程不能保证可达性分析的实时性,这个过程的停顿时间较长。第二个复制算法,它是将某块内存分为两块,分别叫做From区和To区,新创建的对象会被分配分在From区中,From区满了就会进行垃圾回收,将From区中存活的对象复制到To区中,然后清空From区。标记整理算法解决了标记清除算法的内存碎片化问题,但效率仍然比较低,适用于垃圾回收频率较低的内存区域,比如老年代。
2024-03-27 20:58:51
252
1
原创 84、对象什么时候可以被垃圾回收器回收?引用计数法?可达性分析算法?
②引用计数法是给对象中添加一个引用计数器,初始值为0,每当有一个地方引用它时计数器就加1,当引用失效时计数器就减1,计数器为0时就说明这个对象可以被回收了。这个方法实现起来简单并且效率高,但是目前主流的虚拟机中并没有选择这个方法来管理内存,主要是因为它很难解决对象间的循环引用问题,比如A、B两个没有用的对象互相引用着对方,导致它俩的计数器始终不为0,垃圾回收器就无法回收它俩。①如果一个对象不再被引用,那么这个对象就可以被回收了,垃圾回收器就会在合适的时机回收它。
2024-03-27 20:28:14
250
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人