dynamic config tech base on redis(基于redis的动态配置方案)
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
api
cache
client
console
core
pom.xml
readme.md

readme.md

Doraemon

doraemon是什么?一个基于学习和练手为目的实现的动态配置方案,基于redis实现

I. 前置说明

1. 背景

在实际的项目中,经常会遇到一些需要动态修改状态的情况,比如报警,报给谁? 如果直接在代码中写死了,结果这个人离职了,或者新来了个同学,是不是得修改代码重新部署呢?很明显这种效率是非常低的

再比如,项目的改版,经常会出现的灰度情况,比如电商里面的详情页改版,根据设备id来进行灰度,以某些数字结尾的将访问到新的详情页;而其他的依然访问旧版的详情页,这个时候直接在代码中写死肯定是不会被接受的(可以想一想why ?)

还有一种case,某些情况下,我需要同步一个信息给某个应用,比如说一个后台管理系统,在启动时将能够登录这个系统的用户都事先从DB中捞出来,放在内存中了,现在db中去掉了一个有权限的用户,需要更新这个应用的内存,而这个应用部署在多个机器上,这种时候应该怎么办?我要如何同步这个应用的所有机器这个更新缓存的消息呢?

2. 什么是配置中心

前面提出了三种使用背景,那么和我们的这个配置中心又有什么关心呢?而且我们的这个配置中心到底是个什么鬼?

这个配置中心,我自己取的一个名,可能不太贴切,主要是为了解决上面三种应用背景而设计的

简单来将,配置中心就是:

应用可以从远程获取配置,而且这些配置支持修改,且修改完毕之后,获取这些配置的应用都可以获取到最新的配置

3. 目标

从使用背景出发,拆解需求场景,我们的配置中心的目标就比较明确了

业务目标

  1. 配置与应用隔离,配置的变动不需要应用重启就可以获取
  2. 配置的修改,支持也理应独立于获取配置的应用
    • 最好就是有个独立的控制台,用来修改配置
  3. 配置支持按应用纬度进行拆分(应用的隔离,使其更有普适性)
  4. 配置发生变动,对所有获取这个配置的应用而言,都可以立马感受到

性能目标

  1. 稳定性,不会因为qps过高就扛不住的情况
  2. 实时性,配置发生变更,不会出现部分机器依然读取旧配置的情况

安全目标

  1. 准确性,不会出现获取的不是自己希望的配置(即不会窜掉的问题)
  2. 确保每个应用只能修改自己的配置
  3. 操作日志,配置从创建到使用的修改,到最后的删除都应有完整的日志记录

4. 相关拓展

配置中心这个东西,并不是我凭空想出来的,淘宝的 Diamond 可以说是一个比较有名的项目了, 携程的Apollo,git上的表现也很nice,有兴趣的可以看下后面的超链

我们的设计目标和这些经典的配置中心没什么区别,那么为什么要重新造轮子呢?

  1. 以学习为目的,看下如果让我们来做,可以怎么做
  2. 锻炼写作分享的能力,写出一个配置中心是一个挑战,写博文分享这个配置中心又是一个挑战
  3. 可以在里面加一些有意思的特性,可以按照自己的想法去"蹂躏"它

II. 设计方案

方案设计

最少设计两层,一个client,一个core,两者职责分离

  • core : 实现与redis的交互,并对外封装统一的配置查询,更新接口;内部维护配置变更队列,提供一个查询变更配置的接口
  • client : 对使用者暴露查询和设置配置的接口;内部实现配置的mem缓存,注册配置变更监听器,实现配置变动触发器逻辑;下于core交互,实现配置的基本操作

III. 疑问和说明

a. 直接从redis获取配置不行么?

问: 远程配置,放在redis中,每次都直接从redis获取配置就好了,上面所有的东西都不需要,整个简洁明了,没那么多事了

答: 完全可以这么玩,而且没毛病

刚进公司,那时候还是php的环境,还没有配置中心的时候,获取动态配置就是这么做的,那么这里搞个这东西岂不是很鸡肋,且增加了成本。

这么做有以下几个好处:

  • 将配置加载到内存中,避免频繁的redis访问 (效率提升)
  • 底层数据存储完全可以替换成其他的,如db,memcache等,也就是说底层的扩展不影响上层的封装使用
  • 动手造轮子,可以更好的学习设计一个完整的配置中心,可能会遇到哪些问题,又可以怎么去解决,毕竟这是一个以学习为目的的项目

b. 安全问题

问: 存在redis的配置,覆盖写的问题怎么说? 配置变更维护的队列,如何确保能正常的通知所有的适用方

答: 为了确保配置不会被其他人无意的覆盖,因此隔离是有必要的;且有必要确保所有的修改都是通过调用接口来的,而不是直接修改redis中的内容

为了保证配置变更时,所有的使用者都能感知,需要以下几点:

  • 确保每次变更,都会塞入 changeQueue
  • 每个使用者都有一个对的 changeQueue
  • 获取一个变动之后,返回一个ACK状态(确认是正常处理了还是出现问题)

IV. 其他

声明

本项目需要目的是学习探究,暂时不适用于生产环境

扫描关注,java分享

QrCode