Documentation v1.0.0

Normal-Mode Read

This page explains which tiers Get checks in normal mode, when it treats Redis as failed, and how it degrades within the same call.

Flow

graph TB
    Start[Get key] --> R1{Memory hit?}
    R1 -->|Hit, valid| Hit[Return Data, write back to Redis in background]
    R1 -->|Hit, expired| Exp[Delete memory and file, return Not found]
    R1 -->|Miss| R2[redis.Get up to MaxRetry times]
    R2 -->|OK and parses as Cache| Store[Store in memory and return]
    R2 -->|All failed| Switch[Switch to fallback mode]
    Switch --> Local[Continue on the fallback read path]

Steps

Step Condition Behavior Source
1 Memory hit, not expired Return immediately and write back to Redis in a goroutine (Read-Repair) get.go:24-37
2 Memory hit, expired Delete the memory entry and the local JSON file, return Not found get.go:28-33
3 Memory miss Run GET against Redis up to MaxRetry times (default 3); on a parseable result, store in memory and return get.go:39-50
4 Retries exhausted Take the write lock, switch to fallback mode (starting the health check), release the lock, then call the Fallback-Mode Read get.go:52-58

Memory First

In normal mode the memory cache takes precedence over Redis. For any key this instance has written or read, Get returns the in-memory value without asking Redis again, so a key changed or deleted externally in Redis still reads as the old value here until it expires.

Retry Behavior

Item Behavior
Interval No wait between attempts
Per-attempt timeout go-redis client defaults (the instance only sets Addr / Password / DB)
Counted as failure Connection errors, redis.Nil (key missing), a value that does not parse as the Cache structure

Which Values Read Back from Redis

Step 3 parses the Redis value into the Cache structure (key / data / type / timestamp / ttl) with json.Unmarshal, but Set writes only the JSON of Data itself to Redis (strings have their quotes trimmed). Observed results:

Scenario Result
Set then Get on the same instance Memory hit, returns normally
Another instance (or after a restart) calls Get for the same key Parse fails → switch to fallback → no local file → Not found
Get for a missing key redis.Nil → switch to fallback → Not found

The last two cases take the instance out of normal mode until the health check's next successful ping completes recovery. See Known Limitations.

Example

value, err := rf.Get("user:1")
if err != nil {
    // key missing, expired, or the local file failed to parse
    log.Println(err)
    return
}
fmt.Println(value)

Get returns only two error messages, Not found and Failed to parse; it never returns a Redis connection error.

中文