-
nacos的临时实例和持久化实例的区别
临时实例:注册时向nacos发起注册,并隔一段时间就发送健康检测,健康检测内容:服务名+ip+端口+更新内存中的lastUpdatedTime(nacos就是根据这个时间隔了多久还没有更新来判断是否存活的),因为状态是由实例自己传来的,nacos不能保证其真实性(例如:假如实例自己内部死锁,完全处理不了任何业务请求,但它的网络线程池还是好的,依然能每隔5秒成功发送心跳给Nacos,nacos就认为他是健康的,就会将这个实例给调用者,调用者调用就会报错)所以临时实力的健康检测只能确保网络联通和正在运行,而不能保证业务是否健康,所以只能保证AP(高可用和分区容错)。
持久化实例:持久化实例注册时由两种方法:(1)、配置了 ephemeral=false,Nacos客户端也会自动发起注册请求(2)、可以在Nacos控制台提前手动创建一条持久化实例记录,指定IP、端口、服务名。这时候服务进程甚至还没启动,Nacos里就已经有这个实例了。服务注册后,Nacos服务端会按照配置的检查类型和周期,主动向服务实例的IP和端口发起对应的协议请求,然后根据响应的结果来判断服务是否健康。所以是nacos发起健康检测。因为“探测结果(或任何对实例的修改)在Nacos集群内部,必须通过Raft协议经多数节点确认才能生效”。这种“多数派写入”的机制,从根本上保证了数据的强一致性(C),代价是当集群出现网络故障时,部分节点可能无法提供服务(牺牲了部分A)。
-
nacos包含配置管理和服务发现功能,请问,为什么要把它们放在同一个组件,两者有何共同之处?
两者都需要解决“静态配置不适用动态环境”这一核心难题。
共享统一的数据模型,
采用一致的推送机制,
-
seata的AT模式如何实现写隔离?全局锁与本地锁的区别?
Seata AT模式一阶段的完整流程:业务SQL执行→ 查询Before镜像(获取到本地锁,通过 SELECT ... FOR UPDATE语句实现的)→ 执行业务SQL→ 查询After镜像→ 构建undo_log SQL→ 向TC请求全局锁→
如果获取全局锁成功 → 插入undo_log到本地事务 → 提交本地事务
如果获取全局锁失败 → 重试等待 → 超时则回滚本地事务,所以实现隔离是因为加了锁,其他线程需要写数据必须等完成释放锁。
区别:本地锁是数据库自身的行锁机制,由MySQL InnoDB等数据库管理,作用范围仅限于单个数据库实例,在执行
SELECT FOR UPDATE或UPDATE时获取,本地事务提交或回滚时释放,它会阻塞所有要修改同一行数据的操作,无论是否Seata事务;而全局锁是Seata TC管理分布式锁,作用范围覆盖整个分布式系统,锁的对象是业务主键(如订单号),在一阶段本地事务提交前向TC请求获取,二阶段提交或回滚完成后才释放,它只阻塞其他Seata全局事务的提交,对普通本地事务无感知。两者的核心关系是:本地锁保证单库并发安全,全局锁在本地锁之上叠加一层分布式协调,确保跨服务的全局事务不会相互干扰,共同实现AT模式的写隔离。 -
数据一致性问题
-
rocketmq的事务消息如何保证消息与数据库一致性?
RocketMQ的事务消息通过“两阶段提交+事务状态回查”的机制来保证本地数据库事务与消息发送的最终一致性。第一阶段是“发送半事务消息”,生产者先向Broker发送一条对消费者不可见的“半事务消息”,Broker成功持久化后返回确认,此时消息被标记为“暂不可投递”,相当于在消息中间件侧建立了事务的锚点;第二阶段是“执行本地事务与二次确认”,生产者收到半消息确认后立即执行本地数据库操作(如更新订单状态),然后根据执行结果向Broker发送二次确认请求——本地事务成功则发送Commit,Broker将消息标记为可投递供消费者消费,本地事务失败则发送Rollback,Broker丢弃该消息,这一阶段若顺利完成即实现原子性。事务状态回查是应对异常的核心兜底机制:当生产者因网络闪断、宕机重启等原因未能及时发送二次确认时,Broker会在超时后主动向生产者发起回查请求,询问该半消息对应的本地事务最终状态;生产者收到回查后需根据业务ID查询数据库,准确返回Commit、Rollback或Unknown(状态未知),若返回Unknown则Broker会按策略进行多次回查(默认最多15次),直至获得明确结果或最终强制回滚,从而确保即便在异常场景下,数据库与消息状态也能通过异步仲裁达到最终一致。这套机制要求生产者必须实现精确的状态回查逻辑,同时下游消费者需保证幂等处理,以应对可能的消息重复投递。
-
缓存与数据库不同步,如何解决?
延迟双删
加锁
写操作:获取写锁→更新数据库→删除缓存→释放写锁
读操作:获取读锁→查缓存,命中就返回;没命中就查数据库并回写缓存→释放读锁
评论