- 博客(194)
- 收藏
- 关注
原创 Spring Cloud系列—SkyWalking链路追踪
作为SkyWalking的原生数据库,BanyanDB目前还处于高速研发的阶段,随着BanyanDB子项目的不断发展,SkyWalking官方宣布,BanyanDB 0.8已经完全生产可用,是生产环境的理想选择。ES基于倒排索引和分片机制,擅长处理海量时序数据的查询与聚合分析,可通过集群分片应对PB级数据存储需求,并且社区支持广泛,但是ES的运维成本较高,需要独立部署ES集群,对资源消耗大,使得ES的性价比不是很高。应用性能监控,通过收集、分析和可视化应用运行时的数据,帮助运维及时分析系统性能和优化系统。
2025-08-21 12:52:46
487
原创 Spring Cloud系列—Seata分布式事务解决方案TCC模式和Saga模式
在此之后,拥堵在网络上的一阶段Try数据包被TCC服务收到,出现了二阶段Cancel请求比一阶段Try请求先执行的情况,由于已经执行过二阶段的Cancel(空回滚),因此TCC服务执行晚到的Try之后,将永远不会再收到二阶段的Confirm或者Cancel,造成TCC服务悬挂。TC在调用TCC服务的一阶段Try操作时,可能会出现因网络拥堵而导致的超时,此时事务管理器会触发二阶段回滚,调用TCC服务的Cancel操作,Cancel调用未超时(空回滚)。假设存在全局事务T1和T2,都需要执行余额-30的操作。
2025-08-20 11:19:39
656
原创 Spring Cloud系列—Seata分布式事务解决方案AT模式
tx2全局事务在tx1全局事务的二阶段前开启并执行,执行m-100后m=800(由于tx1一阶段会提交本地事务,因此tx2全局事务会读取m修改后的值),在提交本地事务前需要先获取全局锁,但是由于全局锁在tx1手里,因此就会不断重试获取全局锁。通过SELECT FOR UPDATE语句的代理查询tx1事务提交后的数据,该语句会获取全局锁,如果未获取到全局锁,说明事务未提交,就释放本地锁并阻塞等待,阻塞期间不断重试获取全局锁,此时读取的数据就是读已提交的数据,从而避免脏读问题。(数据库数据会真实发生变化)。
2025-08-19 15:27:56
925
原创 Spring Cloud系列—Seata分布式事务解决方案XA模式
性能较差,执行阶段需要锁定数据库资源,等待完成阶段结束才释放,导致事务资源长时间得不到释放,锁定周期长,从而影响性能。XA模式是基于X/Open组织定义的RM与TM之间交互的XA协议(实现原理就是2PC),其核心理念是利用事务资源(数据库、消息服务等)对XA协议的支持,来管理分支事务。TM负责全局事务的开启和结束的通知,即在业务代码中,需要开始事务的方法就是TM部分。简而言之,分支事务的执行提交和回滚仍然由数据库(RM)负责,TM和TC只负责全局事务的开始/结束、分支事务的状态管理等。
2025-08-18 14:19:00
656
原创 Spring Cloud系列—Seata部署
双击运行\seata-server\bin目录下的seata-server.bat,出现seata server started in 1462 millSeconds说明启动成功。两个端口号都需要开放。这里采用Windows部署方式,前往seata官网下载安装包,并将安装包解压到本地:https://seata.apache.org/zh-cn/release-history/seata-server/,管理分支事务处理的资源,负责分支事务的提交或回滚,并与TC通信来注册或汇报分支事务的状态。
2025-08-17 13:32:16
629
原创 Spring Cloud系列—Alibaba Seata分布式事务
DoCommit阶段如果所有的参与者都是可以提交的,则协调者发送“提交”请求,参与者提交事务并返回确认,从而协调者完成整个事务的提交。如果任何一个参与者在Try阶段返回给事务管理器的结果是失败,事务管理器就会给所有参与者发送Cancel请求,各参与者释放锁定资源,并回滚操作,保证数据的一致性。所有参与者提交事务,并返回ACK给协调者。针对2PC协议可能出现的问题,比如超时未应答导致阻塞、协调者参与者互相等待导致资源被长时间锁定,引入超时机制和预提交阶段,把两阶段改成三阶段,就有了性能更好的三阶段提交协议。
2025-08-16 14:34:17
856
原创 Spring Cloud系列—Alibaba Sentinel授权与规则管理及推送
而Push模式的数据源通常是基于远程配置中心的,比如Nacos、ZooKeeper等等。但是反之,如果在Sentinel Dashboard修改流控规则,Nacos配置中心的规则无法同步,这需要开启Sentinel集成Nacos持久化,从而让Sentinel Dashboard和Nacos的通信是双向的。Sentinel Dashboard页面,多了选项流控规则V1,该选项修改的流控规则就会同步给Nacos,选项流控规则还是原来的选项,只能接受Nacos往Sentinel Dashboard单向同步。
2025-08-15 10:49:35
1011
原创 Spring Cloud系列—Alibaba Sentinel熔断降级
熔断是由断路机(熔断器)统计服务调用的慢调用比例、异常比例和异常数,如果超过阈值则进行熔断,拦截请求该服务的请求;在统计时长内,请求数超过最小请求数,且慢调用(请求响应时间超过最大RT(最大响应时间))比例超过比例阈值,就进行熔断,暂停该资源一定时间(熔断时长)的访问。在统计时长内,请求数超过最小请求数,且发生异常的数量超过设置的异常数,就进行熔断,暂停该资源一定时间(熔断时长)的访问。在统计时长内,请求数超过最小请求数,且异常比例超过比例阈值,就进行熔断,暂停该资源一定时间(熔断时长)的访问。
2025-08-14 14:01:27
739
原创 Spring Cloud系列— Alibaba Sentinel限流
对应RuleConstant.CONTROL_BEHAVIOR_WARM_UP,预热模式,在设置的预热时间内,请求的QPS阈值初始值为阈值(maxThreshold)/冷因子(coldFactor),coldFactor默认为3,然后从初始阈值逐渐上升到设置的阈值。比如某微服务系统,服务1调用服务2,服务2调用服务3,假设服务3故障,此时服务2向服务3发送的请求就会超时,进而服务1向服务2发送的请求也会超时,在高流量的情况下,所有的请求都会等待很长时间然后超时,导致系统资源被耗尽而无法得到有效利用。
2025-08-13 17:34:10
759
原创 Spring Cloud系列—Config配置中心
注意:如果需要长度不限的JCE包,就需要从Java官网下载:https://www.oracle.com/java/technologies/javase-jce8-downloads.html,并把下载好的jar包放到Java安装目录下的/jre/lib/security目录中(覆盖)。上述自动刷新,如果配置中心有多个不同端口号服务时,由于刷新端点(监控的地址/actuator/refresh)需要指定ip和端口号,因此手动刷新只能对其中一个服务生效,剩下的服务仍然不能生效。
2025-08-12 15:22:37
589
原创 Spring Cloud系列—Gateway统一服务入口
Gateway的路由匹配基于Route Predicate Factories(路由断言工厂),在Gateway的配置文件中,通常会定义路由匹配规则,服务启动时Route Predicate Factories会识别路由匹配规则并转化为Predicate对象,然后由这些Predicate的条件组合来进行请求的路由。GlobalFilter是Gateway的全局过滤器,也是用来条件过滤的,不同的是GlobalFilter应用于全局所有请求,而GatewayFilter只应用于对应设置的路由。
2025-08-11 20:00:26
1122
原创 VirtualBox虚拟机网卡配置
NAT网络地址转换,是让虚拟机通过主机访问外部网络的方式。在VirtualBox中对应两种网卡:每台虚拟机都有独立的NAT设备,虚拟机之间相互隔离,无法直接通信。多个配置NAT网络网卡的虚拟机可以共享同一个NAT设备,此时这些虚拟机组成局域网,可以相互通信。无论是网络地址转换(NAT),还是NAT网络,外部网络和主机都无法直接访问虚拟机,需要配置端口转发来实现。虚拟机通过宿主机的网卡建立连接,即虚拟机与宿主机组成局域网,为虚拟机分配与宿主机在同一个网段下的ip(网络号相同,设备号不同)。
2025-08-11 19:56:38
1058
原创 Spring Cloud系列—OpenFeign远程调用
上述代码可以发现,在服务调用方实现OpenFeign客户端的代码和服务提供方实现的接口非常相似,那么我们就可以定义一个公共的接口,让服务提供方实现该接口,让服务调用方的OpenFeign客户端接口继承该接口,再把公共接口以一个单独公共的jar包导入项目中,实现项目的解耦。方法的声明格式就类似于product-service的方法实现一样,不一样的是productId是从路径中获取的,因此需要添加@PathVariable("productId")注解。
2025-08-10 19:16:15
924
1
原创 Spring Cloud系列—Nacos配置中心
微服务启动时会创建三个监听器,分别监听${prefix}-${spring.profiles.active}.${file-extension}、${prefix}.${file-extension}和${prefix}这三个配置中心的配置项对应的文件。如果想要配置管理的命名空间和服务管理的命名空间一致,需要在服务中配置文件的Nacos配置中心的配置项(即bootstrap.yml文件)配置namespace和服务管理的命名空间一样(如果不配置默认都读取public命名空间下的配置项)。
2025-08-09 13:53:07
994
原创 Spring Cloud系列—Nacos服务注册/发现
在实际中,服务的实例可能分布在不同地方,比如product-service服务实例共5个,3个在西安,2个在武汉。临时实例定期向Nacos发送心跳汇报自身健康状况(默认5s),Nacos超时未收到心跳信息就会把临时实例设置为不健康(超时时间默认15s),再过一段时间就会将临时实例删除(默认30s)。当某个服务实例出现问题,比如接口响应时长慢,此时就需要对服务进行问题排查,就需要先下线服务。Nacos定期向永久实例探测健康状况(默认20s),健康检测失败就会标记为不健康,但不会从服务列表删除该实例。
2025-08-08 09:52:42
740
原创 Spring Cloud系列—LoadBalance负载均衡
这种方式就是一种负载均衡,是一种客户端负载均衡。创建多个实例后,多次访问接口就会出现始终访问端口号为同一个的实例,这是因为服务发现时Eureka给我们提供随机的服务列表,但是每次都只获取其中下标为0的服务实例,这就会导致某个实例负载过大,因此需要负载均衡。但是上述代码有一些不足之处:服务一旦启动,服务发现一次,其余时间不再服务发现,因此对于服务的注册和下线是无感知的。loadBalancer.choose()的choose()方法是ReactiveLoadBalancer接口的choose()方法,
2025-08-07 13:33:56
750
原创 Spring Cloud系列—Eureka服务注册/发现
Zookeeper节点存在地位划分,主要是Leader、Follower或Observer,这就意味Leader节点故障需要进行重新选举Leader,存在一定时间的服务不可用。,指同一时间无论访问主节点还是从节点获得的数据是一致的(强一致性,弱一致性是主节点涉及修改后由于同步需要时间,因此存在一定时间的不一致)。是指服务提供方启动时主动向服务注册中心注册服务,并定期向注册中心发送心跳包,汇报自身存活状态。是指服务消费者要调用服务提供方接口时,先去服务注册中心查询服务相关信息,比如地址等。
2025-08-06 14:58:30
1036
原创 Spring Cloud系列—简介
5.服务可用性的保证,由于服务数量多,再加上集群环境的复杂,流量高的情况下容易导致某个节点宕机,因此需要使用负载均衡和有效的服务发现来进行流量控制。现在两个服务可以各自独立运行,但是订单信息上是需要显示商品信息的,因此订单服务需要访问商品服务根据订单上的商品id查询订单对应的商品。2.运营成本高,不同服务需要的运行环境不同,不同服务需要的打包、构建等流程也不同,同时因为集群可用性的保证,使得运营成本更高。分布式是每个节点业务不同,无法相互替代,某个节点宕机,其负责的业务就会无法访问。
2025-08-05 14:49:01
670
原创 RabbitMQ—HAProxy负载均衡
注意:由于增加了负载均衡器,如果Haproxy所在节点也发生宕机,对于客户端来讲就无法与RabbitMQ交互,因此通常会用Keepalived等高可用解决方案对haproxy做主备,在HAProxy主节点故障时自动将流量转移到备用节点。因此,直接访问某个节点不太好,需要访问一个统一的入口,该入口来帮助负载均衡到不同的RabbitMQ节点。2.如果都只访问集群的某一个节点,容易导致该节点负载过大从而容易崩溃,而其它集群节点很可能比较空闲,因此需要把消息负载均衡到不同的RabbitMQ节点。
2025-07-25 09:38:43
658
原创 RabbitMQ—仲裁队列
S3成为新Leader后向所有节点发送心跳包,此时S1处于Candidate状态接收到心跳包后得知S3的term高于自己,说明已经有新Leader,于是变为Follower,开始正常工作。上述+2表示还有2个副本。当集群中节点数大于五个,比如6个节点,则默认只有5个副本,1主4从副本,从副本随机分配在除主节点外的其它5个节点上(有一个节点会没有从副本)。而仲裁队列就是上述Raft算法运行的集群上的队列,每个仲裁队列有一个主和多个从副本,主副本在主节点(创建仲裁队列的节点是主节点)上,从副本在从节点上。
2025-07-24 11:03:14
858
原创 RabbitMQ集群搭建
在使用命令service rabbitmq-server start启动了一个节点后(主节点),使用rabbitmqctl status来查看当前节点的具体状态和信息(当RabbitMQ只部署到一个节点上,如果节点宕机就会导致整个系统不可用,集群方案就是解决这一类问题的方案(MySQL、Redis等集群思想也都差不多)。注意:集群中的队列、交换机等信息是共享的,即在任意一个节点都可以查询到。但是消息不是共享的,消息在哪个队列所属的节点,该节点关闭后,消息也会消失。由于真正的集群搭建成本较高,因此采用。
2025-07-23 11:03:29
991
原创 Redis原理之分布式锁
如果已经结束则通过lua脚本解锁。新的问题又出现了,执行解锁的过程中,由于get命令和del命令的执行不是原子性的,因此就会出现命令插队的情况。普通的锁比如Java中的synchronized通常解决的是线程安全问题,但是到了多进程多服务器环境下,普通的锁就无法保证多个进程或节点同时访问同一个资源的问题,这就需要分布式锁。上述方案还有问题,由于多个服务器都可以访问Redis来执行各种命令,就可能出现一个服务器设置键值对(加锁),另一个服务器删除键值对(解锁),从而导致问题(当然这个问题不是故意的)。
2025-07-23 11:01:24
1197
原创 RabbitMQ应用问题
对于最少一次,如果消息处理成功但是ACK因为网络等问题没有返回(生产者-MQ的发布确认模式、MQ-消费者的消息可靠性保证机制(手动确认)),消息就会重发,因此就会出现消费者对同一条消息多次处理的情况(同一订单多次扣款)。但是如果在这一过程中执行了修改操作,select查询的结果就不一样,这并不意味着select操作不是幂等的,因为幂等性指对资源的影响,而不是对结果的影响。:队列向消费者分发消息是并行进行的,因此一些顺序性的消息就被分发到不同消费者,不同消费者处理速度不一样,就无法保证顺序性。
2025-07-22 10:50:54
1090
原创 Redis原理之缓存
查询的key在Redis和MySQL数据库中都不存在,这样的key不会被实时缓存到Redis中,后续如果这类key频繁访问,依然会对MySQL造成较大压力。缓存穿透的特殊情况,缓存穿透是针对普遍的key(包括热点和非热点)突然同时失效的问题,而缓存击穿是指热点key突然过期,导致大量查询未命中去查数据库。当Redis刚启动或大批key同时过期,此时Redis中没有数据,查询就无法命中缓存,从而去查MySQL,给数据库带来大量查询压力。1.业务未进行合理的参数校验,导致非法的key被查询。
2025-07-22 10:47:33
987
原创 RabbitMQ—事务与消息分发
当prefetchCount达到设置的上限,队列就不再向消费者推送消息,直到有新的确认到来。RabbitMQ的事务机制要求消息的发送和接收是原子性的,要么同时成功,要么同时失败(失败后已发送的消息或接收的消息会回退)。当某个队列被多个消费者订阅,队列向消费者推送消息(消息分发对应推模式,对拉模式无效),每条消息只会发送给一个消费者。在这种情况下,假设有10条消息,两个消费者,每个消费者会被推送5条消息,消费者1消费速度快(容易空闲),消费者2消费速度慢,那么消费者2就会消息积压,系统实际吞吐量并不高。
2025-07-19 14:09:10
1192
原创 Redis原理之集群
命令redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave --cluster-master-id [110节点的ID]进行分片内主从关系的构建,第一个ip表示要把哪个节点加入到集群中,第二个ip表示集群中任意节点,--cluster-slave表示当前节点是slave类型,--cluster-master-id表示该slave从属哪个master。注意1:Redis集群是最多能有16384个分片吗?
2025-07-19 14:06:36
952
原创 Redis原理之哨兵机制(Sentinel)
需要提前安装docker和docker-compose,docker简单来讲是一个类似虚拟机的容器,它小巧轻量,提供了容器来统一配置环境信息,尤其是在多服务的环境中,配置很容易出现冲突,使用docker创建容器就可以实现多个服务的环境配置的冲突隔离。如果是slave节点故障,对读写没有太大影响;但是如果是主节点挂了,从节点是不会自动变为主节点的。则是启动节点的方式,ports是端口映射(把物理机的端口映射到容器的端口,容器端口和物理机端口独立,容器端口和容器端口独立,映射了后就可以让物理机访问容器)。
2025-07-18 15:30:53
1079
原创 RabbitMQ—TTL、死信队列、延迟队列
而在消息TTL中,连续发送过期时间长和过期时间短的消息,即使过期时间短的消息已经过期,只要过期时间长的消息还未过期,过期时间短的消息仍然会在队列中。比如消息1TTL为10s,消息2TTL为30s,消息2先发送,消息1后发送。比如订单超时支付自动取消,订单系统下单时设置延迟时间,并将订单消息投递到RabbitMQ中,消息超时则把订单消息发送给消费者(订单系统的订单状态处理模块),订单系统根据是否收到支付系统支付成功的消息或超时订单来修改订单状态(成功支付或超时未支付)。注意:队列TTL和消息TTL的区别。
2025-07-18 15:28:00
774
原创 RabbitMQ—消息可靠性保证
因此消息会先进入OS的缓冲区,待缓冲区满时再统一进行持久化,虽然这个时间很短,但是这期间如果RabbitMQ宕机,消息还为持久化到磁盘上,也会丢失(解决办法:(1)仲裁队列,主从结构。消息确认机制(自动确认和手动确认),自动确认(消息一经发出RabbitMQ就认为消息能到消费者于是进行确认并清除消息,默认auto级别的自动确认),如果需要保证消息的高可靠性需要开启手动确认(消费者显示调用肯定确认或否定确认方法来通知RabbitMQ,RabbitMQ根据手动确认的参数来决定确认成功、重新入队或丢弃)。
2025-07-17 12:51:54
725
原创 Redis原理之主从复制
role表示节点的角色,master_replid是主节点的身份码,offset偏移量表示复制的进度(不是瞬间就把所有的信息复制完),priority表示从节点优先级(用于主节点挂了从节点竞争成为主节点的场景),backlog表示积压缓冲区(和主从复制的策略有关),其余信息字面意思就很容易明白。master节点进行写,slave节点进行读。由于所有的节点的数据都时刻保持一致,因此请求哪个节点得到的数据都一样,这也就提高了系统的性能和并发量,同时如果某个从节点挂掉,只需要请求其他节点即可,提高了可用性。
2025-07-17 12:48:03
904
原创 多注册中心冲突报错Field autoServiceRegistration in org.springframework.cloud.client.serviceregistry
配置了Nacos作为注册中心,项目启动时报错:这是由于启动项目时会自动进行服务注册,需要注入一个唯一的Bean:AutoServiceRegistration,但是容器发现存在两个父类均为AutoServiceRegistration的Bean,一个对应Nacos,一个对应Eureka,简而言之,注册中心太多了,Spring不知道把服务注册到哪个注册中心。
2025-07-16 15:06:19
129
原创 Redis原理之事务
为了解决该问题,Redis引入命令watch,该命令可以监控一个或多个key,一旦在事务期间(multi与exec之间,操作命令放入队列后),其他客户端对监控的key进行修改,就会让执行事务的客户端感知到key被修改了,从而告诉用户该问题的风险。可以发现最终结果是客户端1事务执行后的结果,原因是因为事务队列的命令虽然先到Redis服务器,但是并没有真正执行。假设在客户端1开启事务,把命令放入事务队列,此时客户端2不开启事务,对客户端1那个命令的key进行修改,客户端1再执行事务。
2025-07-16 12:41:54
835
原创 使用Spring Cloud LoadBalancer报错java.lang.IllegalStateException
在使用Spring Cloud LoadBalancer进行负载均衡时,遇到错误:这里使用的restTemplate是使用@LoadBalanced注解的,因此会对该url进行解析,但是解析报错。
2025-07-15 20:03:27
852
原创 Redis原理之持久化
注意:子进程的重写类似于RDB快照文件的生成,因此Redis为了速度,引入混合持久化(配置文件中配置项aof_use_rdb_preamble可以修改是否开启),即开启混合持久化后子进程重写新的AOF文件存储的是和RDB一样的二进制数据,而在后面aof_rewrite_buf缓冲区追加操作新的AOF文件存储的是文本形式的命令操作。就自动触发RDB文件的生成。4.子进程在创建后执行重写,由于子进程已经有父进程fork前的数据了,而AOF文件最终目的是恢复数据,因此只需要把内存中的数据重写到新的AOF文件中。
2025-07-15 17:12:48
989
原创 RabbitMQ工作流程
Producer和RabbitMQ、Consumer和RabbitMQ基于TCP来建立连接,一个连接包含多个通道channel(逻辑上各通道之间相互独立,用于实现连接复用,减少频繁建立/关闭TCP连接的开销),发送消息和接收消息都是基于channel。交换机,生产者的消息进入RabbitMQ后首先进入Exchange,由Exchange进行路由分发(根据消息类型、规则和标签等等),把消息分发给指定的Queue。组件,生产者的消息首先传输到交换机,由交换机进行路由分发到指定的队列中并等待消费者接收。
2025-07-15 17:10:05
1093
原创 Spring原理—加载Bean
最关键的注解是@EnableAutoConfiguration,负责第三方依赖的配置类(@Bean注解的方法获得第三方依赖的对象)和组件(比如MyBatis的@Mapper注解不属于Spring)的扫描,其中包含两个关键注解:@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})。@AutoConfigurationPackage注解把启动类所在的包下面所有的组件都注入到Spring容器中。
2025-07-15 17:06:08
599
原创 SpringBoot系列—统一功能处理(统一异常处理)
initHandlerMappings()方法负责完成请求控制器路由映射处理器的初始化,即该处理器会把请求的URL和控制器方法建立映射关系。如果有多个异常,就通过sort()方法排序,按异常的深度排序(ExceptionDepthComparator类表示异常深度比较器,比如Exception深度为1,那子类RuntimeException的深度就是2,RuntimeException子类NullPointerException的深度就为3),把深度最深的异常放在顺序表matches下标为0的地方。
2025-07-14 13:58:22
1037
原创 RabbitMQ的介绍与安装
(2)RabbitMQ采用Erlang语言开发,MQ功能比较全面,几乎支持所有主流语言,开源,提供的界面也很友好,性能较好,吞吐量能达到万级,社区活跃度较高,比较适合中小型公司、数据量没那么大,且并发量没那么太高的场景。点击右侧的Virtual Hosts可以进行虚拟机的管理,这里的虚拟机不同于传统的虚拟机(虚拟电脑),而是表示逻辑上的环境隔离,作用就和MySQL的databases一样,不同的database负责不同的业务。只不过这个队列存储的内容是消息,消息可以简单,比如字符串、JSON等等;
2025-07-14 13:55:51
867
原创 Redis客户端使用(Client、Java、SpringBoot)
由于可能有多个客户端想要跨主机访问Linux服务器的其他服务器的端口号,ssh为了区分这些端口号,就会把Linux的各种服务的端口号映射到本地主机(发出访问请求的主机)的其他端口号(比如Linux的Redis端口6379映射到本地主机8888端口),从而达到客户端访问本地端口即可实现访问Redis端口,这就是ssh的端口转发功能。其余的命令不再演示,Jedis提供的Java客户端访问Redis的命令基本和Redis客户端的命令一致,使用很简单,只是需要注意返回值和变长参数(或者是Map来组织变长参数)。
2025-07-14 13:53:42
855
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人