想象你准备出门远行三个月,面前只有一个半人高的行李箱。想带的东西远不止箱子的容量:厚外套、七八件T恤、两本书、一双登山靴……真正的收纳高手不会立刻去买更大的箱子,而是花二十分钟把T恤卷成小卷、把外套塞进真空袋、把袜子填进靴子。多花一点打包时间,就能装下多得多的东西。缓存压缩,就是服务器世界里的“收纳艺术”:内存这只“行李箱”空间有限,缓存数据就是你想带的“行李”,而 CPU 时间就是你的“打包时间”。系统在数据写入缓存时把它压缩变小,读取时再展开还原——用一点 CPU 开销,换取大幅提升的有效缓存容量。这门技术听上去简单,但“卷多紧”“用哪种卷法”“哪些行李值得卷”都藏着讲究。接下来的内容,就从行李箱的收纳哲学出发,带你一步步看懂压缩算法、压缩比、性能开销与工程落地。

岗位关联

缓存压缩是 AI 服务内存调优的核心杠杆,也是后端与推理性能工程师的进阶必修课。掌握它,你就能在云资源账单上为团队省下真金白银。

目录
  1. 可视化演示
  2. 1. 缓存压缩概述
  3. 2. 内存压力来源
  4. 3. 压缩算法选型
  5. 4. 压缩比评估
  6. 5. 性能开销分析
  7. 6. 压缩缓存设计
  8. 7. 工程实践策略
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

可视化展示缓存压缩的核心流程:数据序列化、压缩存储、解压读取,对比不同算法压缩比与内存节省效果。

本节配有交互动效(进入视口后自动加载,约 3KB)。

缓存压缩数据流程 原始数据经序列化后压缩存储到缓存 读取时自动解压还原,对应用透明 Saved = (1 - compressed/raw) \u00d7 100% 点击切换查看算法对比

1. 缓存压缩概述

出门前收拾行李时,你面对一个残酷的事实:不管怎么排布,箱子空间就是有限的。收纳高手由此悟出一个道理——与其换更大的箱子,不如把衣服卷起来。服务器世界同样如此:缓存为了追求速度必须住在内存里,而内存贵且有限。于是工程师想到,把缓存数据“卷起来”存放:写入时用 CPU 把它压缩变小,读取时再解压还原。

这个思路就叫缓存压缩。它的核心权衡非常直白:用 CPU 时间去换内存空间。每一次写入,CPU 要多花一点力气“打包”;每一次读取,CPU 要多花一点力气“拆包”。作为回报,同样的物理内存能装下更多的缓存条目,缓存命中率随之提升,最终换来更低的平均访问延迟和更少的数据库压力。

压缩收益的起点是一个简单指标——压缩比。它衡量数据被“压”得多小,比值越大,说明同样大小的空间能放下的原始数据越多。收益模型可以这样理解:缓存的有效容量等于物理内存乘以压缩比。

就像把毛衣塞进真空袋后体积缩成原来的三分之一,压缩比就是“塞之前”和“塞之后”的体积之比。记住这个指标,它是后面所有计算的地基。

r=原始数据大小压缩后数据大小\displaystyle r = \frac{\text{原始数据大小}}{\text{压缩后数据大小}}
压缩比 r 描述数据被“压实”的程度:r=2 表示原来需要 2 份空间的数据现在只占 1 份,r 越大省得越多,缓存有效容量就越大。
  1. 确定原始体积数据进入缓存前在内存中真实占用的字节数,它是压缩比计算的分子。
    SrawS_{\text{raw}}
  2. 确定压缩体积压缩算法处理之后实际存储的字节数,它是压缩比计算的分母。
    ScompS_{\text{comp}}
  3. 两者相除原始体积除以压缩体积得到压缩比,数值大于 1 表示数据确实变小了。
    SrawScomp=r\frac{S_{\text{raw}}}{S_{\text{comp}}} = r

2. 内存压力来源

为什么非要压缩?因为“行李箱”永远不够大。缓存服务的核心诉求是快,数据必须常驻内存;但热点数据不断涌入,被保留的条目越来越多,内存这只行李箱很快就被塞得满满当当。这时你有三个选择:加内存、删数据、压缩数据。

