總結(jié)自https://coolshell.cn/articles/17416.html
緩存和數(shù)據(jù)庫的同步機(jī)制,一般有幾種固定的套路。
程序自己保證一致性
程序中自己控制緩存和數(shù)據(jù)庫的更新過程,保證緩存的數(shù)據(jù)和數(shù)據(jù)庫保持一致。更新的時(shí)候,一般是通過控制更新和訪問緩存還有數(shù)據(jù)庫的順序。先更新數(shù)據(jù)庫,再將緩存設(shè)為實(shí)效,后續(xù)的讀請求再來更新緩存。
- Cache Aside Pattern
由緩存服務(wù)保證一致性
通過一個(gè)緩存的服務(wù),使用緩存的應(yīng)用直接通過緩存去做數(shù)據(jù)操作,緩存和數(shù)據(jù)庫的數(shù)據(jù)一致性交給緩存服務(wù)內(nèi)部處理。緩存數(shù)據(jù)保證和數(shù)據(jù)庫一致性的機(jī)制,一般借鑒了操作系統(tǒng)同步緩存和內(nèi)存的機(jī)制:
- Read/Write Through Pattern
- Write Behind Caching Pattern
幾種機(jī)制的圖解
Cache Aside Pattern
Cache Aside Pattern 就是由調(diào)用方將新數(shù)據(jù)加載到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
不在更新數(shù)據(jù)庫后,繼續(xù)更新緩存中的數(shù)據(jù),是為了防止多線程更新的時(shí)候,向緩存中寫入臟數(shù)據(jù)。并為緩存設(shè)置失效時(shí)間。
Read Through Pattern
Read Through Pattern 就是在查詢中,由緩存服務(wù)自己將新數(shù)據(jù)加載到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 就是在更新數(shù)據(jù)的時(shí)候:
- 如果沒有命中,cache service將更新請求發(fā)給db,直接更新數(shù)據(jù)庫。
- 如果命中,先更新cache,然后由cache service自己更新數(shù)據(jù)庫。
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上關(guān)于memery的一個(gè)活動(dòng)圖,可以作為Read/Write Through Pattern的實(shí)現(xiàn)參考
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套路,一句說就是,在更新數(shù)據(jù)的時(shí)候,只更新緩存,不更新數(shù)據(jù)庫,而我們的緩存會(huì)異步地批量更新數(shù)據(jù)庫。
wiki上的活動(dòng)圖以供參考
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