浅谈0/1切换

 

前言:
  做过GUI开发的同学, 都知晓双缓存机制. 其过程为先把所有的场景和实体对象画到一个备份canvas, 然后再把备份canvas的内容整个填充真正的画板canvas中. 如果不采用双缓存机制, 你的画面有可能会出现闪烁和抖动.
  究其原因是整个绘制过程, 包含清屏, 绘制场景和各个实体. 其耗时远远大于单个canvas的复制. 进而导致CPU写canvas的速率小于LCD读取canvas的速率. 这样就出现闪烁的现象了.
  在后台服务中, 也会遇到类似的情形: 当数据/资源需要更新时, 采用直接增量更新的方式代价大(耗时长, 阻塞服务可用/实时响应), 由此引入back buffer,做0/1切换.
  本文以"配置文件热载更新"为例, 着重介绍0/1切换的思路和优化技巧.

热载更新:
  以往更新配置时, 往往需要重启服务进程. 为了提高服务的可用性, 更方便运维.
  采取的改进方式是:
  1) 引入配置中心服务(ConfigServer)
  把模块的配置文件搁置在ConfigServer中, 具体模块从ConfigServer中获取(拉起/通知).
  2) 监控本地配置文件变更
  进程模块通过定期轮询/事件触发的方式, 感知配置文件是否发生变化, 若发生变化, 则重新载入.
  但无论采用何种方式, 势必存在切换过程.

切换特点:
  把切换的双方定义为前端和后端, 前端资源往往被N个线程访问(静态只读), 后端资源往往是一个线程更新写. 于是就形成了一个N读1写的格局.
  具体在c/c++实现时, 切换过程往往就是一个指针的重新赋值, 十分简单.
  但问题也就隐藏在这了, 在切换后的旧资源销毁过程中, 存在多线程的竞态冲突风险.
  
  有人可能会提议, 如果对资源的访问资源的切换相同的锁保护, 就没有这个问题. 但在低频率切换的场景下, 加锁带来的性能损失, 有些得不偿失.

无锁0/1切换:
  是否存在无锁的切换方式呢?
  1). 延迟销毁
  工作线程持有并访问旧资源句柄时间不长, 可以设定一个时间窗口, 该时间窗口内属于保护期, 禁止对旧资源进行销毁.
  
  注: 在绝大多数场景下, 该方案满足条件. 只是理论上, 不排除低概率事件.
  2). 带引用计数的智能指针切换
  我们借助boost的shared_ptr来构建切换的小例子

#include <boost/shared_ptr.hpp>

#include <stdint.h>
#include <stdio.h>

class Config {
};

class DataCenter {
public:
    DataCenter() {
    }
    void init() {
        active_idx = 0;
        switchover[active_idx].reset(new Config());
    }
    // *) 切换函数, 由更新线程调用
    void swith() {
        uint32_t unactive_idx = (active_idx == 0) ? 1 : 0;
        uint32_t old_active_idx = active_idx;
    
        // *) 新资源ready    
        switchover[unactive_idx].reset(new Config());
        // *) 正式切换
        active_idx = unactive_idx;
        
        // *) 旧资源reset, 引入计数减一
        switchover[old_active_idx].reset();
    }

    // *) 访问资源, 由前端线程调用
    boost::shared_ptr<Config> getConfig() {
        return switchover[active_idx];
    }

private:
    volatile uint32_t active_idx;
    // *) 切换数组
    boost::shared_ptr<Config> switchover[2];
};

  巧用boost::shared_ptr内部有个原子计数器代理指针, 借助RAII的思想完美的实现了无引用时的自动清理工作. 也避免了上述的竞态冲突.

总结:
  在服务模块中的0/1切换有很多, 这边简述了下解决方案, 没有细致展开, 权当个人的学习笔记.

写在最后:
  
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

   

 

posted on 2015-04-30 12:46  mumuxinfei  阅读(864)  评论(2编辑  收藏  举报

导航