加内存是最直接的方案,但内存是服务器硬件中最贵的资源之一,云上的内存型实例价格惊人,而且扩容往往要迁移数据、重启服务,代价不小。删数据则意味着缓存命中率下降——大量请求会穿透到数据库,延迟从毫秒级飙升到几十毫秒。两条路都不痛快。

压缩缓存提供了第三条路:不换箱子,而是把箱子里的东西变小。假设物理内存是 M,平均压缩比是 r,那么缓存能容纳的原始数据量就从 M 变成了 M 乘 r。内存压力越大,压缩的收益就越明显。

箱子还是那个箱子,但经过收纳,能装的“回忆”翻倍了。理解了内存压力的来源,你就明白为什么压缩缓存是高并发场景下的“救命稻草”。

Ceff=M×rˉ\displaystyle C_{\text{eff}} = M \times \bar{r}
有效容量等于物理内存乘以平均压缩比。1GB 内存配合 r=2 的压缩,理论上就能装下 2GB 的原始数据,相当于免费“扩容”了一倍。
  1. 物理内存实际分配给缓存的内存大小,单位通常是字节,它是有效容量的基数。
    MM
  2. 平均压缩比整段缓存数据综合后的压缩比,不同条目压缩效果不同,需要取加权平均。
    rˉ\bar{r}
  3. 相乘得到有效容量物理内存乘平均压缩比,得到缓存理论上能容纳的原始数据总量。
    Ceff=M×rˉC_{\text{eff}} = M \times \bar{r}

3. 压缩算法选型

收纳手法各有千秋:T 恤直接卷起来,快但省不了太多空间;羽绒服塞进真空袋,多花点力气却能省下一大片地方;有些衣服只能简单叠放,还有些硬物怎么压都纹丝不动。旅行者要根据行李的材质和取用频率,选择不同的打包手法。压缩算法就是数据世界的“打包手法”。

主流算法各有性格。LZ4 像“随手卷 T 恤”,压缩解压极快,但压缩比普通,适合延迟敏感、CPU 紧张的场景。Zstd 像“可调力度的真空袋”,速度很快且压缩比明显更好,还支持 1 到 19 级的压缩档位,是工程上的平衡之选。Snappy 与 LZ4 类似,主打超低延迟。Gzip 则像“暴力压路机”,压缩比最高,但 CPU 开销大,适合写多读少、追求极致空间的场景。

选型时不能只看压缩比,要把速度和压缩收益放在一起权衡。一个实用的指标是“压缩性价比”:单位 CPU 时间换来的压缩收益越高,算法就越划算。

没有万能的手法,只有最合适的行囊组合。选算法的本质,就是在“打包速度”和“空间收益”之间找平衡点。

V=rtcomp+tdecomp\displaystyle V = \frac{r}{t_{\text{comp}} + t_{\text{decomp}}}
算法的性价比等于压缩比除以单次压缩加解压的总耗时。它回答了一个问题:每花一份 CPU 时间,能换回多少空间收益?
  1. 压缩收益算法在给定数据上获得的压缩比,代表空间收益。
    rr
  2. 总处理耗时压缩一次加解压一次的时间之和,代表读写全链路的 CPU 代价。
    tcomp+tdecompt_{\text{comp}} + t_{\text{decomp}}
  3. 计算性价比压缩比除以总耗时,数值越高,说明单位 CPU 时间换来的空间收益越大。
    V=rtcomp+tdecompV = \frac{r}{t_{\text{comp}} + t_{\text{decomp}}}

4. 压缩比评估

同样的手法,压不同的东西效果天差地别:羽绒服压完只剩五分之一,牛仔裤只能压到一半,砖头则纹丝不动。压缩比从来不是算法的绝对属性,而是“算法与数据”共同作用的结果。这是评估压缩效果时最容易忽略的一点。

同样是 Zstd,对一段包含大量重复字段的 JSON 文本,压缩比可能轻松超过 5;对一张已经压缩过的 PNG 图片,压缩比可能只有 1.01——因为图片内部已经没有多少冗余可挖。因此,评估压缩比必须用真实业务数据做基准,而不是拿通用测试语料想当然。

