ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Apache Druid 缓存配置实战指南:Local / Memcached / Hybrid 三种缓存类型深度解析

Apache Druid 缓存配置实战指南:Local / Memcached / Hybrid 三种缓存类型深度解析 Apache Druid 缓存配置实战指南Local / Memcached / Hybrid 三种缓存类型深度解析【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址: https://gitcode.com/gh_mirrors/druid7/druid缓存是 Druid 查询链路中最重要的性能优化手段之一。在 Apache Druid 中缓存可以按需在Broker、Historical 和 Realtime三类进程上开启用于加速重复查询、降低底层 Segment 扫描压力。本文以仓库中的官方配置文档docs/content/configuration/caching.md为主体结合server/src/main/java/io/druid/client/cache/下的源码实现与examples/conf/中的真实示例配置完整讲解local、memcached、hybrid三种缓存类型的全部配置参数、底层工作原理、适用场景与常见实践帮助你为自己的集群选择并落地正确的缓存方案。一、缓存在哪里生效Broker、Historical 与 RealtimeDruid 的查询缓存是一个可选项需要在Broker、Historical以及 Realtime 处理节点上分别决定是否启用。官方文档给出了三份对应的配置说明broker 缓存配置Broker 负责接收查询请求、将其分发到各数据节点并合并结果是缓存收益最明显的进程historical 缓存配置Historical 节点直接提供历史数据查询开启缓存可大幅降低重复扫描realtime 缓存配置实时节点提供近实时数据同样可参与缓存。以 Broker 为例其缓存开关在examples/conf/druid/broker/runtime.properties中有真实示例# Query cache druid.broker.cache.useCachetrue druid.broker.cache.populateCachetrue druid.cache.typelocal druid.cache.sizeInBytes2000000000druid.broker.cache.useCache与druid.broker.cache.populateCache分别控制“查询时是否读取缓存”和“查询结果是否写入缓存”二者独立配置默认均为false见 CacheConfig.java 源码中private boolean useCache false;与private boolean populateCache false;。因此“开启缓存”至少需要同时把这两个开关置为true否则只会单向生效。哪些查询类型默认不参与缓存CacheConfig中还内置了一个默认不可缓存的查询类型列表private ListString unCacheable Arrays.asList(Query.GROUP_BY, Query.SELECT);也就是说默认情况下 GroupBy 与 Select 查询不会被缓存Timeseries、TopN 等查询类型则正常参与缓存。该列表可通过druid.cache.unCacheable配置覆盖。CacheConfig的isQueryCacheable(String queryType)方法正是通过判断查询类型是否落在该列表中来决定缓存的可用性。二、缓存类型总览druid.cache.typeDruid 默认使用本地 JVM 内存缓存local除非你显式指定了其他类型。全局缓存类型由公共配置文件即examples/conf/druid/_common/common.runtime.properties中的druid.cache.type决定因此Broker 与 Historical 可以复用同一份缓存配置。PropertyPossible ValuesDescriptionDefaultdruid.cache.typelocal,memcached,hybrid查询使用的缓存类型。各类型的详细配置选项见下文local缓存类型通过CacheProvider接口工厂化注入LocalCacheProvider、MemcachedCacheProvider、HybridCacheProvider分别对应上述三种类型统一实现 CacheProvider.java 与 Cache.java 抽象出的get / put / getBulk / close / getStats等操作。三、Local Cache简单高效的进程内 LRU 缓存3.1 原理Local Cache 是一个简单的 JVM 堆内内存 LRU 缓存其实现为MapCache包装的ByteCountingLRUMap见 LocalCacheProvider.javaOverride public Cache get() { return new MapCache(new ByteCountingLRUMap(initialSize, logEvictionCount, sizeInBytes)); }ByteCountingLRUMap继承自LinkedHashMap并以accessOrder true构造即按访问顺序排序因此天然具备 LRU 淘汰语义它额外用AtomicLong numBytes按字节精确统计缓存占用并在超过sizeInBytes上限时按插入/访问顺序淘汰最久未使用的条目详见 ByteCountingLRUMap.java。由于缓存驻留在 JVM 堆内存中启用 Local Cache 后务必同步调大进程的堆内存如jvm.config中的-Xmx否则缓存会与数据对象争抢堆空间。3.2 配置参数PropertyDescriptionDefaultdruid.cache.sizeInBytes缓存最大字节数。设为0表示禁用缓存0druid.cache.initialSize缓存底层哈希表hashtable的初始大小500000druid.cache.logEvictionCount非零时每淘汰logEvictionCount个条目记录一条日志0其中sizeInBytes与initialSize都带有Min(0)校验约束当logEvictionCount非零时ByteCountingLRUMap会在淘汰计数达到该值的整数倍时输出日志日志中同时打印当前大小与平均对象大小便于排查缓存抖动。3.3 实践示例官方 Quickstart 配置examples/conf/druid/broker/runtime.properties给出的正是 Local Cache 的典型用法druid.broker.cache.useCachetrue druid.broker.cache.populateCachetrue druid.cache.typelocal druid.cache.sizeInBytes2000000000 # 2GB 堆内缓存四、Memcached进程间共享的分布式缓存4.1 原理Memcached 模式使用memcached 作为缓存后端所有节点共享同一个缓存实例因此多 Broker / 多 Historical 之间可以共用缓存命中结果避免各自为政的重复计算。底层通过 spymemcached 客户端MemcachedCacheMemcacheClientPool与 memcached 服务通信LZ4Transcoder负责对象的 LZ4 压缩编解码。与 Local Cache 不同Memcached 缓存不占用 Druid 进程的堆内存这是它适合大规模共享缓存的关键原因。4.2 配置参数PropertyDescriptionDefaultdruid.cache.expirationMemcached 缓存条目的过期时间秒259200030 天druid.cache.timeout等待 memcached 响应的最大毫秒数500druid.cache.hosts逗号分隔的 memcached 主机列表host:port无必填druid.cache.maxObjectSize单个 memcached 对象的最大字节数5242880050 MBdruid.cache.memcachedPrefix所有 key 在 memcached 中的统一前缀druiddruid.cache.numConnections使用的 memcached 连接数1对照源码 MemcachedCacheConfig.java以下细节值得注意hosts为NotNull必填项格式为逗号分隔的host:port列表expiration默认 30 天超过 30 天的值会被 memcached 解释为绝对 POSIX 时间戳而非相对时长因此如需更长保留期需小心换算源码中还包含文档未列出的两个进阶参数druid.cache.readBufferSize客户端读缓冲字节数-1表示使用 spymemcached 默认值与druid.cache.maxOperationQueueSize客户端操作队列最大字节数0表示无界可按需微调。4.3 实践示例druid.cache.typememcached druid.cache.hostsmemcache-1:11211,memcache-2:11211 druid.cache.expiration86400 # 1 天 druid.cache.timeout500 druid.cache.memcachedPrefixdruid_prod druid.cache.numConnections4五、Hybrid CacheLocal Memcached 两级 L1/L2 缓存5.1 原理与读取流程Hybrid 模式组合任意两种缓存构成 L1 / L2 两级缓存最常见的是“本地内存L1 远端 memcachedL2”的组合兼顾本地命中的低延迟与远端共享的命中率。读取流程由 HybridCache.java 的get/getBulk实现先查L1缓存若L1 未命中miss再查L2缓存若L2 命中则同时回填写入 L1下次相同查询即可在本地直接命中只有两级都未命中时才算整体 miss。写入时则是两级同时putlevel1.put(key, value); level2.put(key, value);保证一致性。统计信息命中、未命中、条目数、字节数、淘汰数、超时数、错误数由两级分别统计后汇总。从 HybridCacheProvider.java 可以看到两级缓存通过依赖注入Named(l1)与Named(l2)绑定任一缺失都会直接抛出 l1/l2 cache not specified for hybrid cache 异常。5.2 配置参数PropertyDescriptionDefaultdruid.cache.l1.typeL1 缓存的类型取值同druid.cache.typelocal/memcached/hybridlocaldruid.cache.l2.typeL2 缓存的类型取值同druid.cache.typelocaldruid.cache.l1.*L1 缓存类型的任意合法属性均可用此前缀覆盖。例如 L1 为local时用druid.cache.l1.sizeInBytes设置其大小与对应缓存类型的默认值一致druid.cache.l2.*L2 缓存设置前缀语义同 L1与对应缓存类型的默认值一致即druid.cache.l1.*与druid.cache.l2.*是各自层级的属性命名空间其下的属性名与对应缓存类型在全局配置中的属性名一一对应。5.3 实践示例druid.cache.typehybrid # L1本地内存缓存容量 1GB druid.cache.l1.typelocal druid.cache.l1.sizeInBytes1000000000 druid.cache.l1.initialSize500000 # L2共享 memcached druid.cache.l2.typememcached druid.cache.l2.hostsmemcache-1:11211 druid.cache.l2.expiration2592000 druid.cache.l2.memcachedPrefixdruid六、缓存类型的选型建议结合上述原理与源码三种缓存类型的适用场景可以归纳如下场景推荐类型理由单机 / 小集群、查询重复度高、延迟敏感local零网络开销命中延迟最低注意同步增大 JVM 堆内存多节点共享缓存、堆内存紧张、节点间结果可复用memcached缓存不占 Druid 堆内存所有节点共享同一份结果兼顾本地低延迟与远端高命中率hybridL1 承担热点、L2 兜底并回填是生产环境最均衡的方案无论选择哪种类型都需要在公共配置文件中统一定义如examples/conf/druid/_common/common.runtime.properties从而让 Broker、Historical 等进程复用同一份缓存配置同时配合各进程的druid.process.cache.useCache与druid.process.cache.populateCache开关控制具体行为。缓存命中率、淘汰数与内存占用等指标可通过CacheStats与CacheMonitor上报到 Druid 的监控体系中进行观测与调优。【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址: https://gitcode.com/gh_mirrors/druid7/druid创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表