加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

微服务架构下静态数据通用缓存机制

发布时间:2018-10-31 18:26:32 所属栏目:编程 来源:佚名
导读:在分布式系统中,特别是最近很火的微服务架构下,有没有或者能不能总结出一个业务静态数据的通用缓存处理机制或方案,这篇文章将结合一些实际的研发经验,尝试理清其中存在的关键问题以及探寻通用的解决之道。 什么是静态数据 这里静态数据是指不经常发生
副标题[/!--empirenews.page--]

在分布式系统中,特别是最近很火的微服务架构下,有没有或者能不能总结出一个业务静态数据的通用缓存处理机制或方案,这篇文章将结合一些实际的研发经验,尝试理清其中存在的关键问题以及探寻通用的解决之道。

什么是静态数据

这里静态数据是指不经常发生变化或者变化频率比较低的数据,比如车型库、用户基本信息、车辆基本信息等,车型库这种可能每个月会更新一次,用户和车辆基本信息的变化来源于用户注册、修改,这个操作的频率相对也是比较低的。

另外这类数据的另一个特点是要求准确率和实时性都比较高,不能出现丢失、错误,以及过长时间的陈旧读。

具体是不是应该归类为静态数据要看具体的业务,以及对变化频率高低的划分标准。在这里的业务定义中,上边这几类数据都归为静态数据。

为什么需要缓存

在面向用户或车联网的业务场景中,车型信息、用户基本信息和车辆基本信息有着广泛而高频的业务需求,很多数据都需要对其进行关联处理。在这里缓存的目的就是为了提高数据查询效率。静态数据通常都保存在关系型数据库中,这类数据库的IO效率普遍不高,应对高并发的查询往往捉襟见肘。使用缓存可以极大的提升读操作的吞吐量,特别是KV类的缓存,没有复杂的关系操作,时间复杂度一般都在O(1)。注意这里说的缓存指内存缓存。

当然除了使用缓存,还可以通过其它手段来提高IO吞吐量,比如读写分离,分库分表,但是这类面向关系型数据库的方案更倾向于同时提高读写效率,对于单纯提升读吞吐量的需求,这类方案不够彻底,不能在有限的资源情况下发挥更好的作用。

通用缓存机制

下面将直接给出一个我认为的通用处理机制,然后会对其进行分析。

微服务架构下静态数据通用缓存机制

微服务架构下静态数据通用缓存机制

对于某个具体的业务,其涉及到六个核心程序:

  • 业务服务:提供对某种业务数据的操作接口,比如车辆服务,提供对车辆基本信息的增删改查服务。
  • 关系数据库:使用若干表持久化业务数据,比如SQLServer、MySQL、Oracle等。
  • 持久化队列:可独立部署的队列程序,支持数据持久化,比如RabbitMQ、RocketMQ、Kafka等。
  • 缓存处理程序:从队列接收数据,然后写入缓存。
  • 数据一致处理程序:负责检查缓存数据库和关系型数据库中数据是否一致,如果不一致则使用关系数据库进行更新。
  • 缓存数据库(Redis):支持持久化的缓存数据库,这里直接选了Redis,这个基本是业界标准了。
  • Java架构交流学习圈:874811168 面向1-3年经验 Java开发人员 帮助突破瓶颈 提升思维能力

以及两个外部定义:

  • 数据生产者:业务静态数据的来源,可以理解为前端APP、Web系统的某个功能或者模块。
  • 数据消费者:需要使用这些业务静态数据的服务或者系统,比如报警系统需要获取车辆对应的用户信息以便发送报警。

下面以问答的形式来说明为什么是这样一种机制。

为什么需要业务服务?

既然是微服务架构,当然离不开服务了,因为这里探讨的是业务静态数据,所以是业务服务。不过为了更好的理解,这里还是简单说下服务出现的原因。

当今业务往往需要在多个终端进行使用,比如PC、手机、平板等,既有网页的形式,又有APP的形式,另外某个数据可能在多种不同的业务被需要,如果将数据操作分布在多个程序中很可能产生数据不一致的情况,另外代码不可避免的冗余,读写性能更很难控制,变更也基本上是不敢变的。通过一个业务服务可以将对业务数据的操作有序的管理起来,并通过接口的形式对外提供操作能力,代码不用冗余了,性能也好优化了,数据不一致也得到了一定的控制,编写上层应用的人也舒服了。

为什么不是进程内缓存?

很多开发语言都提供了进程内缓存的支持,即使没有提供直接操作缓存的包或库,也可以通过静态变量的方式来实现。对数据的查询请求直接在进程内存完成,效率可以说是杠杠滴了。但是进程内缓存存在两个问题:

缓存数据的大小:进程可以缓存数据的大小受限于系统可用内存,同时如果机器上部署了多个服务,某个服务使用了太多的内存,则可能会影响其它服务的正常访问,因此不适合大量数据的缓存。

缓存雪崩:缓存同时大量过期或者进程重启的情况下,可能产生大量的缓存穿透,过多的请求打到关系数据库上,可能导致关系数据库的崩溃,引发更大的不可用问题。

为什么是Redis?

Redis这类数据库可以解决进程内缓存的两个问题:

  • 独立部署,不影响其它业务,还可以做集群,内存扩容比较方便。
  • 支持数据持久化,即使Redis重启了,缓存的数据自身就可以很快恢复。

另外Redis提供了很好的读写性能,以及方便的水平扩容能力,还支持多种常用数据结构,使用起来比较方便,可以说是通用缓存首选。

为什么需要队列?

队列在这里的目的是为了解耦,坦白的说这个方案中可以没有队列,业务服务在关系数据库操作完成后,直接更新到缓存也是可以的。 之所以加上这个队列是由于当前的业务开发有很明显的系统拆分的需求,特别是在微服务架构下,为了降低服务之间的耦合,使用队列是个常用选择,在某些开发模型中也是很推崇的,比如Actor模型。

举个例子,比如新注册一个用户,需要赠送其300积分,同时还要给其发个注册成功的邮件,如果将注册用户、赠送积分、发成功邮件都写到一起执行,会产生两个问题:一是注册操作耗时增加,二是其中某个处理引发整体不可用的几率增大,三是程序的扩展性不好;通多引入队列,将注册信息分别发到积分队列和通知队列,然后由积分模块和通知模块分别处理,用户、积分、通知三个模块的耦合降低了,相互影响变小了,以后再增加注册后的其它处理也就是增加个队列的事,整体的扩展性得到了增强。

队列作为一种常用的解耦方案,在缓存这里虽然产生的影响不大,但是除了缓存难免同时还会有其它业务处理,所以为了统一处理机制,这里保留了下来。(既然用了,就把它发扬光大。)

为什么队列需要持久化?

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读