除了压缩比,还要看吞吐量:压缩和解压每秒能处理多少字节。吞吐量决定了 CPU 开销会被放大多少倍——如果解压吞吐只有 100MB/s,而缓存读取峰值是 1GB/s,CPU 就会成为瓶颈。

先摸清“行李材质”,再选“打包手法”。真实的业务数据就是你的行李清单,务必让评估结果来自你真正要装进箱子的那些东西。

吞吐量=Dt\displaystyle \text{吞吐量} = \frac{D}{t}
吞吐量表示每秒钟能压缩或解压的字节数。它和压缩比一样重要:一个压缩比很高但速度极慢的算法,在实际高并发场景里可能根本无法落地。
  1. 处理数据量一次压缩或解压操作处理的总字节数。
    DD
  2. 耗时完成这些处理所消耗的时间。
    tt
  3. 求吞吐量数据量除以耗时,得到每秒处理能力,用来横向对比不同算法的速度。
    Dt\frac{D}{t}

5. 性能开销分析

卷衣服省了空间,但代价是找衣服变慢了:每次想穿那件卷起来的 T 恤,都得先展开再穿上。如果这件衣服你一天穿三次,展开三次的麻烦就会远远超过省空间的收益。压缩缓存的性能开销,正是同样的逻辑。

写入缓存时压缩成本只付一次,但读取时解压成本几乎每次都躲不掉。对于读多写少的缓存场景,解压延迟会被请求频率反复放大。于是评估压缩缓存时,不能只看“压缩省了多少内存”,还要看“平均每次访问慢了多少”。这里的关键是命中率:命中率越高,解压成本被放大的次数越多;反之,未命中回源数据库的成本又太高。两者之间存在一个收益平衡点。

聪明的旅行者会把天天穿的衣服放在最外层,不卷不压;只有偶尔才用的才塞进真空袋。压缩缓存的性能优化,本质也是这个道理。

Tavg=h×(Tread+Tdecomp)+(1−h)×Tmiss\displaystyle T_{\text{avg}} = h \times (T_{\text{read}} + T_{\text{decomp}}) + (1 - h) \times T_{\text{miss}}
平均访问延迟等于命中率乘命中路径耗时,加上未命中率乘回源耗时。压缩让命中路径多了解压延迟,别小看它——高命中率下这个延迟会被放大到用户可感知的程度。
  1. 命中率请求在缓存中找到数据的概率,越接近 1 说明缓存越有效。
    hh
  2. 命中路径耗时命中时读取数据和解压还原的时间之和。
    Tread+TdecompT_{\text{read}} + T_{\text{decomp}}
  3. 未命中路径耗时未命中时回源数据库或上层存储的开销,通常远大于命中路径。
    (1−h)×Tmiss(1 - h) \times T_{\text{miss}}
  4. 加权平均把两条路径按概率加权求和,就是用户感知的平均访问延迟。
    Tavg=h×(Tread+Tdecomp)+(1−h)×TmissT_{\text{avg}} = h \times (T_{\text{read}} + T_{\text{decomp}}) + (1 - h) \times T_{\text{miss}}

6. 压缩缓存设计

一个真正好用的收纳系统,绝不是把东西一股脑塞进箱子,而是有分区、有收纳袋、有清晰的条理。压缩缓存的工程实现同样需要精心设计,否则省下的内存可能被管理成本悄悄吃掉。

首先要决定在哪个环节压缩。常见做法是写入时同步压缩,简单直接;如果写入峰值高,也可以先写原数据再异步压缩,但会增加复杂度。其次要决定压缩粒度:按块压缩比按整个对象压缩更灵活,允许只解压需要的块,减少无效解压。每个压缩块还需要一条元数据记录,保存压缩算法类型、原始大小、压缩后大小和偏移量,这些元数据本身也会占内存。

内存管理上,压缩块大小不一,容易产生碎片,工程上常用内存池复用缓冲区。逐出策略也要配合压缩后的真实容量记账——统计缓存已用空间时,必须以压缩后的字节数为准,否则容量会严重失真。

