前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发编程框架Disruptor之高性能设计

并发编程框架Disruptor之高性能设计

原创
作者头像
JavaEdge
修改2020-10-09 15:56:11
8910
修改2020-10-09 15:56:11
举报
文章被收录于专栏:JavaEdgeJavaEdge

文章收录在我的 GitHub 仓库,欢迎Star/fork: Java-Interview-Tutorial https://github.com/Wasabi1234/Java-Interview-Tutorial

架构 UML

1 单线程写

Disruptor的RingBuffer, 之所以可以做到完全无锁,也是因为"单线程写",这是所有"前提的前提",离了这个前提条件,没有任何技术可以做到完全无锁。Redis、Netty等等高性能技术框架的设计都是这个核心思想。

2 系统内存优化-内存屏障

要正确的实现无锁,还需要另外一个关键技术:内存屏障。对应到Java语言,就是valotile变量与happens before语义。

参阅: 内存屏障 - Linux的smpwmb()/smp rmb() 系统内核:比如Linux的kfifo:smp wmb(),无论是底层的读写 都是使用了Linux的smp wmb

https://github.com/opennetworklinux/linux-3.8.13/blob/master/kernel/kfifo.c

3 系统缓存优化-消除伪共享

缓存系统中是以缓存行(cache line) 为单位存储的。缓存行是2的整数幂个连续字节,一般为32-256个字节。最常见的缓存行大小是64个字节。

当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享。

核心:Sequence

可看成是一个AtomicLong用于标识进度。还有另外一个目的就是防止不同Sequence之间CPU缓存伪共享(Flase Sharing)的问题。

  • 如下设计保证我们保存的 value 永远在一个缓存行中。(8 个long,正好 64 字节)。这也是一个空间换时间的案例。
    4 算法优化-序号栅栏机制我们在生产者进行投递Event的时候,总是会使用:
代码语言:txt
复制
long sequence = ringBuffer.next();

Disruptor3.0中,序号栅栏SequenceBarrier和序号Sequence搭配使用。协调和管理消费者与生产者的工作节奏,避免了锁和CAS的使用。

  • 消费者序号数值必须小于生产者序号数值
  • 消费者序号数值必须小于其前置(依赖关系)消费者的序号数值
  • 生产者序号数值不能大于消费者中最小的序号数值
  • 以避免生产者速度过快,将还未来得及消费的消息覆盖

SingleProducerSequencerPad#next

代码语言:txt
复制
    /**
     * @see Sequencer#next(int)
     */
    @Override
    public long next(int n) // 1
    {
        if (n < 1) // 初始值:sequence = -1
        {
            throw new IllegalArgumentException("n must be > 0");
        }
		// 语义级别的
		// nextValue为SingleProducerSequencer的变量
        long nextValue = this.nextValue;

        long nextSequence = nextValue + n;
        // 用于判断当前序号是否绕过整个 ringbuffer 容器
        long wrapPoint = nextSequence - bufferSize;
        // 用于缓存优化
        long cachedGatingSequence = this.cachedValue;

        if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue)
        {
            long minSequence;
            while (wrapPoint > (minSequence = Util.getMinimumSequence(gatingSequences, nextValue)))
            {
                LockSupport.parkNanos(1L); // TODO: Use waitStrategy to spin?
            }

            this.cachedValue = minSequence;
        }

        this.nextValue = nextSequence;

        return nextSequence;
    }

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 架构 UML
  • 1 单线程写
  • 2 系统内存优化-内存屏障
  • 3 系统缓存优化-消除伪共享
    • 核心:Sequence
      • SingleProducerSequencerPad#next
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com