Sentinel 核心组件剖析:LongAdder 在高并发计数中的应用

引言

在微服务架构和分布式系统中,对服务的请求量、响应时间等指标的实时监控至关重要。阿里巴巴开源的 Sentinel 是一个用于流量控制、熔断降级、系统负载保护的中间件。它通过一系列的度量指标来实现对系统状态的实时感知,而 LongAdder 正是 Sentinel 实现这些度量的核心数据结构之一。


一、LongAdder:线程安全的高性能计数器

LongAdder 是 Java 8 引入的一个新类,位于 java.util.concurrent.atomic 包中。它的设计目的是为了在高并发环境下提供高性能的加法操作,尤其适合用于计数场景。LongAdder 的实现借鉴了 Striped64 类,后者是 ConcurrentHashMap 的基础组件之一,通过减少锁的竞争来提高并发性能。

示例:使用 LongAdder 计数

import java.util.concurrent.atomic.LongAdder;public class LongAdderExample {
    private static final int THREAD_COUNT = 100;
    private static final int TASK_COUNT_PER_THREAD = 10000;

    public static void main(String[] args) throws InterruptedException {
        LongAdder longAdder = new LongAdder();

        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < TASK_COUNT_PER_THREAD; j++) {
                    longAdder.increment();
                }
            });
            threads[i].start();
        }

        for (Thread thread : threads) {
            thread.join();
        }

        System.out.println("Total count: " + longAdder.longValue());
    }}

二、Sentinel 中的 LongAdder 应用

在 Sentinel 中,LongAdder 被广泛应用于统计各种度量指标,例如资源的请求次数、响应时间等。这是因为 LongAdder 在高并发场景下能够提供优秀的性能和准确的数据统计,非常适合 Sentinel 这种需要实时监控系统状态的场景。

源码解析:Sentinel 中的度量指标存储

在 Sentinel 的源码中,DefaultMetricRecord 类是用于存储度量指标的主要载体,其中就使用了 LongAdder 来存储诸如 passCount(通过的请求次数)、blockCount(被限流的请求次数)等数据。

// Sentinel 源码片段示意public class DefaultMetricRecord implements MetricRecord {
    private final LongAdder passCount = new LongAdder();
    private final LongAdder blockCount = new LongAdder();
    private final LongAdder exceptionCount = new LongAdder();
    
    // ...其他属性和方法
    
    public long getPassCount() {
        return passCount.longValue();
    }
    
    public long getBlockCount() {
        return blockCount.longValue();
    }
    
    public long getExceptionCount() {
        return exceptionCount.longValue();
    }}

三、LongAdder 的内部实现

LongAdder 的内部实现基于 Striped64,其核心思想是通过分割(striping)技术来减少锁的竞争。它维护了一个数组,每个元素代表一个槽(cell),每个槽都可以独立地进行加法操作。当线程需要进行加法操作时,它会选择一个槽进行操作,如果该槽已经被占用,则会尝试其他的槽。这样,即使在高并发场景下,也能极大地减少锁的争用,从而提高整体的性能。

源码解析LongAdder 的 add 方法

// LongAdder 源码片段示意public final void add(long x) {
    Cell[] as; long b, s; int h;
    if ((as = cells) != null || !casBase(b = base, b + x)) {
        synchronized (this) {
            if (as == null || (h = ThreadLocalRandom.getProbe()) >= as.length)
                ThreadLocalRandom.rescaleProbe(h);
            else if (cells == as)
                lazySetCells(null);
            Cell a = as[(h & (as.length - 1))];
            if (a == null)
                as[h & (as.length - 1)] = a = new Cell();
            a.value += x;
            s = sum();
            if (base != b && s != b)
                base = s;
        }
    }}

结语

LongAdder 在 Sentinel 中扮演着重要的角色,它不仅提高了度量指标的统计效率,还保证了数据的一致性和准确性。通过本文的介绍,相信你已经对 LongAdder 及其在 Sentinel 中的应用有了更深的理解。掌握这一核心组件的运作机制,对于构建高性能的流量控制和系统保护策略至关重要。


更多搜索作者名称【源码解析】 知识星球,与你一起探索技术深处的秘密。

在知识星球,我们将继续深入探讨 Sentinel 的其他核心组件和技术细节,包括但不限于限流算法、熔断策略和系统保护机制。加入我们,让我们一起挖掘技术背后的奥秘,提升你的技能,成为真正的技术专家。


如果你对 Sentinel、高并发计数、流量控制等话题感兴趣,欢迎加入我的知识星球,那里有更多深度分析和实战案例等待着你。


来源: 互联网
本文观点不代表源码解析立场,不承担法律责任,文章及观点也不构成任何投资意见。

赞 ()

相关推荐

发表回复

评论列表

点击查看更多

    联系我们

    在线咨询: QQ交谈

    微信:13450247865

    邮件:451255340#qq.com

    工作时间:周一至周五,9:30-18:30,节假日休息

    微信