Skip to content

CoCache 介绍

CoCache 是一个面向 Java/Kotlin 的二级分布式一致性缓存框架,提供基于事件驱动一致性的两级缓存架构。它以 me.ahoo.cocache 为组织标识发布,当前版本为 4.0.2

CoCache 位于应用与数据源之间,增加两层缓存 -- 本地内存 L2 缓存(Guava 或 Caffeine)和共享的分布式 L1 缓存(Redis) -- 同时通过事件总线保持所有实例间的缓存一致性。

三级缓存概念

CoCache 实现了三级数据访问模型:

层级名称位置用途源码
L2客户端缓存进程内(Guava / Caffeine)最快访问,每实例独立cocache-api/.../client/ClientSideCache.kt
L1分布式缓存共享(Redis)跨实例一致性cocache-api/.../distributed/DistributedCache.kt
L0数据源原始数据(数据库、API)权威数据来源cocache-api/.../source/CacheSource.kt
mermaid
graph TB
    subgraph Application
        direction TB
        Caller["Caller<br>cache.get(key)"]
    end

    subgraph sg_20 ["L2 - Client-side Cache"]
        direction TB
        L2["Guava / Caffeine<br>In-process Memory"]
    end

    subgraph sg_21 ["L1 - Distributed Cache"]
        direction TB
        L1["Redis<br>Shared across instances"]
    end

    subgraph sg_22 ["L0 - DataSource"]
        direction TB
        L0["Database / API<br>Authoritative Source"]
    end

    Caller --> L2
    L2 -->|"cache miss"| L1
    L1 -->|"cache miss"| L0
    L0 -->|"return data"| L1
    L1 -->|"populate"| L2

    style Caller fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L2 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L0 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
mermaid
graph LR
    subgraph sg_23 ["Instance A"]
        L2A["L2 Cache<br>ClientSideCache"]
    end
    subgraph sg_24 ["Instance B"]
        L2B["L2 Cache<br>ClientSideCache"]
    end
    subgraph sg_25 ["Shared"]
        L1["L1 Cache<br>Redis"]
        EB["Event Bus<br>Redis Pub/Sub"]
    end

    L2A --> L1
    L2B --> L1
    L1 -->|"CacheEvictedEvent"| EB
    EB -->|"invalidate"| L2A
    EB -->|"invalidate"| L2B

    style L2A fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L2B fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style EB fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

核心特性

特性说明源码
二级缓存L2(本地)+ L1(分布式),配合细粒度锁DefaultCoherentCache.kt:89-135
事件驱动一致性CacheEvictedEventBus 实现分布式缓存失效CacheEvictedEventBus.kt
注解驱动配置@CoCache@GuavaCache@CaffeineCache@JoinCacheablecocache-api/.../annotation/
JoinCache将多个缓存值组合为单一结果JoinCache.kt
缓存击穿防护逐键同步锁防止惊群效应DefaultCoherentCache.kt:78-86
缓存穿透防护MissingGuard 缓存空值,防止重复击穿数据库MissingGuard.kt
布隆过滤器可选的布隆过滤器阻止对不存在键的查询BloomKeyFilter.kt
TTL 抖动随机 TTL 幅度防止缓存雪崩ComputedTtlAt.kt:49-56
代理式缓存运行时通过动态代理实现缓存接口CoCacheProxy.kt
Spring Boot Starter自动配置与条件化 Bean 注册CoCacheAutoConfiguration.kt:61-186

架构概览

