oxcache 0.5.0-rc.5

A high-performance multi-level cache library for Rust with L1 (memory) and L2 (Redis) caching.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# 🏗️ Oxcache 架构文档

本文档描述 Oxcache 库(v0.5.0-rc.4)的架构、设计决策和技术细节。

## 📋 目录

<details open>
<summary>📑 目录</summary>

- [🧭 概述](#-概述)
- [🧱 总体架构](#-总体架构)
- [🧩 组件](#-组件)
  - [1. 内部缓存注册表](#1-内部缓存注册表)
  - [2. 缓存接口](#2-缓存接口)
  - [3. 后端层](#3-后端层)
  - [4. 特性模块](#4-特性模块)
  - [5. 基础设施模块](#5-基础设施模块)
  - [6. 安全模块](#6-安全模块)
  - [7. 键生成器](#7-键生成器)
  - [8. 事件模块](#8-事件模块)
  - [9. 配置与注册模块](#9-配置与注册模块)
- [🔀 数据流](#-数据流)
- [📐 一致性模型](#-一致性模型)
- [🧯 故障处理](#-故障处理)
- [⚡ 性能优化](#-性能优化)
- [🔒 安全](#-安全)
- [📈 可扩展性](#-可扩展性)
- [🎨 特性标志](#-特性标志)
- [🔮 未来增强](#-未来增强)
- [📚 参考资料](#-参考资料)

</details>

## 🧭 概述

Oxcache 是一个多级缓存系统,专为高性能、生产就绪的应用设计。它整合了:

- **L1 缓存**:使用 Moka(LRU/TinyLFU 淘汰)或 DashMap 的内存缓存
- **L2 缓存**:使用 Redis(Standalone/Sentinel/Cluster)、Valkey、Dragonfly 或 Aerospike 的分布式缓存
- **ChainCache**:按分数排序的多后端缓存链,支持回填与竞速读取
- **同步 API**:异步 API 的同步镜像(`get_sync` / `set_sync` / …),用于非异步调用场景
- **布隆过滤器**:可选装饰器,在负查询到达内部后端前短路返回
- **单条目 TTL**:所有后端统一支持 `ttl` / `expire` 操作
- **穿透与击穿防护**:单飞去重(64 分片)、空值哨兵、TTL 抖动、布隆负查询短路
- **跨实例失效**:`invalidation` 特性经 Redis Pub/Sub 广播失效事件,键空间通知第二通道
- **版本化 CAS**:`versioning` 特性提供内存与 Redis WATCH/MULTI/EXEC 两种 `compare_and_swap` 实现
- **自动降级**:`degradation` 特性三态状态机(Active/Degraded/HalfOpen),故障时降级 L1-only 并自动探测恢复

> **说明**:文档历史版本中引用的 WAL(Write-Ahead-Log)恢复层不存在于当前代码库中,持久性委托给 Redis 后端本身;跨实例失效层则以 `invalidation` 特性形式在 0.5.0-rc.4 落地。

### 设计目标

1. **性能**:L1 延迟 50-100ns,L2 延迟 1-5ms(P99,随环境变化)
2. **可靠性**:后端 trait 层级让调用方在 L2 不可达时优雅降级
3. **易用性**:通过 `#[cached]` 宏实现零模板代码集成
4. **可观测性**:指标(`CacheStats`、Prometheus/JSON 导出)、`telemetry` 遥测、健康检查
5. **安全性**:Redis 键 / Lua 脚本 / SCAN 模式的输入校验,敏感数据脱敏

## 🧱 总体架构

Oxcache 采用「统一接口 + 可插拔后端」的分层设计。应用只面对 `Cache<K, V>` 一个类型安全入口,序列化(`infra::serialization`)与指标(`infra::metrics`)横切其后。所有读写最终落到实现 `CacheReader` / `CacheWriter` / `CacheConnector` 三个 trait 的后端上,blanket impl 自动将其组合为 `CacheBackend`。`#[cached]` 宏由独立的 `oxcache_macros` crate 提供,经 `internal::MACRO_CACHES` 注册表把函数调用接入同一套缓存路径。

```mermaid
flowchart TD
    APP["应用代码"] --> CACHE
    MACRO["oxcache_macros<br/>cached 属性宏"] --> REG["internal<br/>MACRO_CACHES 注册表"]
    REG --> CACHE["cache<br/>Cache / CacheBuilder / ChainCache"]
    CACHE --> BACKEND["backend<br/>CacheReader / CacheWriter / CacheConnector"]
    CACHE --> INFRA["infra<br/>serialization / metrics"]
    CACHE --> SEC["security<br/>输入校验 / 脱敏"]
    CACHE --> UTILS["utils<br/>KeyGenerator"]
    CACHE --> ERR["error<br/>OxCacheError"]
    BACKEND --> MEM["memory<br/>Moka / DashMap"]
    BACKEND --> DIST["redis / dragonfly / aerospike"]
    BACKEND --> FEATS["features<br/>bloom_filter / dist_lock / encryption / invalidation"]
```

`batch`(缓冲写入)、`integrations::kit`(生命周期集成)、`i18n`、`config`、`traits`、`testing` 等模块按特性门控挂载。

## 🧩 组件

### 1. 内部缓存注册表

**位置**:`src/internal.rs`

**职责**:缓存实例的中央注册表,供 `#[cached]` 宏使用。

**数据结构**:

```rust
type MacroCacheMap = Mutex<HashMap<String, Arc<Cache<String, Vec<u8>>>>>;
static MACRO_CACHES: once_cell::sync::OnceCell<MacroCacheMap> = ...;
```

注册表存储**具体的 `Cache<String, Vec<u8>>` Arc 句柄**(非 trait 对象),以服务名为键。使用 `Mutex<HashMap<…>>` 而非 `DashMap`。

**公共内部函数**(仅两个):

- `__internal_register_cache(name, cache: Arc<Cache<String, Vec<u8>>>)` — 注册/覆盖某服务的缓存(同步,互斥锁中毒时为 no-op)
- `__internal_get_cache(name) -> Option<Arc<Cache<String, Vec<u8>>>>` — 按服务名获取缓存(同步)

两者均从 `oxcache::internal` 重导出,`oxcache::__internal_get_cache` 在 crate 根重导出供宏生成代码使用。

**线程安全**:互斥锁仅在 map 变更/查找期间持有(持锁期间无 await)。

**使用模式**:

```rust
use oxcache::Cache;

// 构建缓存实例
let cache: Cache<String, Vec<u8>> = Cache::builder().build().await?;

// 方式一:经 internal 模块注册(供 #[cached] 宏使用)
oxcache::internal::__internal_register_cache("my_service", Arc::new(cache.clone()));

// 方式二:使用 Cache 上的便捷方法
cache.register_for_macro("my_service").await?;

// 宏生成的代码从注册表获取缓存:
#[cached(service = "my_service", ttl = 300)]
async fn get_user(id: u64) -> User { /* ... */ }
```

### 2. 缓存接口

**位置**:`src/cache/`

**职责**:统一的类型安全缓存接口。

**模块结构**:

- `cache/mod.rs` — 模块根和重导出
- `cache/builder/` — `CacheBuilder` 实现
- `cache/api/` — 缓存操作实现(`basic_ops`、`batch_ops`、`bytes_ops`、`macros` 等)
- `cache/chain.rs` + `cache/chain/` — `ChainCache`、`ChainLink`、`ChainCacheBuilder`
- `cache/interface.rs` — `UnifiedCache` trait
- `cache/typed_namespace.rs` — `TypedNamespace` 类型化命名空间隔离

**关键类型**:

- `Cache<K, V>`:主缓存类型,泛型键(`K: CacheKey`)和值(`V: Serialize + DeserializeOwned`)
- `CacheBuilder<K, V>`:用于创建已配置缓存实例的构建器
- `ChainCache` / `ChainLink` / `ChainCacheBuilder`:多级缓存链(按分数排序)
- `L1Builder` / `L2Builder` / `ChainBuilder`:分层构建器 API(与 `CacheBuilder`/`ChainCacheBuilder` 并存)

`Cache<K, V>` 的构造方法(`builder` / `new` / `memory` / `redis` / `with_dependencies`)、`CacheBuilder` 全部方法与「`CacheBuilder` 不暴露 `.redis(...)` / `.tiered(...)` 等方法,组合多后端用 `ChainCache` + `.backend_arc(...)`」的说明见 [API 参考](API_REFERENCE.md#-cachebuilder)。要点:`sync_mode(true)` 不能与 `backend_arc(Arc<dyn CacheBackend>)` 组合,两者同时设置时 `build()` 返回 `Err(OxCacheError::NotSupported)`(OXCACHE_009)——这是 stable Rust 上 `trait_upcasting` 的临时限制。

关键异步方法(`get` / `set` / `set_with_ttl` / `get_by_str` / `set_by_str` / `delete` / `exists` / `clear` / `get_or` / `ttl` / `expire` / `get_bytes` / `set_bytes` / 生命周期与统计 / `register_for_macro`)与同步方法(`get_sync` / `set_sync` / `set_with_ttl_sync` / `delete_sync` / `exists_sync` / `clear_sync` / `ttl_sync` / `expire_sync` / `get_or_sync`)的逐项签名见 [API 参考](API_REFERENCE.md#-cachek-v) 与 [API 参考的同步 API 章节](API_REFERENCE.md#-同步-api)。

**线程安全**:所有操作通过 `Arc<dyn CacheBackend>`(同步路径为 `Option<Arc<dyn SyncCacheBackend>>`)保证线程安全。

**使用模式**:

```rust
use oxcache::Cache;
use std::time::Duration;

// 1) 简单内存缓存(默认)
let cache: Cache<String, User> = Cache::builder()
    .ttl(Duration::from_secs(3600))
    .capacity(10000)
    .build()
    .await?;

// 2) Redis 缓存(强制 TLS,除非设置了 OXCACHE_ALLOW_INSECURE_REDIS)
let cache: Cache<String, User> = Cache::redis("rediss://localhost:6379").await?;

// 3) 注入任意自定义后端
let backend: Arc<dyn oxcache::backend::CacheBackend> = /* ... */;
let cache: Cache<String, User> = Cache::builder()
    .backend_arc(backend)
    .ttl(Duration::from_secs(3600))
    .build()
    .await?;

// 4) 同步 API(Moka 需要 multi_thread tokio 运行时)
let cache: Cache<String, String> = Cache::builder()
    .sync_mode(true)
    .build()
    .await?;
cache.set_sync(&"k".to_string(), &"v".to_string())?;
let v = cache.get_sync(&"k".to_string())?;

// 注册供 #[cached] 宏使用
cache.register_for_macro("my_service").await?;
```

### 3. 后端层

**位置**:`src/backend/`

**职责**:可插拔的缓存后端实现,遵循 ISP 合规 trait 层级。

**模块结构**:

- `backend/mod.rs` — 模块根和重导出
- `backend/interface.rs` — `CacheReader` / `CacheWriter` / `CacheConnector` / `CacheBackend` 及其同步镜像;`AtomicCacheWriter` / `SyncAtomicCacheWriter` 用于原子操作
- `backend/memory/` — 内存后端实现(Moka、DashMap)及 Redis/Valkey 客户端
- `backend/dragonfly/` — Dragonfly 后端(基于 Redis 协议包装)
- `backend/aerospike/` — Aerospike 后端(独立协议,feature-gated)
- `backend/score.rs` — `BackendScore` / `Scores` 常量供 `ChainCache` 使用
- `backend/config_validation.rs` — Redis/Valkey URL / Sentinel 配置校验
- `backend/factory.rs` — `BackendFactory` / `BackendRegistry` / `BackendSpec` 后端工厂注册中心

**后端类型**(重导出在 `oxcache::backend::*`,部分在 crate 根):

| 类型 | 路径 | 特性 | 说明 |
|------|------|------|------|
| `MokaMemoryBackend` | `oxcache::backend::MokaMemoryBackend` | `memory` | L1 缓存,Moka(LRU/TinyLFU) |
| `DashMapMemoryBackend` | `oxcache::backend::DashMapMemoryBackend` | `memory` | 纯内存并发缓存,FIFO O(1) 淘汰 |
| `RedisBackend` | `oxcache::backend::RedisBackend` | `redis` | L2 分布式缓存(Redis/Valkey) |
| `RedisBackendBuilder` | `oxcache::backend::RedisBackendBuilder` | `redis` | Redis/Valkey 构建器(模式、连接池、TLS) |
| `DragonflyBackend` | `oxcache::backend::DragonflyBackend` | `dragonfly` | Dragonfly 缓存(Redis 协议兼容) |
| `AerospikeBackend` | `oxcache::backend::AerospikeBackend` | `aerospike` | Aerospike 持久化 KV 存储 |
| `ChainCache` | `oxcache::cache::chain::ChainCache` | — | 按分数排序的多后端缓存链 |
| `BloomFilterBackend` | `oxcache::features::bloom_filter::BloomFilterBackend` | `bloom` | 负查询过滤装饰器 |

**异步 Trait 层级**(`backend/interface.rs`):

```rust
#[async_trait]
pub trait CacheReader: Send + Sync + 'static {
    async fn get(&self, key: &str) -> OxCacheResult<Option<Vec<u8>>>;
    async fn exists(&self, key: &str) -> OxCacheResult<bool>;
    async fn ttl(&self, key: &str) -> OxCacheResult<Option<Duration>>;
    async fn len(&self) -> OxCacheResult<u64>;
    async fn is_empty(&self) -> OxCacheResult<bool> { /* 默认实现 */ }
    async fn capacity(&self) -> OxCacheResult<u64>;
    async fn stats(&self) -> OxCacheResult<HashMap<String, String>>;
    async fn get_many(&self, keys: &[String]) -> OxCacheResult<Vec<Option<Vec<u8>>>> { /* 默认 */ }
    async fn keys(&self, pattern: &str) -> OxCacheResult<Vec<String>> { /* 默认:空 Vec */ }
}

/// 批量写入条目类型:`(Arc<str> key, Arc<Vec<u8>> value, Option<Duration> ttl)`
pub type CacheSetItem = (Arc<str>, Arc<Vec<u8>>, Option<Duration>);

#[async_trait]
pub trait CacheWriter: Send + Sync + 'static {
    async fn set(&self, key: Arc<str>, value: Arc<Vec<u8>>, ttl: Option<Duration>) -> OxCacheResult<()>;
    async fn delete(&self, key: &str) -> OxCacheResult<()>;
    async fn clear(&self) -> OxCacheResult<()>;
    async fn expire(&self, key: &str, ttl: Duration) -> OxCacheResult<bool>;
    async fn set_many(&self, items: &[CacheSetItem]) -> OxCacheResult<()> { /* 默认 */ }
    async fn delete_many(&self, keys: &[String]) -> OxCacheResult<()> { /* 默认 */ }
}

#[async_trait]
pub trait CacheConnector: Send + Sync + 'static {
    async fn health_check(&self) -> OxCacheResult<()>;
    async fn shutdown(&self);
    fn backend_kind(&self) -> BackendKind;
    #[cfg(feature = "lua")]
    fn as_lua_executor(&self) -> Option<&dyn LuaExecutor> { None }
    fn as_atomic_writer(&self) -> Option<&dyn AtomicCacheWriter> { None }
}

#[async_trait]
pub trait CacheBackend: CacheReader + CacheWriter + CacheConnector + 'static {}
// blanket 实现:满足三个超级 trait 的任意 T 自动成为 CacheBackend。
```

**同步 Trait 层级**(镜像异步版本,无 `async`/`#[async_trait]`):

```rust
pub trait SyncCacheReader: Send + Sync + 'static { /* 同步 fn */ }
pub trait SyncCacheWriter: Send + Sync + 'static { /* 同步 fn */ }
pub trait SyncCacheConnector: Send + Sync + 'static { /* 同步 fn */ }
pub trait SyncCacheBackend: SyncCacheReader + SyncCacheWriter + SyncCacheConnector + 'static {}
```

后端通过额外实现同步 trait 来选择加入同步 API。`Cache<K, V>::get_sync` 通过 `Arc<dyn SyncCacheBackend>` 分发。**异步和同步层级有意分离**,使后端可以只支持其一,且保持异步 trait 对象的对象安全(异步热路径上无 `block_in_place`)。

**AtomicCacheWriter**(独立 trait,非 `CacheWriter` 的超级 trait):

```rust
#[async_trait]
pub trait AtomicCacheWriter: Send + Sync + 'static {
    async fn incr(&self, key: &str, delta: i64, ttl: Option<Duration>) -> OxCacheResult<i64>;
    async fn compare_and_swap(&self, key: &str, expected: Option<&[u8]>, new: Vec<u8>, ttl: Option<Duration>) -> OxCacheResult<bool>;
    async fn set_if_absent(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> OxCacheResult<bool>;
}

pub trait SyncAtomicCacheWriter: Send + Sync + 'static { /* 同步镜像 */ }
```

后端通过 `CacheConnector::as_atomic_writer()` 暴露原子能力。`Cache<K,V>::incr()` / `compare_and_swap()` / `set_if_absent()` 通过此运行时发现方法委托;后端缺少原子支持时返回 `Err(NotSupported)`。`versioning` 特性另提供带版本信封的 `MemoryVersionedCache` / `RedisVersionedCache`(WATCH/MULTI/EXEC)实现。

**`BackendKind` 枚举**(`Moka | DashMap | Redis | Valkey | Dragonfly | Aerospike | Chain | Mock | Unknown`)由 `backend_kind()` 返回,用于运行时标识而无需 `as_any()`。

**ChainCache 读取路径**:

```
1. 从最高分(L1)到最低分(L2)遍历 ChainLink
2. 命中 → 返回值
3. 未命中(None 或 Err)→ 记录警告并继续下一个链接
   (L1 读取失败优雅降级而非使请求失败)
4. 在非最高分链接命中后,如启用回填,
   异步填充更高分(更靠近 L1)的链接
   (fire-and-forget tokio::spawn,失败仅警告不传播)
```

启用 `enable_race_read()`(选择加入)后,读取路径改为**并发**查询**所有**
后端(`JoinSet`)并返回首个命中;非最高分命中时仍执行回填,
仅当所有后端都失败时读取才报错。

**ChainCache 写入路径**:

```
1. 并发(tokio::spawn / JoinSet)写入所有分数
   <= 写入者阈值的链接(通常所有非持久化 + 持久化写入者)
2. 持久化后端接收写入以保证持久性
3. 单链接失败仅记录日志并容忍;仅当所有后端都失败时
   写入才报错
4. 无 WAL(持久性委托给 Redis 后端本身)
```

**ChainCache 健康检查**:每个链接并发 ping,每个后端 5 秒超时;仅当所有链接都失败时 `health_check()` 才失败。

### 4. 特性模块

**位置**:`src/features/`

**职责**:可选能力和运行时特性信息。

**关键项**:

- `features::bloom_filter::BloomFilter` — 概率数据结构(`new(capacity, fpr)`、`insert`、`contains`、`clear`、`len`、`is_empty`)
- `features::bloom_filter::BloomFilterBackend` — 装饰器,包装任意 `CacheBackend`;`get` 时如键不在布隆过滤器中则直接返回 `Ok(None)`
- `features::dist_lock` — Redis 分布式锁(watchdog 续期、可重入);`red-lock` 提供 `RedLock` 多节点多数派锁与 fencing token
- `features::encryption` — `EncryptedBackend` 值级 XChaCha20-Poly1305 加密装饰器
- `features::invalidation` — 跨实例失效总线(Redis Pub/Sub 广播 + 键空间通知)
- `features::degradation` — `DegradableBackend` 三态自动降级装饰器
- `features::compression` — `CompressingBackend` 自适应 zstd 压缩装饰器
- `features::audit` — `AuditEventPublisher` 结构化审计事件流
- `features::versioning` — 版本化 CAS 实现
- `features::confers_config` — confers 配置驱动构建(`OxcacheConfig` + `ConfigBus` 热更新)
- `get_l1_feature_info() / get_l2_feature_info() / get_all_feature_info()`
- `is_l1_enabled() / is_l2_enabled()`

### 5. 基础设施模块

**位置**:`src/infra/`

**职责**:指标、序列化和键校验工具。

**子模块**:

- `infra/metrics/backend.rs` — `MetricsCollector`、`LatencyHistogram`、`OperationCounter`、`FullMetrics`
- `infra/metrics/snapshot.rs` — `CacheStats`
- `infra/metrics/export.rs` — `export_json_format`、`export_prometheus_format`、`get_enhanced_stats`
- `infra/metrics/unified.rs` — `UnifiedMetrics`、原子计数器、直方图数据
- `infra/serialization/` — JSON 序列化器(`JsonSerializer`)、`UnifiedSerializer` 与二进制格式(`SerializationFormat`:Json/Bincode/Postcard)
- `infra::validate_cache_key(key)` — 键校验便捷方法

**Crate 根重导出**(启用 `metrics` 特性时):

```rust
pub use infra::{export_json_format, export_prometheus_format, export_prometheus_standard, get_enhanced_stats, CacheStats};
```

**重要**:`MetricsCollector` **不**在 crate 根重导出。它位于 `oxcache::infra::metrics::backend::MetricsCollector::new() -> OxCacheResult<Self>`。指标注入端口的抽象为 `MetricsRecorder`(crate 根重导出,含 `NoOpMetricsRecorder` 默认实现)。

**序列化**:默认 **JSON**(`serialization` 特性引入 `serde` + `serde_json`);`serde-bincode` / `postcard` 特性启用对应二进制格式,经 `CacheBuilder::serialization_format()` 切换,同一键前缀禁混格式。序列化在 `infra/serialization/` 中实现(`json.rs`、`binary.rs`、`unified.rs`、`utils.rs`、`depth_limited.rs`):

- **`JsonSerializer`** — 异步/同步后端侧序列化器(值为 `Vec<u8>`);`with_compression()` 启用 flate2 gzip 输出。
- **`UnifiedSerializer`** — 值级编解码(`serialize<T>` / `deserialize<T>` / `estimate_size`),供 `Cache<K, V>` 和 `#[cached]` 宏使用。
- **`depth_limited.rs`** — `deserialize_safe` 防止深层嵌套 JSON DoS:禁用 `serde_json` 递归限制(`unbounded_depth` 特性),流通过 `serde_stacker` 包装为基于堆栈的递归。`MAX_JSON_DEPTH` 常量加 64 MiB 反序列化大小上限和 gzip 魔数头检测加固了该路径。

线上无 base64 往返:值以原始字节传递(可选压缩)。

### 6. 安全模块

**位置**:`src/security/`

**职责**:输入校验和敏感数据脱敏。模块本身为 `pub(crate)` — 调用方必须使用 **crate 根重导出**。

**子模块**:

- `security/validation.rs` - Redis 键、Lua 脚本、SCAN 模式校验
- `security/redaction.rs` - 敏感数据脱敏(`Redacted` 包装器)
- `security/log.rs` - 安全日志工具
- `security/regex.rs` - 模式匹配

**Crate 根重导出**(启用 `redis` 或 `full` 特性时):

```rust
pub use crate::security::{
    clamp_scan_count,
    log::{log_cache_key, sanitize_message},
    redaction::{redact_cache_key, redact_connection_string, redact_field, redact_value, Redacted},
    validate_lua_script, validate_redis_key, validate_scan_pattern,
};
```

> **导入路径说明**:`oxcache::security::*` 是**无效**路径(模块为 `pub(crate)`)。直接使用 `oxcache::validate_redis_key(...)` 等。函数名为 `validate_redis_key`(非 `validate_key`)。安全设计的完整说明见[安全文档](SECURITY.md)。

### 7. 键生成器

**位置**:`src/utils/`

**职责**:缓存键生成和管理。

**关键类型**:

- `KeyGenerator`:用于生成带命名空间和前缀的缓存键的工具(重导出在 `oxcache::KeyGenerator`)

**关键方法**:

- `new()`:创建默认键生成器
- `with_namespace(ns)`:设置命名空间用于键隔离
- `with_prefix_str(prefix)`:设置前缀用于键组织
- `generate(template, params)`:从模板生成键
- `generate_full(template, params)`:使用命名空间和前缀生成键
- `validate_key(key)`:校验键格式

**使用模式**:

```rust
use oxcache::KeyGenerator;

let generator = KeyGenerator::new()
    .with_namespace("myapp")
    .with_prefix_str("cache");

let key = generator.generate_full("user:{id}", &[("id", "123")]);
// 结果:"myapp:cache:user:123"
```

### 8. 事件模块

**位置**:`src/core/events.rs`

**职责**:缓存事件系统,用于监控和钩子。

**关键类型**(重导出在 crate 根):

- `CacheEventType`:事件类型枚举(`Hit`、`Miss`、`Set`、`Delete`、`Expire`、`Clear`、`Get`、`BatchStart`、`BatchEnd`、`Error`、`Connect`、`Disconnect`、`Custom(String)`)
- `CacheEvent`:事件数据结构(builder 模式构造)
- `EventPublisher`:事件发布 trait(提供 `NoopPublisher` 供测试使用)

**`CacheEvent` API**(builder 模式):

```rust
let event = CacheEvent::new(CacheEventType::Hit)
    .with_key("user:123")
    .with_latency(15)
    .with_metadata("source", "l1");
```

字段:`event_type`、`key: Option<String>`、`timestamp: u64`(毫秒)、`latency_ms: Option<u64>`、`error: Option<String>`、`metadata: Vec<(String, String)>`。

### 9. 配置与注册模块

**位置**:`src/config/`、`src/registry.rs`、`src/backend/factory.rs`

- **`config/`**:私有模块(`mod config`),承载分布式参数类型(`DistributedConfig`:重试策略、熔断阈值、健康检查间隔)。公开的配置入口是 `CacheBuilder` 与 `RedisBackendBuilder`;`config-confers` 特性另提供 confers 加载的 `OxcacheConfig`(容量/TTL/熔断参数)与 `ConfigBus` watch 热更新。
- **`registry.rs`**:全局缓存注册表(`init` / `register` / `get` / `remove` / `clear`),供显式管理多个命名缓存实例。
- **`backend::factory`**:`BackendRegistry` 后端工厂注册中心,按名注册/构建后端(内置 moka/dashmap/memory,feature 门控 redis),serde 友好的 `BackendSpec`,供 kit 等动态选择后端。

## 🔀 数据流

### #[cached] 宏执行路径

`#[cached]` 宏通过自动处理缓存查找、存储和序列化实现零模板代码缓存。有效的宏参数为:`service`、`ttl`、`key`、`key_prefix`、`sync`、`skip_cache_write`、`single_flight`、`strict`、`condition`、`cache_none`(不存在 `key_generator` 或 `cache_type` 参数)。

```mermaid
sequenceDiagram
    participant App as 应用
    participant Gen as 宏生成代码
    participant Reg as MACRO_CACHES 注册表
    participant Cache as Cache
    participant BE as CacheBackend

    App->>Gen: 调用被标注函数
    Gen->>Reg: 按服务名查找缓存
    Reg-->>Gen: 返回缓存实例
    Gen->>Gen: 生成缓存键
    Gen->>Cache: get_bytes key
    Cache->>BE: get
    BE-->>Cache: Option bytes
    alt 缓存命中
        Cache-->>Gen: 字节值
        Gen->>Gen: JSON 反序列化
        Gen-->>App: 返回缓存值
    else 缓存未命中
        Gen->>Gen: 执行原函数
        Gen->>Gen: JSON 序列化结果
        Gen->>Cache: set_bytes key bytes ttl
        Cache->>BE: set
        Gen-->>App: 返回函数结果
    end
```

**宏生成代码结构**:

```rust
#[cached(service = "my_service", ttl = 300)]
async fn get_user(id: u64) -> OxCacheResult<User> {
    // ... 原始函数体 ...
}
```

展开后大致为:

```rust
async fn get_user(id: u64) -> OxCacheResult<User> {
    let cache_key = format!("my_service:get_user:{:?}", id);

    // 从注册表获取缓存(同步查找)
    let client = match oxcache::__internal_get_cache("my_service") {
        Some(c) => c,
        None => return { /* 原始代码 */ }.await,
    };

    // 尝试缓存命中(JSON 反序列化为 User)
    if let Ok(Some(bytes)) = client.get_bytes(&cache_key).await {
        if let Ok(val) = serde_json::from_slice::<User>(&bytes) {
            return Ok(val);
        }
    }

    // 执行原始函数
    let result = { /* 原始代码 */ }.await;

    // 成功时缓存结果
    if let Ok(ref val) = result {
        if let Ok(bytes) = serde_json::to_vec(val) {
            let _ = client.set_bytes(&cache_key, bytes, Some(Duration::from_secs(300))).await;
        }
    }

    result
}
```

未注册服务时默认静默穿透执行原函数,`strict` 模式改为 panic;`condition` 谓词返回 false 时旁路缓存。

### ChainCache 读取路径

```mermaid
flowchart TD
    A["Cache 读请求"] --> B["ChainCache 从最高分链接开始"]
    B --> C{"最高分链接命中?如 L1 Moka"}
    C -->|命中| D["返回值"]
    C -->|未命中或出错| E{"下一个链接命中?如 L2 Redis"}
    E -->|命中| F{"已启用回填?"}
    F -->|是| G["异步回填更高分链接"]
    F -->|否| D
    G --> D
    E -->|未命中或出错| H["返回 None"]
```

读取、写入与回填的逐步语义(含 `enable_race_read()` 竞速读取)见[后端层的 ChainCache 路径](#3-后端层)。

### 写操作(配合 #[cached] 宏)

```mermaid
flowchart TD
    A["应用<br/>cached 函数"] --> B["执行函数"]
    B --> C{"结果 Ok?"}
    C -->|否| D["返回错误"]
    C -->|是| E["序列化结果"]
    E --> F["set_bytes 到缓存<br/>带 TTL"]
    F --> L["返回结果"]
```

> **说明**:`#[cached]` 在注册的 `Cache<String, Vec<u8>>` 上调用 `set_bytes`,由其分发到所接入的后端(内存、Redis、ChainCache 或 BloomFilterBackend)。如果后端是 `ChainCache`,链按分数/回填策略内部处理 L1+L2 写入。

## 📐 一致性模型

### 单实例一致性

在单个 `Cache<K, V>` 实例内,配置的后端决定一致性:

- **仅 Moka / DashMap**:进程内强一致性。无跨实例协调。
- **仅 Redis**:通过 Redis 单线程命令执行实现强一致性。
- **ChainCache(Moka + Redis)**:进程内读后写一致性。L1 缓存同步更新;L2(Redis)写入在 `set` 返回前完成。如启用回填,L2 命中会异步填充 L1。

### 跨实例一致性

默认配置下,oxcache **不**自动做跨实例 L1 失效,多实例一致性由应用负责。两种路径:

**内建路径(`invalidation` 特性)**:

- Redis Pub/Sub 广播失效事件(key / namespace 粒度),各实例后台监听并失效本地 L1;消息带 `instance_id`,写实例自身免除自失效
- `KeyspaceNotificationListener` 键空间通知第二通道:把外部 `DEL`/`EXPIRED` 投影为本地失效(需 Redis `notify-keyspace-events "Egx"`)
- `InvalidatingBackend` 写路径装饰器透明接入

**应用自管路径**(不启用该特性时):

- 使用 Redis 作为唯一真实来源(跳过 L1,或接受 L1 的短暂过期数据)
- 使用短 L1 TTL 限制数据过期程度
- 应用外部失效(如 Redis keyspace 通知、应用层 Pub/Sub)并在每个实例上调用 `cache.delete(key)`

对读-改-写竞争,`versioning` 特性提供 `compare_and_swap(key, expect_version, new_value)`(内存实现 + Redis WATCH/MULTI/EXEC 实现)。

### 单飞(缓存击穿保护)

`get_or`(异步)和 `get_or_sync`(同步)都实现单飞:当多个并发调用未命中同一键时,仅第一个调用者("领导者")执行 fallback;跟随者在 `tokio::sync::Notify`(异步)或 `std::sync::Condvar`(同步)上阻塞,直到领导者写入结果。panic 安全守卫确保即使领导者 panic 跟随者也能被释放。

飞行中注册表**分片**(64 个哈希桶通过 `DefaultHasher`)以减少并发下跨键锁竞争:`get_or_shard_index(key)` 将每个键路由到一个分片,每个分片拥有 `Mutex<HashMap<String, Arc<Notify>>>`(异步)/ `Mutex<HashMap<String, SyncFlight>>`(同步)。

## 🧯 故障处理

### Redis 故障

**检测**(通过 `CacheConnector::health_check()`):

- 连接超时 / 拒绝
- `PING` 失败
- 连接被远端关闭

**恢复(应用驱动 + 可选自动降级)**:

1. `Cache::health_check().await` 返回 `Err(OxCacheError::*)` — 调用方可切换到回退代码路径
2. `ChainCache` 即使 L2 链接报错仍继续提供 L1 命中(未命中仅传播为 `None`);L1 读取错误被记录并穿透到下一链接;L2 写入失败被记录,仅当所有后端都失败时写入才向调用方报错
3. **`degradation` 特性**:`DegradableBackend` 保护 L2,故障计数超阈值自动降级为 L1-only(返回 `Degraded` 错误供 ChainCache 回落),降级超时后进入半开探测,探测成功自动恢复、失败重新降级;状态变化回调 + 全局 degraded 指标
4. 应用也可以在缓存外包裹自己的熔断器/重试策略

重连后无 WAL 重放机制(WAL 层不存在于当前代码库)。

### 网络分区

- 每个实例继续使用本地 L1 缓存运行
- Redis 写入/读取将失败并表现为 `Err(OxCacheError::*)`
- 恢复后无自动数据协调,应用可发出 `cache.clear()` 或依赖 TTL 过期;启用 `invalidation` 时,恢复后的写事件会继续经 Pub/Sub 驱动各实例失效

### 后端 Trait 错误

所有后端错误通过 `OxCacheError` 传递(参见 `src/error.rs`)。完整错误码表(OXCACHE_001–OXCACHE_024)见 [API 参考](API_REFERENCE.md#-错误处理)。关键变体:

| 错误码 | 变体 | 含义 |
|--------|------|------|
| OXCACHE_001 | `NotFound` | 键未找到 |
| OXCACHE_002 | `Connection` | 网络连接失败 |
| OXCACHE_003 | `Serialization` | 序列化/反序列化失败 |
| OXCACHE_005 | `Degraded` | 缓存处于降级模式 |
| OXCACHE_007 | `L2Error` | L2(Redis)后端错误 |
| OXCACHE_009 | `NotSupported` | 此后端/配置不支持的操作 |
| OXCACHE_015 | `Timeout` | 操作超时 |
| OXCACHE_020 | `InvalidInput` | 错误的键/值/配置输入 |

## ⚡ 性能优化

### 优化技术

1. **Moka 单条目 TTL**:使用 `moka::Expiry` trait 实现真正的单条目 TTL(覆盖构建器的全局 TTL),避免独立过期跟踪的开销。
2. **连接池**:`RedisBackend::with_pool(url, pool_size)` 复用 Redis 连接。
3. **Pipeline / 批量操作**:`RedisBackend` 支持通过 Redis pipeline 的 `set_many` / `delete_many` / `get_many`(默认 trait 实现循环,但 `RedisBackend` 覆盖它们)。`batch` 特性添加 `BatchWriter` 缓冲 L2 写入(容量/时间双阈值刷盘)。
4. **无锁 L1**:Moka 的并发缓存设计(TinyLFU 准入、LRU 淘汰)。
5. **可插拔序列化**:默认 JSON;`serde-bincode` / `postcard` 二进制格式可显著降低 L2 传输体积(见[性能基线](PERFORMANCE.md))。`MAX_JSON_DEPTH` 常量防止深层嵌套 JSON DoS。
6. **自适应压缩**:`compression` 特性的 `CompressingBackend` 按阈值触发 zstd,读取按魔数识别并兼容旧 gzip。
7. **单飞**:`get_or` / `get_or_sync` 对每键的并发 fallback 执行去重,防止缓存击穿惊群效应。
8. **布隆过滤器短路**:`BloomFilterBackend` 在键不在过滤器中时直接返回 `Ok(None)` 而不触及内部后端,适用于高负查询比工作负载。
9. **热路径借用键 API**:`get_by_str` / `set_by_str` 消除热路径上的多余分配(实测 get -6.7%、set -12.7%,见[性能基线](PERFORMANCE.md))。

### 性能调优

```rust
use std::time::Duration;
use oxcache::Cache;

let cache: Cache<String, User> = Cache::builder()
    .capacity(10_000)              // L1 最大条目数
    .ttl(Duration::from_secs(600)) // 默认 TTL
    .tti(Duration::from_secs(300)) // 空闲 TTL(Moka)
    .build()
    .await?;

// Redis 连接池大小:
let redis = oxcache::backend::RedisBackend::with_pool(
    "rediss://localhost:6379", 16,
).await?;
```

### 基准测试结果

> 测试环境:M1 Pro,16GB RAM,macOS,Redis 7.0
>
> **注意**:性能因硬件、网络条件和数据大小而异。将这些视为数量级估计。

| 操作 | 吞吐量 | 延迟(P99) |
|------|--------|-------------|
| L1 读取 | 5-10M ops/sec | 50-100ns |
| L1 写入 | 2-5M ops/sec | 50-200ns |
| L2 读取 | 50-100K ops/sec | 1-5ms |
| L2 写入(批量) | 200-500K ops/sec | 1-10ms |

可复现的实测数据(序列化体积、压缩率、热路径 Criterion 基准)见[性能基线](PERFORMANCE.md)。

## 🔒 安全

### 威胁模型

1. **缓存穿透**:攻击者请求不存在的键 → 加载数据库
2. **缓存击穿**:热点键过期,大量请求同时打到数据库
3. **DoS 攻击**:高请求率压垮系统
4. **SQL 注入**:Redis 键中的恶意模式
5. **Lua 脚本注入**:Lua 脚本中的危险命令
6. **ReDoS**:恶意 SCAN 模式导致 CPU 耗尽
7. **深层嵌套 JSON DoS**:恶意 JSON 在反序列化时导致栈溢出

### 防御措施

上述威胁由多层防御缓解:单飞与空值哨兵/TTL 抖动(穿透与击穿防护)、`validate_redis_key` / `validate_lua_script` / `validate_scan_pattern` / `clamp_scan_count` 输入校验(含注释预处理防绕过)、`Redacted` 与 `redact_*` 系列脱敏、`MAX_JSON_DEPTH` + 64 MiB 上限 + 基于栈的递归、TLS 强制、`encrypt` / `integrity` 值保护。各机制的完整规则与配置摘要见[安全文档](SECURITY.md),README 安全章节提供防线速览。

> **注意**:oxcache **无内置限流**。限流由应用或上游代理负责。

### 布隆过滤器穿透防护

`bloom` 特性的 `BloomFilterBackend` 在负查询到达内部后端前短路返回;机制图解、示例与穿透防护组合表见 [README 布隆过滤器章节](../README.md#-布隆过滤器与穿透防护)。

### 输入校验

`security` 模块(私有;通过 crate 根重导出消费,见 [API 参考](API_REFERENCE.md#-安全特性))提供 `validate_redis_key` / `validate_lua_script` / `validate_scan_pattern` / `clamp_scan_count`,逐条校验规则与常量见[安全文档](SECURITY.md)。

### 最佳实践

1. **键设计**:使用稳定、可预测的键(使用 `KeyGenerator` 进行命名空间管理)
2. **TTL 策略**:根据数据易变性设置适当的 TTL;使用 `cache.ttl(&key)` 在保留 TTL 的更新工作流中读取已有 TTL
3. **访问控制**:使用 Redis AUTH + TLS(`rediss://` URL)
4. **监控**:通过 `get_enhanced_stats` / `export_prometheus_format` 跟踪 `CacheStats`(命中率、操作计数器、延迟直方图)
5. **同步 API**:为非异步调用场景启用 `sync_mode(true)`。在 `multi_thread` tokio 运行时上,Moka 的同步桥通过 `block_in_place` 复用当前运行时;否则它用 `noop` waker + 手动轮询驱动(运行时无关的)moka future,在任何运行时内外都安全,无全局运行时线程

## 📈 可扩展性

### 水平扩展

```mermaid
flowchart TD
    subgraph 应用实例
        I1["实例 1<br/>L1 Moka + L2 Redis"]
        I2["实例 2<br/>L1 Moka + L2 Redis"]
        I3["实例 3<br/>L1 Moka + L2 Redis"]
    end

    subgraph Redis层
        R["Redis 集群<br/>共享 L2"]
    end

    I1 --> R
    I2 --> R
    I3 --> R
```

每个实例维护自己的 L1(Moka)并共享 L2(Redis)。跨实例 L1 失效默认不自动,启用 `invalidation` 特性后经 Redis Pub/Sub 广播失效(参见[一致性模型](#-一致性模型))。

### 垂直扩展

- 通过 `CacheBuilder::capacity(u64)` 增加 L1 容量(更多内存)
- 使用更快/专用的 Redis 实例
- 在 Redis 端启用 Redis 持久化(AOF + RDB)
- 通过 `RedisBackend::with_pool(url, pool_size)` 增加 Redis 连接池

### 分区

oxcache 不内置分区配置。应用可以通过将键路由到不同的 `Cache<K, V>` 实例(每个由不同的 Redis db / 集群支持)实现自己的分区;`TypedNamespace`(marker 类型 + `namespace!` 宏)提供编译期命名空间隔离。

## 🎨 特性标志

分层特性集(`minimal` / `core` / `full` 预设)与组件特性逐项说明见 [API 参考的特性要求](API_REFERENCE.md#-特性要求) 与 [README 特性标志](../README.md#-特性标志)。`bloom`、`kit` 及其余选择加入特性**不包含**在 `full` 中,需通过 `features = ["bloom"]` 等显式启用;`full` 的精确成员见 `Cargo.toml` 的 `[features]`。

## 🔮 未来增强

1. **自适应 TTL**:基于访问模式的 TTL 优化启发式
2. **地理分布**:多区域复制原语
3. **缓存预热**:智能预热策略
4. **`trait_upcasting` 迁移**:stable 后解除 `sync_mode + backend_arc` 互斥限制,使用户能注入自定义后端并同时使用同步 API

## 📚 参考资料

- [Moka 文档](https://github.com/moka-rs/moka)
- [Redis 文档](https://redis.io/docs/)
- [TinyLFU 论文](https://arxiv.org/abs/1512.00757)
- [布隆过滤器](https://en.wikipedia.org/wiki/Bloom_filter)
- [ISP 合规 trait 设计](https://en.wikipedia.org/wiki/Interface_segregation_principle)
- [📘 API 参考](API_REFERENCE.md) / [📖 用户指南](USER_GUIDE.md) / [📊 性能基线](PERFORMANCE.md)