doc: 阅读redis文档

This commit is contained in:
asahi
2025-09-22 11:41:39 +08:00
parent 8eb167073e
commit 81c1ab11e0

View File

@@ -134,6 +134,11 @@
- [single bit operations](#single-bit-operations) - [single bit operations](#single-bit-operations)
- [operations on group of bits](#operations-on-group-of-bits) - [operations on group of bits](#operations-on-group-of-bits)
- [longest streak of daily visits](#longest-streak-of-daily-visits) - [longest streak of daily visits](#longest-streak-of-daily-visits)
- [Probabilistic](#probabilistic)
- [HyperLogLog](#hyperloglog)
- [Bloom Filter](#bloom-filter)
- [Example](#example-1)
- [Reserving Bloom filters](#reserving-bloom-filters)
# redis # redis
@@ -2303,5 +2308,90 @@ bitcount的使用示例如下
bitmaps可以被轻松的拆分为多个key通常来讲也应当避免操作过大的key。将大的bitmap拆分为多个key时通用策略是`限制每个key`存储`M`个bits并且通过`{bit-index}/M`来决定当前bit位于哪个key而`{bit-index} MOD M`则用于当前bit位于key的哪个位置。 bitmaps可以被轻松的拆分为多个key通常来讲也应当避免操作过大的key。将大的bitmap拆分为多个key时通用策略是`限制每个key`存储`M`个bits并且通过`{bit-index}/M`来决定当前bit位于哪个key而`{bit-index} MOD M`则用于当前bit位于key的哪个位置。
### Probabilistic
`Probabilistic data structure`向使用者提供了统计数据的`近似值`,例如`计数、频率、排名`等而并非精确值。使用Probabilistic data structure可以提高计算效率。
#### HyperLogLog
`HyperLogLog`数据结构用于估计set中的基数HyperLogLog并不能保证结果的精确性但是能够提高空间的使用效率。
> Redis的HyperLogLog实现最多占用12KB空间并提供了`0.81%`的标准误差。
通常统计items中的唯一项个数需要花费的空间和items的个数成正比但是有一系列算法可以`牺牲精确性来换取内存使用大小`
- 其能够返回唯一项个数的大致估计值并且估计值存在标准误差在redis HyperLogLog的实现中标准误差小于1%
- 在使用该算法时并不需要使用和items个数成正比的内存空间而是使用常量大小的内存在最坏情况下使用空间大小为12KB当HyperLogLog中包含元素较少时其使用的空间也远小于12KB
在redis中HyperLogLog是编码成Redis strings的。故而对于`HyperLogLog`类型,可以通过`GET`来进行序列化,并通过`SET`来进行反序列化。
在使用HyperLogLog时其API如下
- `PFADD`: 可以通过该命令将new item添加到HyperLogLog
- `PFCOUNT`: 当想要获取唯一项个数的近似值时,可以调用`PFCOUNT`命令
- `PFMERGE`: 如果想要对两个不同的HyperlogLog进行合并可以使用`PFMERGE`命令
HyperLogLog的使用示例如下所示
```redis-cli
> PFADD bikes Hyperion Deimos Phoebe Quaoar
(integer) 1
> PFCOUNT bikes
(integer) 4
> PFADD commuter_bikes Salacia Mimas Quaoar
(integer) 1
> PFMERGE all_bikes bikes commuter_bikes
OK
> PFCOUNT all_bikes
(integer) 6
```
HyperLogLog数据结构通常有如下用例场景统计页面或网站的每天用户访问量
#### Bloom Filter
Bloom Filter也是一种`Probabilistic data structure`用于检测在set中item是否存在其使用少量的的固定大小存储空间。
Bloom Filter并不会将items都存储在set中相对的其仅存储item在hash后的结果故而在部分程度上会牺牲精确性。`通过对精确性的牺牲Bloom Filter拥有十分高的内存效率并且其执行效率也很高`。
`Bloom Filter仅能够保证某元素在set中不存在但是关于元素的存在其仅能给出一个估计值`
- 当Bloom Filter的返回结果表示某item不存在于set中时`返回结果是精确的该item一定在set中不存在`
- 但是如果若Bloom Filter返回结果表示某item存在时`每N个存在的返回结果就有一个是错误的`。
Bloom Filter通常用于`negative answer will prevent more costly operations`的场景,例如`用户名称是否被占用,信用卡是否被丢失,用户是否看过广告等`
##### Example
假设自行车生产商已经生产了百万种不同型号的自行车,目前需要`在为新model指定名称时避免指定旧model已经使用过的名称`。
在该种用例场景下可以使用bloom filter来检测重复。在如下实例中创建的bloom filter可容纳100w entries并且错误率仅为0.1%。
```redis-cli
> BF.RESERVE bikes:models 0.001 1000000
OK
> BF.ADD bikes:models "Smoky Mountain Striker"
(integer) 1
> BF.EXISTS bikes:models "Smoky Mountain Striker"
(integer) 1
> BF.MADD bikes:models "Rocky Mountain Racer" "Cloudy City Cruiser" "Windy City Wippet"
1) (integer) 1
2) (integer) 1
3) (integer) 1
> BF.MEXISTS bikes:models "Rocky Mountain Racer" "Cloudy City Cruiser" "Windy City Wippet"
1) (integer) 1
2) (integer) 1
3) (integer) 1
```
> 在上述示例中即使bloom filter中仅存在少量元素返回的`存在`结果也存在误报的可能,即元素其实根本不存在。
##### Reserving Bloom filters
在使用bloom filters时大部分sizing工作都会自动完成
```redis-cli
BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion] [NONSCALING]
```
- `error_rate`: 该参数代表`false positive rate`该rate为0和1之间的decimal例如当希望的false positive rate为`0.1%`(1 in 1000)时需要将error_rate设置为0.001
- `expected capacity(capacity)`: 该参数代表`bloom filter中期望包含的元素数量`。需要确保该值的准确性:
- 如果该值设置过大,其会浪费内存空间
- 如果该值设置过小那么filter被填充满后`a new one will have to be stacked on top of it (sub-filter stacking)`
- `when a filter consists of multiple sub-filters stacked on top of each other``其新增操作的延迟仍然会保持不变;但是存在性检查的延迟会增加`
- 存在性检查的原理如下首先会对top filter检查元素的存在性如果返回为false那么会继续检查以一个sub-filter`该机制会导致存在性检查的延迟增加`
- `scaling(EXPANSION)`: 在向bloom filter中添加数据时并不会因为数据结构的填充而失败。在向filter中添加元素时error rate也会随之增加。为了保证错误率和bloom filter创建时指定的error rate相近bloom filter需要自动扩容`当capacity限制达到时需要自动创建额外的sub-filter`。
- `new sub filter`的size大小等于`last-sub-filter-size * EXPANSION`。
- 如果filter中存储的items数量未知可以将`EXPANSION`设置为`2 or more`从而减少sub-filters的数量。
- 否则,可以将`EXPANSION`设置为`1`,从而减少内存的消耗
- 默认的EXPANSION为2
> 在向filter中添加new sub-filter时相比于前一个filter会为new sub-filter分配更多的hash function
- `NONSCALING`: 如果想要禁用scale可以指定`NONSCALING`。如果达到了initially assigned