mermaid
graph TB
    subgraph sg_26 ["Spring Boot Application"]
        direction TB
        EnableCoCache["@EnableCoCache<br>caches = [UserCache::class]"]
        UserCache["UserCache Interface<br>@CoCache + @GuavaCache"]
        Proxy["CoCacheProxy<br>InvocationHandler"]
    end

    subgraph sg_27 ["CoCache Core"]
        direction TB
        CoherentCache["DefaultCoherentCache<br>L2 + L1 + Event"]
        KeyConverter["KeyConverter<br>key -> cacheKey"]
        MissingGuard["MissingGuard<br>null value protection"]
    end

    subgraph sg_28 ["L2 - Client Side"]
        direction TB
        Guava["GuavaClientSideCache"]
        Caffeine["CaffeineClientSideCache"]
        Map["MapClientSideCache"]
    end

    subgraph sg_29 ["L1 - Distributed"]
        direction TB
        Redis["RedisDistributedCache"]
    end

    subgraph sg_30 ["Coherence"]
        direction TB
        EventBus["CacheEvictedEventBus<br>Redis Pub/Sub"]
    end

    EnableCoCache --> UserCache
    UserCache --> Proxy
    Proxy --> CoherentCache
    CoherentCache --> KeyConverter
    CoherentCache --> MissingGuard
    CoherentCache --> Guava
    CoherentCache --> Caffeine
    CoherentCache --> Map
    CoherentCache --> Redis
    CoherentCache --> EventBus

    style EnableCoCache fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style UserCache fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Proxy fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CoherentCache fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style KeyConverter fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style MissingGuard fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Guava fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Caffeine fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Map fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style Redis fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style EventBus fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

缓存流转

mermaid
sequenceDiagram
autonumber
    participant Caller as Caller
    participant L2 as L2 Cache
    participant KeyFilter as KeyFilter
    participant L1 as L1 Redis
    participant Lock as KeyLock
    participant L0 as DataSource
    participant EventBus as EventBus

    Caller->>L2: get(key)
    alt L2 hit
        L2-->>Caller: CacheValue
    else L2 miss
        L2-->>Caller: null
        Caller->>KeyFilter: notExist(key)?
        alt key definitely not exist
            KeyFilter-->>Caller: MissingGuard (null)
        else key may exist
            Caller->>L1: getCache(key)
            alt L1 hit
                L1-->>Caller: CacheValue
                Caller->>L2: setCache(key, value)
            else L1 miss
                Caller->>Lock: synchronized(lock)
                Lock->>L2: getCache(key) [double-check]
                Lock->>L1: getCache(key) [double-check]
                Lock->>L0: loadCacheValue(key)
                L0-->>Lock: CacheValue or null
                alt value found
                    Lock->>L2: setCache(key, value)
                    Lock->>L1: setCache(key, value)
                    Lock->>EventBus: publish(CacheEvictedEvent)
                else value not found
                    Lock->>L2: setCache(key, MissingGuard)
                    Lock->>L1: setCache(key, MissingGuard)
                end
                Lock-->>Caller: CacheValue or null
            end
        end
    end

模块架构

模块说明源码
cocache-api核心接口(CacheCacheValueClientSideCacheCacheSourcecocache-api/
cocache-core默认实现(DefaultCoherentCache、代理式缓存)cocache-core/
cocache-springSpring 集成(@EnableCoCache、FactoryBean)cocache-spring/
cocache-spring-redisRedis 分布式缓存实现cocache-spring-redis/
cocache-spring-cacheSpring Cache 抽象桥接cocache-spring-cache/
cocache-spring-boot-starterSpring Boot 自动配置cocache-spring-boot-starter/
cocache-test共享测试规范(TCK)cocache-test/
cocache-example示例应用cocache-example/
cocache-bomBill of Materialscocache-bom/
cocache-dependencies集中式版本目录cocache-dependencies/

项目信息

属性源码
Groupme.ahoo.cocachegradle.properties:14
Version4.0.2gradle.properties:15
LicenseApache License 2.0gradle.properties:23
JDK17+(通过 jvmToolchainbuild.gradle.kts
Gradle9.4.1(wrapper)gradle/wrapper/gradle-wrapper.properties

快速示例

kotlin
// 1. 定义缓存接口
@CoCache(keyPrefix = "user:", ttl = 120)
@GuavaCache(
    maximumSize = 1_000_000,
    expireUnit = TimeUnit.SECONDS,
    expireAfterAccess = 120
)
interface UserCache : Cache<String, User>

// 2. 启用缓存
@EnableCoCache(caches = [UserCache::class])
@SpringBootApplication
class AppServer

// 3. 使用缓存
@RestController
class UserController(private val userCache: UserCache) {
    @GetMapping("{id}")
    fun get(@PathVariable id: String): User? = userCache[id]
}

相关页面

基于 Apache License 2.0 发布。