文档章节

Redis实现参数的集中式管理

ksfzhaohui
 ksfzhaohui
发布于 2017/08/30 11:54
字数 1469
阅读 3718
收藏 145
点赞 2
评论 0

系列文章

  1. Zookeeper实现参数的集中式管理
  2. JMS实现参数的集中式管理
  3. Redis实现参数的集中式管理

前言
上一篇文件JMS实现参数的集中式管理中使用JMS作为中间层,利用的JMS的发布订阅功能实现了对参数的集中式管理;同样分布式缓存Redis也提供了类似的发布订阅功能,并且Redis本身提供了缓存和持久化的功能,本文将介绍通过Redis实现简单的参数集中式管理。

Maven引入
Spring相关的jar引入参考上一篇文章

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.4.0</version>
</dependency>

目标
1.可以同时配置监听多个节点如/app1,/app2;
2.希望只需要配置如/app1,就能够监听其子节点如/app1/modual1以及子节点的子节点如/app1/modual1/xxx/…;
3.服务器启动能获取当前指定父节点下的所有子节点数据;
4.在添加节点或者在更新节点数据的时候能够动态通知,这样代码中就能够实时获取最新的数据;
5.spring配置中可以从Zookeeper中读取参数进行初始化。

虽然在实现的方式上有点区别,但是最终达成的目标是一致的,同样列出了这5条目标

实现
RedisWatcher主要用来和Redis进行连接,然后对监听的节点进行初始化,模糊订阅需要监听的节点,最后接受数据的变更,更新本地数据,存储数据等。

1.同时配置监听多个节点
提供一个字符串数组给用户用来添加需要监听的节点:

private String[] keyPatterns;

2.能够监听其子节点以及子节点的子节点
使用Redis提供的psubscribe命令,订阅一个或多个符合给定模式的频道,提供了模糊订阅的功能

private void watcherPaths() {
    new Thread(new Runnable() {
 
        @Override
        public void run() {
            jedis.psubscribe(new JedisPubSub() {
 
                @Override
                public void onMessage(String channel, String message) {
                    try {
                        keyValueMap.put(channel, message);
                        LOGGER.info("key = " + channel + ",value = " + message);
                    } catch (Exception e) {
                        LOGGER.error("onMessage error", e);
                    }
                }
 
                @Override
                public void onPMessage(String arg0, String arg1, String arg2) {
                    System.out.println("onPMessage=>" + arg0 + "=" + arg1 + "="
                            + arg2);
                }
 
                @Override
                public void onPSubscribe(String pattern, int subscribedChannels) {
                    LOGGER.info("onPSubscribe=>" + pattern + "=" + subscribedChannels);
                }
 
                @Override
                public void onPUnsubscribe(String arg0, int arg1) {
                }
 
                @Override
                public void onSubscribe(String arg0, int arg1) {
                }
 
                @Override
                public void onUnsubscribe(String arg0, int arg1) {
                }
            }, getSubKeyPatterns());
        }
    }).start();
}

提供了使用匹配符*的模糊匹配功能,组装带*号的匹配字符串

/**
     * 获取订阅的模糊channel
     * 
     * @return
     */
    private String[] getSubKeyPatterns() {
        String[] subKeyPatterns = new String[keyPatterns.length];
        for (int i = 0; i < keyPatterns.length; i++) {
            subKeyPatterns[i] = keyPatterns[i] + "*";
        }
        return subKeyPatterns;
    }

3.服务器启动初始化节点数据
通过使用keys命令来获取匹配节点的数据(keys命令可能引发性能问题,根据实际情况使用)

private void initKeyValues() {
    for (String keyPattern : keyPatterns) {
        Set<String> keys = jedis.keys(keyPattern + "*");
        for (String key : keys) {
            String value = jedis.get(key);
            keyValueMap.put(key, value);
            LOGGER.info("init key = " + key + ",value = " + value);
        }
    }
}

4.监听节点数据的变更
目标2中通过psubscribe命令,使用模糊订阅来监听数据的变更,onMessage用来接受变更的数据

5.spring配置中可以从Redis中读取参数进行初始化

public class RedisPropPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
 
    private RedisWatcher rediswatcher;
 
    @Override
    protected Properties mergeProperties() throws IOException {
        return loadPropFromRedis(super.mergeProperties());
    }
 
    /**
     * 从Redis中加载配置的常量
     * 
     * @param result
     * @return
     */
    private Properties loadPropFromRedis(Properties result) {
        rediswatcher.watcherKeys();
        rediswatcher.fillProperties(result);
        return result;
    }
}

通过以上的处理,可以使用如下简单的配置来达到目标:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    <bean id="rediswatcher" class="zh.maven.DynamicConf.redis.RedisWatcher">
        <property name="keyPatterns" value="/a2,/a3" />
    </bean>
    <bean id="propertyConfigurer" class="zh.maven.DynamicConf.redis.RedisPropPlaceholderConfigurer">
        <property name="rediswatcher" ref="rediswatcher"></property>
    </bean>
    <bean id="person" class="zh.maven.DynamicConf.Person">
        <property name="name">
            <value>${/a2/m1}</value>
        </property>
        <property name="address">
            <value>${/a3/m1/v2}</value>
        </property>
        <property name="company">
            <value>${/a3/m1/v2/t2}</value>
        </property>
    </bean>
</beans>

测试
1.启动Redis服务器

redis-server.exe

2.启动Redis客户端进行初始化数据

redis-cli.exe
redis 127.0.0.1:6379> set /a2/m1 zhaohui
OK
redis 127.0.0.1:6379> set /a3/m1/v2 nanjing
OK
redis 127.0.0.1:6379> set /a3/m1/v2/t2 codingo
OK

