Soul源码学习 - 数据同步的一个问题记录

环境

今天讨论的版本是2.2.1 - release版本;
soul-admin 和 soul-bootstrap都集群部署

分析

问题

admin在做集群不是的时候,如果用户修改配置,当节点数据只到达其中一个而没有到达其他节点时,其他节点会有一个5分钟的延时。
admin节点和节点之间时互不感知的。

在HttpLongPollingDataChangedListenner 的afterInitialize方法中会通过一个5分钟的定时任务去拉取数据到admin缓存中。

@Override
    protected void afterInitialize() {
        long syncInterval = httpSyncProperties.getRefreshInterval().toMillis();
        // Periodically check the data for changes and update the cache
        scheduler.scheduleWithFixedDelay(() -> {
            log.info("http sync strategy refresh config start.");
            try {
                this.refreshLocalCache();
                log.info("http sync strategy refresh config success.");
            } catch (Exception e) {
                log.error("http sync strategy refresh config error!", e);
            }
        }, syncInterval, syncInterval, TimeUnit.MILLISECONDS);
        log.info("http sync strategy refresh interval: {}ms", syncInterval);
    }

处理方式

admin,提供2个接口,一个是listener,一个是fetch
1、listener接口,用于hold来自web的http请求,如果没有配置变更,会阻塞http请求,直到超时;如果有配置变更,会响应请求,告诉web是哪个group的配置发生了变更;
2、fetch接口,用于拉取group配置组的数据;

如果有多个Admin, 例如a, b, c三个节点,更新的操作只到达了一个节点;web会监听所有的admin节点,一旦节点有变化,就会收到最新的配置数据,但是某些节点数据,并不是最新的,这样倒置bootstrap拉不到最新的数据,所以bootstrap请求的时候会带上last_update_time 来监听listener,这个时候admin会对比时间戳,如果时间落后了,则更新本地配置数据;

private boolean checkCacheDelayAndUpdate(final ConfigDataCache serverCache, final String clientMd5, final long clientModifyTime) {

     ...
        long lastModifyTime = serverCache.getLastModifyTime();
        if (lastModifyTime >= clientModifyTime) {
            // 客户端配置过时了
            return true;
        }

        // the lastModifyTime before client, then the local cache needs to be updated.
        // Considering the concurrency problem, admin must lock,
        // otherwise it may cause the request from soul-web to update the cache concurrently, causing excessive db pressure
        ...
        if (locked) {
            try {
                ConfigDataCache latest = CACHE.get(serverCache.getGroup());
                if (latest != serverCache) {
                    // the cache of admin was updated. if the md5 value is the same, there's no need to update.
                    return !StringUtils.equals(clientMd5, latest.getMd5());
                }
                // 从数据库加载配置到缓存中
                this.refreshLocalCache();
                latest = CACHE.get(serverCache.getGroup());
                return !StringUtils.equals(clientMd5, latest.getMd5());
            } finally {
                LOCK.unlock();
            }
        }

        ...

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值