微服务广播模式实践:维护内存数据的缓存一致性

本文分享自华为云社区《微服务广播模式实践》,作者:张俭 。

微服务广播模式,指的是在微服务多实例部署的场景下,将消息广播到多个微服务实例的一种模式。

广播模式,一般用来维护微服务的内存数据,根据数据类型的不同,有助于解决两类问题。通常广播模式会使用支持发布订阅的消息中间件实现(如Redis、Kafka、Pulsar等),本文也基于消息中间件进行讨论。

利用广播模式维护一致的缓存

这应该是广播模式利用最多的一种场景,假想一个拥有海量用户的电商网站、或是一个亿级设备连接的IoT平台。势必会存在一些缓存数据,像是用户的购物车信息,或是设备的密钥缓存。如果没有广播模式,可能会存在这样的问题

当用户更新了它的购物车之后,微服务实例1的数据发生了更新,数据库的数据也成功更新。但是微服务实例2中的缓存数据未能更新,那么如果用户的请求均衡到了实例2,就会发生意想不到的后果。

这种情况下我们可以让微服务1在广播通道中发送一个缓存的invalidate消息,将微服务实例2中该用户的缓存清零,使得微服务实例2在下一次处理该用户的请求时,从数据库中读取最新的消息。

使用该模式需要注意的点:

  • 每个微服务实例应该使用不同的消费组,可以通过微服务的IP、主机名、UUID等拼装成订阅组名称,这才称得上广播之名
  • 微服务消费消息的时候,应从Latest开始消费,避免从Earliest开始消费无用的缓存清理消息
  • 由于每一次微服务重启都会产生一个新的消费组,需要注意消费组的老化,可以通过消息中间件自带的不活跃消费组老化能力兜底,建议通过gracefulExit、监听kill信号等机制来主动删除消费组信息

为什么说消费组老化比较重要呢,因为很多监控系统都会根据消费组的积压来做告警,很容易产生误告警。

利用广播模式维护内存中的数据

这种模式相对比较少见,常见于key的基数不是很大,能够将数据完整地存储在内存中,比如电商平台的企业卖家个数、物联网平台的用户个数等,并且对数据的一致性要求不是很高(因为广播模式情况下,对于两个微服务实例来说没有一致性保障)。像Apache Pulsar设计的TableView,在我看来,就是做这个事的一个最佳实践。Pulsar内部大量使用了topic存储数据,就是采用这个方式。

使用该模式需要注意的点:

  • 同上,需要使用不同的消费组名称
  • 微服务消费消息的时候,应该从Earliest开始消费,保证所有微服务内存中的消息视图一致
  • 同上,需要注意消费组的老化

为什么需要消费组老化作为保底手段

因为在极端场景下,无论是graceful的代码,还是监听kill信号的代码,都不能保证代码百分百地被执行。需要兜底。

Kafka消费组老化

Kafka通过offsets.retention.minutes参数控制消费组中offsets保留时间,在此时间内如果没有提交offset,offsets将会被删除。Kafka判定消息组中没有在线的消费者(如empty状态),且没有offsets时,将会删除此消费组。

Pulsar消费组老化

pulsar的消费组老化策略更加灵活,可以配置到namespace级别。

sql 复制代码
bin/pulsar-admin namespaces | grep expiration
    get-subscription-expiration-time      Get subscription expiration time for 
      Usage: get-subscription-expiration-time [options] tenant/namespace
    set-subscription-expiration-time      Set subscription expiration time for 
      Usage: set-subscription-expiration-time [options] tenant/namespace
            Subscription expiration time in minutes
    remove-subscription-expiration-time      Remove subscription expiration 
      Usage: remove-subscription-expiration-time [options] tenant/namespace

这里注意要合理地配置消费组的老化时间,在pulsar的当前版本(2.11版本)下,catch up读,也就是说消费组平时积压量不大。如果将消费组的老化时间配置大于等于消息的老化时间,会出现消费组老化不了的现象。

当然,由于消费组和消息老化都是定时任务,预估时间时,要考虑一定的buffer。

这里让我们稍稍dive一下原理,消费组的老化是通过判断Cursor游标的LastActive time来判断能否老化的。如果该消费组的游标位置到达了消息老化区域,被老化掉了,消费组的游标位置就会强制更新到一个可用的位置,这个时候会更新游标的LastActive time到当前时间,周而复始,导致消费组无法老化。举个🌰

假设消费组的老化时间为4h,消息的老化时间为3h,就可能会发生这样的事情

总结

广播模式在微服务架构中起到了重要的角色,尤其是在需要在微服务实例之间同步数据的场景中,它具有显著的优势。它能够帮助维护内存数据的缓存一致性。希望本篇文章能提供您全面的广播模式的知识。

点击关注,第一时间了解华为云新鲜技术~

相关推荐
码农派大星。15 分钟前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu1 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s1 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王1 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
九卷技术录2 小时前
(微服务)服务治理:几种开源限流算法库/应用软件介绍和使用
微服务·服务治理·限流算法
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
2402_857589362 小时前
SpringBoot框架:作业管理技术新解
java·spring boot·后端