收纳系统设计得当,行李箱才能长期保持整洁高效。压缩缓存不是简单调一个压缩等级,而是一套包含元数据、内存池、逐出策略的完整工程方案。

Bsaved=D×(1−1r)\displaystyle B_{\text{saved}} = D \times \left(1 - \frac{1}{r}\right)
当缓存总共要容纳原始数据量 D、平均压缩比为 r 时,节省的内存等于 D 乘以(1 减 r 分之一)。这个公式帮你估算压缩到底省下了多少字节。
  1. 原始数据总量一段时间内所有写入缓存的原始字节数。
    DD
  2. 压缩后的占用比例压缩比越大,压缩后数据占原始数据的比例越小。
    1r\frac{1}{r}
  3. 节省的内存原始总量减去压缩后总量,得到实际节约的空间。
    D×(1−1r)D \times \left(1 - \frac{1}{r}\right)

7. 工程实践策略

老练的旅行者会分层规划行李箱:天天穿的放在最外层,随手就能拿;偶尔穿的叠在中间;压箱底的厚衣服塞进最深处。缓存压缩的工程实践,正是这套分层哲学的数字化版本。

实践中最有效的策略是热冷数据分层:高频访问的热数据保持不压缩或用 LZ4 这种极快算法,把延迟降到最低;低频访问的冷数据用 Zstd 高压缩档位,把空间省到极致。其次,小于某个阈值的数据块直接跳过压缩——小数据压缩收益微乎其微,反而白付 CPU 开销。更进一步,可以根据数据类型自适应选择算法,比如对 JSON 纯文本用高压缩比,对 protobuf 二进制用快速算法。

上线后还要持续监控:CPU 使用率、平均压缩比、缓存命中率、解压延迟等指标缺一不可。压缩引入的 CPU 开销占比是关键信号,一旦超过阈值,就要调低压缩档位或调整分层策略。容量规划时也要为压缩预留 CPU 余量,避免压缩本身拖垮服务。

收纳的最高境界是“该卷的卷,该放的放”。当你的缓存系统能做到这一点,CPU 和内存就在你的调配下达成了优雅的平衡。

P=Tcomp+TdecompTbase+Tcomp+Tdecomp\displaystyle P = \frac{T_{\text{comp}} + T_{\text{decomp}}}{T_{\text{base}} + T_{\text{comp}} + T_{\text{decomp}}}
压缩引入的 CPU 额外开销占比,等于压缩解压耗时之和除以新的总耗时。这个占比是判断压缩策略是否过度的“体温计”。
  1. 压缩解压耗时缓存读写链路中新增的 CPU 处理时间。
    Tcomp+TdecompT_{\text{comp}} + T_{\text{decomp}}
  2. 基线总耗时不压缩时的正常读写耗时,体现原始链路速度。
    TbaseT_{\text{base}}
  3. 开销占比新增耗时除以加上新增后的总耗时,占比过高时就要调低压缩档位。
    Tcomp+TdecompTbase+Tcomp+Tdecomp\frac{T_{\text{comp}} + T_{\text{decomp}}}{T_{\text{base}} + T_{\text{comp}} + T_{\text{decomp}}}

AI 应用场景

1. 在线推理服务的特征缓存瘦身

阶段:特征工程 / 在线推理

解决的问题:AI 推荐与广告服务每次请求都要读取大量用户特征和物品特征,这些特征以 KV 形式缓存在内存中。特征数据通常包含重复的 ID 序列和枚举字段,可压缩性极强。传统做法直接存原始结构体,导致内存暴涨、命中率下降;压缩后,同样的内存能缓存两到三倍的特征条目,同时保持命中率稳定。

具体案例:某推荐系统特征缓存约 50GB,大量特征为重复的用户画像 JSON。引入 Zstd 压缩后,有效容量提升 2.4 倍,命中率从 82% 升到 95%,数据库 QPS 下降 60%,整体推理 P99 延迟几乎不变。

2. 大模型推理的 KV Cache 压缩

阶段:模型推理

解决的问题:大语言模型生成时,注意力机制的 Key/Value 缓存占用了大量显存,限制了并发 batch 大小。KV Cache 数据分布存在大量冗余模式,压缩后可以显著降低显存占用,让单卡塞进更多并发请求。这相当于在“显存行李箱”里用更聪明的收纳方式多塞几个请求。