3.启动Main类

public class Main {
  
    public static void main(String[] args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "spring-config.xml" });
        Person person = (Person) context.getBean("person");
        System.out.println(person.toString());
        }
}

4.启动RedisPublish
定时发布数据,同时查看集群节点的Main类日志输出

public class RedisPublish {
 
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        int i = 0;
        while (true) {
            jedis.publish("/a2/b4/c1" + i, "message_" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
    }
}

日志输出如下:

2017-08-30 10:44:00 - init key = /a2/m1,value = zhaohui
2017-08-30 10:44:00 - init key = /a3/m1/v2,value = nanjing
2017-08-30 10:44:00 - init key = /a3/m1/v2/t2,value = codingo
2017-08-30 10:44:00 - onPSubscribe=>/a2*=1
2017-08-30 10:44:00 - onPSubscribe=>/a3*=2
2017-08-30 10:44:00 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4bad4a49: defining beans [rediswatcher,propertyConfigurer,person]; root of factory hierarchy
name = zhaohui,address = nanjing,company = codingo
onPMessage=>/a2*=/a2/b4/c10=message_1504061045414
onPMessage=>/a2*=/a2/b4/c11=message_1504061047458
onPMessage=>/a2*=/a2/b4/c12=message_1504061049458
onPMessage=>/a2*=/a2/b4/c13=message_1504061051458

详细代码svn地址:http://code.taobao.org/svn/temp-pj/DynamicConf

总结
关于参数的集中式管理一共写了三篇文章,分别利用Zookeeper,MQ以及Redis来实现了一个简单的参数的集中式管理,但更多的只是提供了一个思路
离生产还有很大距离,本片文章也是这个系列的最后一篇,综合来看Zookeeper更加适合做参数的集中式管理平台,MQ方式本身没有提供存储的功能
只能作为一个中间层存在;而Redis方式虽然提供了持久化功能,但是会因为选择不同的持久化方式会出现丢数据的可能,还有就是本身的集群方式
并不是很完善;虽然Zookeeper本身并不是一个存储系统,但是紧紧用来存储少量的参数应该足够了。

个人博客:codingo.xyz

© 著作权归作者所有

共有 人打赏支持
ksfzhaohui

ksfzhaohui

粉丝 296
博文 126
码字总数 153828
作品 3
南京
高级程序员
美团在Redis上踩过的一些坑-2.bgrewriteaof问题

转载请注明出处哈:http://carlosfu.iteye.com/blog/2254154 一、背景 1. AOF: Redis的AOF机制有点类似于Mysql binlog,是Redis的提供的一种持久化方式(另一种是RDB),它会将所有的写命令按...

付磊-起扬 ⋅ 2015/11/05 ⋅ 0

集中式session

集中式的Seesion管理 1.会话 2.技术实现 3.Servlet方案 4.自定义实现

wangjack ⋅ 2014/06/11 ⋅ 0

利用元数据管理数据质量

什么是元数据 任何文件系统中的数据分为数据和元数据。数据是指普通文件中的实际数据,而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息(in...

mcy0425 ⋅ 03/06 ⋅ 0

分布式session实现方式

当一个传统的Web项目需要从单点扩张成为集群式时候,需要考虑的一个问题:分布式Session的实现。通常分布式session有三种解决方式,现对三种方式进行简单记录: 1.session广播 顾名思义,广播...

塞上名猪 ⋅ 2017/05/10 ⋅ 0

分布式Session集中存储方案

在文章分布式web架构中Session管理的方法中讲了分布式Session管理的4种办法,其中第4种的Session集中存储实际运用比较广泛,下面来讲解这种的实现方案。 目前常用的Session集中管理方案有两种...

刘诗书 ⋅ 2017/11/23 ⋅ 0

xsequence 分布式序列号生成组件 1.3 发布

项目介绍 微服务时代,我们需要生产一个连续的友好的序列号,例如订单号等。变得比较麻烦。 这里我提供了两种业界常用的解决方案来实现这个分布式序列号生成组件。 使用集中式存储功能取步长...

徐安是个好人 ⋅ 05/31 ⋅ 0

teacher kwan/JeeRTD

JeeRTD简介 JeeRTD基于SpringBoot+SrpingCloud+Spring+SpringMVC+Mybatis+Redis+阿里巴巴dubbo+Javax.ws微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中...

teacher kwan ⋅ 2017/06/15 ⋅ 0

集群环境websocket如何处理通知到每个server问题

测试在两个server下部署J2ee应用;页面评论通知使用websocket处理,需要集中管理每个websocket连接,以保证能通知到每个打开的评论页面;javax.websocket.server.ServerEndpoint 方式tomcat实...

YangEphraim ⋅ 2016/08/19 ⋅ 5

中小型研发团队架构实践:集中式日志ELK

一、集中式日志 日志可分为系统日志、应用日志以及业务日志,系统日志给运维人员使用,应用日志给研发人员使用,业务日志给业务操作人员使用。我们这里主要讲解应用日志,通过应用日志来了解...

张辉清 ⋅ 2017/12/04 ⋅ 0

AOS V2.0 发布,JavaEE 应用基础平台

此版本是一个全新的换代升级版本。在AOS1.X的基础上扬长避短,以更轻、更快、更安全、同时拥抱企业应用和互联网后端应用为目标进行了大刀阔斧的重构和完善。 版本变更日志 1. 完善了AOS标签库...

神盾局-局座 ⋅ 2016/10/24 ⋅ 11

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 41分钟前 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部