一、压缩的本质:信息熵与冗余度
做低延迟系统这么多年,我经常被问到同一个问题:压缩到底在做什么?
说白了,压缩就是去掉冗余。你想想看,一段数据里其实有很多“废话”。比如一个文本文件里连续出现100个空格,或者一段音频里有一段静音,这些都属于冗余。
那怎么衡量一个数据能不能压缩?能压缩多少?这就引出了两个核心概念:信息熵和冗余度。
1.1 信息熵:数据的不确定性
信息熵这个概念,最早是香农提出来的。它衡量的是数据的不确定性。熵越高,数据越“随机”,越难压缩。熵越低,数据越“有序”,压缩空间越大。
公式很简单:
H(X) = -Σ p(x) * log₂ p(x)
其中 p(x) 是每个符号出现的概率。
举个例子:
- 如果一段数据全是字母'A',那 p('A') = 1,熵 H = 0。这意味着完全没有不确定性,可以压缩到极致。
- 如果一段数据里'A'和'B'各占一半,p=0.5,熵 H = 1。这意味着每个符号需要1个bit来表示。
- 如果数据里有256种符号均匀分布,熵 H = 8。这意味着每个符号需要8个bit,也就是一个字节。
核心观点:信息熵给出了无损压缩的理论极限。你不可能压缩到比熵更小的体积,除非你愿意丢失信息(有损压缩)。
1.2 冗余度:压缩的“油水”
冗余度就是数据中可以被去掉的部分。它等于数据实际大小减去信息熵。
冗余度 = 数据大小 - 信息熵
我在项目中遇到过一种情况:一个日志文件,里面90%的内容都是重复的时间戳和IP地址。这种数据的冗余度极高,压缩比能做到50:1甚至更高。但如果是加密后的数据,看起来完全是随机的,冗余度接近0,基本压不动。
实战经验:判断一个数据能不能压缩,先看它的冗余度。如果冗余度很低,就别浪费时间了。我曾经见过有人用gzip去压缩AES加密后的数据,结果文件反而变大了——因为加密增加了熵。
1.3 常见的冗余类型
在实际系统中,冗余通常来自以下几个方面:
| 冗余类型 | 说明 | 例子 |
|---|---|---|
| 统计冗余 | 某些符号出现频率更高 | 英文文本中'e'远多于'z' |
| 空间冗余 | 相邻数据之间存在相关性 | 图片中相邻像素颜色相近 |
| 时间冗余 | 连续帧之间变化很小 | 视频中相邻帧几乎一样 |
| 字典冗余 | 相同模式重复出现 | 日志中重复的URL路径 |
不同的冗余类型,需要用不同的压缩算法去处理。比如统计冗余适合用霍夫曼编码,空间冗余适合用差分编码或变换编码。
二、为什么需要低延迟压缩?
好,现在我们知道压缩的本质了。但问题来了:为什么要在低延迟场景下做压缩?
传统的压缩方案,比如gzip、bzip2,它们的目标是压缩比最大化。为了多压几个百分点,它们愿意花大量CPU时间去做复杂的计算。这在离线场景下没问题——你压缩一个文件,等几秒钟无所谓。
但在低延迟场景下,情况完全不同。
2.1 低延迟场景的典型需求
我参与过几个金融交易系统的项目,这些系统对延迟的要求是微秒级的。在这种场景下:
- 网络带宽是瓶颈,需要压缩数据来减少传输时间
- 但压缩和解压缩本身不能引入太多延迟
- 压缩比不是第一目标,延迟和吞吐量才是
举个例子:
假设你要传输1MB的数据,网络带宽是10Gbps。不压缩的话,传输时间大约是0.8毫秒。如果用gzip压缩到200KB,压缩比5:1,但gzip压缩需要5毫秒,解压缩需要3毫秒。总延迟变成了5+0.16+3=8.16毫秒,反而更慢了。
但如果用LZ4这种轻量级算法,压缩只需要0.5毫秒,解压缩0.3毫秒,压缩到400KB。总延迟是0.5+0.32+0.3=1.12毫秒,比不压缩的0.8毫秒略高,但节省了60%的带宽。
关键权衡:低延迟压缩的核心是在压缩比和速度之间找到平衡点。不是压得越小越好,而是要在可接受的延迟预算内,尽可能减少数据量。
2.2 低延迟压缩的应用场景
我整理了几个典型的低延迟压缩场景:
- 金融交易:行情数据、订单流需要在微秒级内完成压缩传输
- 实时视频流:直播、视频会议需要低延迟编码解码
- 数据库日志:WAL日志、redo log需要快速压缩写入
- 内存数据库:数据页压缩,减少内存带宽压力
- 物联网:传感器数据在边缘设备上快速压缩后上传
这些场景有一个共同点:延迟是硬约束。你不能为了压缩而牺牲延迟,否则系统就不可用了。
2.3 低延迟压缩的核心挑战
嗯,这里要注意。低延迟压缩并不是简单地把算法换一下就行。它有几个核心挑战:
- CPU开销:压缩算法需要计算,会占用CPU时间片
- 内存访问:压缩需要读写数据,会引入缓存未命中的开销
- 流式处理:数据是源源不断来的,不能等全部收齐再压缩
- 硬件适配:不同硬件(CPU、GPU、FPGA)的压缩性能差异很大
避坑指南:我曾经在一个项目中,直接用了zlib的默认参数去压缩实时数据流。结果发现压缩延迟波动很大,有时候一个数据包要压几十毫秒。后来才发现,zlib的默认参数会动态调整压缩级别,导致延迟不稳定。解决方案是固定压缩级别,并且使用预分配的缓冲区,避免内存分配带来的抖动。
三、本章知识体系
为了让你更直观地理解本章的内容结构,我画了一张图:
这张图把本章的两个核心主题串起来了。左边是压缩的理论基础,右边是低延迟场景下的实际需求。两者结合,就是我们这门课要讲的核心内容。
我的建议:如果你刚开始接触低延迟压缩,先理解信息熵和冗余度的概念。这比学具体算法更重要。因为只有理解了为什么能压缩,你才能判断该用什么算法。
好了,第一章就到这里。记住一句话:压缩不是魔法,它只是把数据里的“水分”挤出去。而低延迟压缩,就是要在挤水分的同时,保证速度够快。
公众号:蓝海资料掘金营,微信deep3321