具体案例:某 LLM 服务在 4 张 A100 上部署,原始 KV Cache 峰值 60GB,制约 batch size 上限。对 KV Cache 做块级压缩后,显存占用下降约 40%,推理吞吐提升 55%,单 Token 延迟增加不到 8%。

3. 边缘设备上的本地模型缓存

阶段:模型部署 / 端侧推理

解决的问题:边缘设备内存极小,既要跑模型又要缓存高频输入数据的推理结果。设备 CPU 相对空闲而内存极度稀缺,恰好是“用 CPU 换内存”的理想场景。压缩缓存让端侧设备在不加内存条的情况下,多缓存数倍的输入样本。

具体案例:某智能摄像头端侧部署违规检测模型,推理结果缓存 256MB。引入缓存压缩后,有效缓存容量达到 600MB,重复请求的命中率提升近一倍,设备无需硬件升级。

Python 演示

python64 行
import zlib class CompressedCache:    """一个简单的压缩缓存实现, 用 zlib 压缩大对象"""    def __init__(self, max_bytes=1024 * 1024, level=6):        self.max_bytes = max_bytes        self.level = level        self._data = {}    # key -> 压缩/原始字节        self._meta = {}    # key -> (类型, 原始大小, 存储大小)        self._used = 0     def put(self, key, value, compress=True):        # 覆盖旧值时先回退已记账的存储体积        if key in self._data:            self._used -= self._meta[key][2]        raw = value.encode('utf-8') if isinstance(value, str) else value        raw_size = len(raw)        # 超过阈值才压缩, 小对象直接存原始字节        if compress and raw_size > 256:            blob = zlib.compress(raw, self.level)            self._meta[key] = ('zlib', raw_size, len(blob))        else:            blob = raw            self._meta[key] = ('raw', raw_size, raw_size)        self._data[key] = blob        self._used += self._meta[key][2]        # 超过容量上限时按插入顺序驱逐最老的数据        while self._used > self.max_bytes and self._data:            old = next(iter(self._data))            del self._data[old]            self._used -= self._meta[old][2]            del self._meta[old]     def get(self, key):        if key not in self._data:            return None        kind, _, _ = self._meta[key]        blob = self._data[key]        return zlib.decompress(blob) if kind == 'zlib' else blob     def stats(self):        raw_total = sum(m[1] for m in self._meta.values())        stored_total = sum(m[2] for m in self._meta.values())        return {            'items': len(self._data),            'raw_bytes': raw_total,            'stored_bytes': stored_total,            'ratio': raw_total / stored_total if stored_total else 0,        }  def simulate():    cache = CompressedCache(max_bytes=20000)    for i in range(200):        cache.put('key_%03d' % i, 'hello world! ' * 20)    st = cache.stats()    print('items:', st['items'])    print('raw_bytes:', st['raw_bytes'])    print('stored_bytes:', st['stored_bytes'])    print('ratio: %.2f' % st['ratio'])  if __name__ == '__main__':    simulate()
目的:用 Python 内置 zlib 实现一个带容量上限的压缩缓存,演示“写入压缩、读取解压、压缩后容量记账”的完整流程,帮助理解正文中的收益公式。
  1. if compress and raw_size > 256:只有超过 256 字节的对象才压缩,模拟工程中“小数据块跳过压缩”的策略。
  2. blob = zlib.compress(raw, self.level)写入时用 CPU 执行压缩,得到更小的存储字节串。
  3. self._used += self._meta[key][2]按压缩后的实际字节数记账,这正是“逐出策略配合”的关键。
  4. while self._used > self.max_bytes and self._data:超过容量上限时逐出最老条目,保证内存不超限。
  5. zlib.decompress(blob) if kind == 'zlib' else blob读取时先判断类型,压缩过的才解压还原。

常见误区

误区“选压缩算法当然选压缩比最高的,Gzip 比 LZ4 压缩比高那么多,为什么不用?省下的内存不是越多越好吗?”

