总结自https://coolshell.cn/articles/17416.html
缓存和数据库的同步机制,一般有几种固定的套路。
程序自己保证一致性
程序中自己控制缓存和数据库的更新过程,保证缓存的数据和数据库保持一致。更新的时候,一般是通过控制更新和访问缓存还有数据库的顺序。先更新数据库,再将缓存设为实效,后续的读请求再来更新缓存。
- Cache Aside Pattern
由缓存服务保证一致性
通过一个缓存的服务,使用缓存的应用直接通过缓存去做数据操作,缓存和数据库的数据一致性交给缓存服务内部处理。缓存数据保证和数据库一致性的机制,一般借鉴了操作系统同步缓存和内存的机制:
- Read/Write Through Pattern
- Write Behind Caching Pattern
几种机制的图解
Cache Aside Pattern
Cache Aside Pattern 就是由调用方将新数据加载到cache。
sequenceDiagram
loop read data
application->>cache: try to read data from cache
cache->>application: not fount in the cache
application->>db: updata data from db to cache
db->>cache: update data in the cache
cache->>application: response data
end
loop write data
application->>db: update data in the db
db->>cache: invalid item in the cache
cache->>cache: waiting for next read request to reload the cache
end
不在更新数据库后,继续更新缓存中的数据,是为了防止多线程更新的时候,向缓存中写入脏数据。并为缓存设置失效时间。
Read Through Pattern
Read Through Pattern 就是在查询中,由缓存服务自己将新数据加载到cache
sequenceDiagram
application->>cache service: read data from cache
cache service->>cache service: not hit
cache service->>db: read data from db
db->>cache service: updata data in the cache
cache service->>application: response data
Write Through Pattern
Write Through Pattern 就是在更新数据的时候:
- 如果没有命中,cache service将更新请求发给db,直接更新数据库。
- 如果命中,先更新cache,然后由cache service自己更新数据库。
sequenceDiagram
loop not hit
application->>cache service: request update data
cache service->>cache service: not hit
cache service->>db: update data in the db
end
loop hit
application->>cache service: request update data
cache service->>cache service: hit item
cache service->>cache service: udpate data in the cache
cache service->>db: update data in the db
end
wiki上关于memery的一个活动图,可以作为Read/Write Through Pattern的实现参考
graph TD
A[Memory request] --> B{Request type}
B --> |Read| C[Cache hit?]
C --> |No| E[Locate a cache block to use]
E --> F[Read data from lower memory into the cache block]
F --> G[Return data]
G --> H[Done]
C --> |Yes| G
B --> |Write| D[Cache hit?]
D --> |No| I[Write data into lower memory]
I --> H
D --> |Yes| J[Write data into cache block]
J --> I
Write Behind Caching Pattern
Write Back套路,一句说就是,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。
wiki上的活动图以供参考
graph TD
MEM[Memory request] --> RT[Request type]
RT --> |Read| Read{Cache hit?}
Read --> |No| RLocate[Locate a cache block to use]
RLocate --> RDirty{Is it dirty?}
RDirty --> |No| R2C[Read data from lower memory into the cache block]
RDirty --> |Yes| R2M[Write cache block previouse data back to the lower memory]
R2M --> R2C
R2C --> MND[Mark the cache block as 'not dirty']
MND --> RE[Return data]
Read --> |Yes| RE
RE --> DONE
RT --> |Write| Write{Cache hit}
Write --> |No| WLocate[Locate a cache block to use]
WLocate --> WDirty{Is it dirty}
WDirty --> |No| W2C[Read data from lower memory into the cache block]
WDirty --> |Yes| W2M[Write cache block previouse data back to the lower memory]
W2M --> W2C
W2C --> WN2C[Write the new data into the cache block]
WN2C --> MD[Mark the cache block as 'dirty']
Write --> WN2C
MD --> DONE