正解压缩比只是收益的一半,CPU 开销是另一半成本。就像用暴力压路机打包,空间省下了,但每次取衣服都要花十分钟拆包。如果缓存读取频繁,解压延迟会被命中率反复放大,最终平均访问延迟反而变差。选型要看“性价比公式”:压缩比除以压缩解压总耗时,而不是只看压缩比一个数。

为何常见:初学阶段容易只关注“省了多少内存”这个直观收益,忽略了 CPU 开销同样会以延迟形式让用户付出代价。

误区“既然压缩能省内存,那就把缓存里所有数据都压缩一遍,收益最大化。”

正解热数据访问频率极高,每次访问都要解压,压缩带来的延迟放大远超省内存的收益。这就像把每天穿的 T 恤也卷进真空袋,省了一点空间,却让每天早上找衣服变得无比麻烦。工程实践的正确姿势是热冷分层:热数据不压或快压,冷数据才用高压缩比,小于阈值的小对象直接跳过压缩。

为何常见:人们容易把“压缩”看作一个无差别操作,忽略了访问频率这个关键维度。

误区“用了压缩缓存,内存肯定能省一半以上,我预估一下大概能缓存两倍的数据。”

正解压缩比高度依赖数据类型。含大量重复文本的 JSON 可能压缩比超过 5,但已经压缩过的图片、视频、加密数据几乎压不动,压缩比接近 1。这就像砖头塞不进真空袋,再好的收纳手法也压不出水来。上线前必须用真实业务数据实测平均压缩比,再根据公式计算有效容量,而不是拍脑袋假设翻倍。

为何常见:人们用通用语料的印象替代了对自己业务数据的测量,忽略了“算法与数据共同决定压缩比”这一事实。

误区“解压就是几微秒的事,比起网络传输和数据库查询,这点开销不算什么。”

正解解压开销会被命中率放大。命中率 95% 时,95% 的请求都要额外付一次解压时间;如果缓存 QPS 是 10 万,解压 20 微秒就意味着每秒多出 2000 微秒的 CPU 占用。用平均访问延迟公式算一算就会发现,命中率越高,解压成本越不可忽视。旅行中“每次取用都要拆包”的烦恼,会随着行李被翻找的次数线性增长。

为何常见:单次操作的开销看起来微不足道,初学者容易忽略它在高并发和高命中率下的放大效应。

面试题

Q1. 缓存压缩本质是一场资源交换,交换的双方是:

单选题 · easy

  • A.用内存空间换取磁盘资源
  • B.用 CPU 资源换取内存空间← 正确答案
  • C.用网络带宽换取 CPU 时间
  • D.用磁盘空间换取网络带宽

答案:B。压缩缓存的核心是用额外的 CPU 时间去压缩数据,从而在有限物理内存中容纳更多缓存条目,本质是“用 CPU 换内存”。就像用打包时间换行李箱空间,其他选项描述的都是不同资源之间的交换,不符合压缩缓存的定义。

Q2. 压缩比 r 的正确计算方式是:

单选题 · easy

  • A.压缩后大小除以原始大小
  • B.原始大小减去压缩后大小
  • C.原始大小除以压缩后大小← 正确答案
  • D.压缩后大小加上原始大小

答案:C。压缩比等于原始数据大小除以压缩后数据大小,衡量数据被“压实”的程度。r=2 表示原来两份空间的数据现在只占一份。A 得到的是小于 1 的分数,B 得到的是差值而非比值,D 更是无意义的加和。

Q3. 以下哪种数据压缩后的收益最明显?

单选题 · mid

  • A.已经压缩过的 PNG 图片数据
  • B.完全随机生成的加密数据
  • C.高熵均匀分布的密钥数据
  • D.含大量重复字段的日志文本← 正确答案

答案:D。压缩算法挖掘的是数据中的冗余模式。日志文本包含大量重复字段和固定前缀,冗余度高,压缩比可观。已压缩的图片、随机数据和密钥数据的熵高、冗余极低,几乎压不动。所以评估压缩效果必须看真实数据类型,而不是盲目相信算法宣传。

Q4. 关于 LZ4 算法,下列说法正确的是:

单选题 · easy

  • A.以极快速度著称且压缩比适中← 正确答案
  • B.压缩比最高但压缩速度极慢
  • C.属于有损压缩无法还原原始数据
  • D.只能压缩一次终身无法解压

答案:A。LZ4 的核心优势是压缩和解压速度极快,压缩比适中,适合延迟敏感场景。Gzip 才是压缩比高但速度慢的代表。LZ4 是无损压缩,压缩后可以完整解压还原。这就像随手卷 T 恤,动作快但省的空间有限。

Q5. 引入缓存压缩后,系统需要承担哪些额外开销?

多选题 · mid

  • A.写入时的压缩 CPU 开销← 正确答案
  • B.读取时的解压延迟开销← 正确答案
  • C.压缩块元数据的额外内存← 正确答案
  • D.源端数据库的额外存储空间

答案:ABC。压缩缓存的三大额外开销是:写入时压缩消耗 CPU、读取时解压增加延迟、记录压缩类型和原始大小的元数据占用内存。源端数据库的存储空间与压缩缓存无关。这就像收纳行李要付出打包时间、找衣服时的拆包时间,以及收纳袋本身占的角落空间。

Q6. 对于高频访问的热数据,工程上通常采用的策略是:

单选题 · mid

  • A.使用最高压缩比强力压缩
  • B.保持不压缩以降低访问延迟← 正确答案
  • C.压缩后每次访问都重复解压
  • D.直接放弃缓存全部回源数据库

答案:B。热数据访问频率极高,每次访问都要解压,压缩带来的延迟放大会超过省内存的收益。正确做法是热数据不压缩或使用极快算法,冷数据才用高压缩比。这与旅行中把天天穿的衣服放在最外层不打包是一个道理。

Q7. 某缓存分配 1GB 物理内存,采用平均压缩比 r=2 的算法后,有效缓存容量约为:

单选题 · mid

  • A.有效容量保持 1GB 不变
  • B.有效容量降到 0.5GB
  • C.有效容量提升到 2GB← 正确答案
  • D.有效容量提升到 4GB

答案:C。根据有效容量公式 C_eff = M 乘以 r,1GB 内存乘压缩比 2 得到 2GB 有效容量。压缩没有改变物理内存大小,只是让每份数据占用空间减半,从而能容纳两倍的原始数据。B 把压缩比放在分母上算反了,D 则是把压缩比错当成 4。

Q8. 选择压缩算法时需要考察哪些指标?

多选题 · easy

  • A.压缩速度与解压速度表现← 正确答案
  • B.数据类型的可压缩性高低← 正确答案
  • C.平均压缩比与波动情况← 正确答案
  • D.操作界面是否美观易用

答案:ABC。选型要综合看压缩和解压速度、目标数据的可压缩性、以及平均压缩比是否稳定。压缩是后端服务的内嵌能力,不涉及用户操作界面。就像选择打包手法要看手法快不快、行李材质适不适合、能省多少空间,而不是看收纳袋好不好看。

Q9. 平均访问延迟公式中,符号 h 代表的含义是:

单选题 · hard

  • A.读取到的数据原始字节数
  • B.压缩后数据的平均字节数
  • C.请求在缓存中命中的概率← 正确答案
  • D.未命中缓存的回源延迟值

答案:C。在 T_avg = h × (T_read + T_decomp) + (1 − h) × T_miss 中,h 是缓存命中率。命中率越高,压缩缓存的解压延迟被放大的次数越多。A 和 B 与公式含义无关,D 是 T_miss 代表的概念,不是 h。

Q10. 下列哪些做法能有效降低压缩缓存的 CPU 开销?

多选题 · hard

  • A.对所有数据一律采用高压缩比
  • B.冷数据压缩而热数据不压缩← 正确答案
  • C.小于阈值的小数据块跳过压缩← 正确答案
  • D.按数据特征自适应选择算法← 正确答案

答案:BCD。降低压缩 CPU 开销的关键是“挑着压”:热数据不压避免延迟放大,小对象跳过压缩避免无谓开销,按数据特征自适应选算法让每种数据用最合适的手法。对所有数据一律高压缩比恰恰会放大 CPU 开销,是错误做法。