Kv缓存用法指南
8-27 kv緩存初步學習
一、理解業務中的使用緩存優勢
舉個簡單的例子,我們可以類比去圖書館看書。
沒有使用緩存的情況
當我們想要查看某本書的時候(查看數據庫的記錄),需要先去圖書館找到這本書所在的類目(記錄存在的表),然后再找到這本書,看一會后再把這本書還回去。
但是如果有幾本我們常看的數,我們每次看都要去圖書館取,取完了再放回去太麻煩。
使用緩存的情況
當我們想要查看某本書的時候(查看數據庫的記錄),需要先去圖書館找到這本書所在的類目(記錄存在的表),然后再找到這本書,把這本書借回去放到自己的書架上。
這樣做我們可以對一些我們頻繁閱讀的書籍放在觸手可及的書架上,大大節約了時間成本。
- 就像書架(redis占據的內存)和圖書館(數據庫占據的磁盤)一樣,書架的資源和空間非常的寶貴,因此一些不必要的書籍沒有必要放在書架(redis中)上。
- 就像去圖書館和用手拿書一樣,內存的讀取速度時磁盤的500-1000倍,當我們需要對一些熱點數據訪問的時候,大大節約了時間成本。
總結:redis緩存是一種key-value緩存數據庫,是對數據庫頻繁訪問的某些熱點字段的一種優化方案。
二、搭建kv緩存使用環境
kv是把熱點數據作為Key-Value形式存儲的一種
2.1 連接redis服務器
2.2 引入jedis客戶端
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency>2.3 引入Kv緩存框架
- 引入所需要的包
三、使用Kv緩存框架
3.1 通過kv工廠創建 特定kvCacheWrapper(服務包裝接口)
kv緩存框架采用的是工廠設計模式創建指定存儲的kvCacheWrapper
當然,這些CacheWrapper我們需要隨著spring的啟動而被創建(就像Repository一樣),因此我們需要指定在springbean初始化的時候對其進行創建。@PostConstruct注解下的方法可以在spring加載這個類的時候自動調用。
首先,我們通過依賴注入的方式引入KvCacheFactory。
@Autowiredprivate KvCacheFactory kvCacheFactory;接著,在初始化方法下通過kvCacheFactory.create()創建特定的kvCacheWrapper接口
在創建之前,先來了解一下KvCacheFactory.created()所需的參數
- CacheOptions:緩存配置項。(key:redis某一類數據的標識,相當于mysql中的表明。version:版本號。expireIn:每條緩存記錄的時限。)
- RepositoryProvider:持久層的支持(這里支持我們訪問數據庫)。我們需要實現兩個方法
-
findByKey是指定,我們通過什么類型的key來獲取緩存中的value,當然這里也意味著我們存數據的時候key與這個類型一致,這個約定是在keyWrapper中約定的。 - ModelConverter:模型和json的轉換,這里寫我們需要存取數據的model模型,當我們在存取的時候參與轉換。
比如說我們這里創建一個User的緩存接口。
@PostConstructpublic void init(){userCache = kvCacheFactory.create(new CacheOptions("user", 1, DateUtils.SECOND_PER_DAY),new RepositoryProvider<Long, User>() {@Overridepublic User findByKey(Long key) throws Exception{return repository.findById(key).orElse(null);}@Overridepublic Map<Long, User> findByKeys(java.util.Collection<Long> keys) throws Exception{return repository.findByIdIn(keys).stream().collect(Collectors.toMap(User::getId, t -> t));}}, new BeanModelConverter<>(User.class)); }3.2 使用cacheWrapper
通過查看KvCache接口我們可以查看它的所有用法
public interface KvCache<K, T> {// 只從緩存中查找,如果緩存中沒有,則返回null(不進入數據庫)。T findByKey(K key, boolean cacheOnly);// 先從緩存中查找,如果緩存中沒有進入數據庫中查找,找到后緩存到redis中。T findByKey(K key);// 同上Map<K, T> findByKeys(Collection<K> keys, boolean cacheOnly) throws KvCacheException;// 同上Map<K, T> findByKeys(Collection<K> keys) throws KvCacheException;// 保存到緩存中void save(K key, T value) throws KvCacheException;// 批量保存void saveMany(Map<K, T> items) throws KvCacheException;// 刷新緩存(重新加載內容,寫入緩存并返回)T refresh(K key) throws Exception;// 從緩存中刪除void remove(K key) throws KvCacheException;// 根據prefix清理全部數據(這個prefix是我們在配置Policy配置的)void flush() throws KvCacheException;}Policy策略
policy默認的為我們提供了一些策略
- 過期時間使用的是我們在CacheOption中配置的過期時間
- 前綴策略(供定制批量刪除策略):是我們的 CacheOption中key(也就是redis的表明)+:+版本號+:組成的,比如 admin:1:xxx
flush()
通過前綴策略,批量刪除某個數據組的某個版本的所有數據。
因為我們在通過工廠create cacheWrapper的時候,我們自動在這里的前綴策略默認使用的是:“組名:版本號:”
flush源碼:
3.3 如何使用緩存
因為內存資源的珍貴,我們并不能任意的緩存數據庫記錄到緩存中,如何合理的使用緩存在業務中至關重要。
- 是否從緩存中獲取的模型有被禁止序列化的字段,如果需要用到這些字段應該從數據庫中直接查詢
- 修改和刪除數據庫記錄的時候要注意及時清除臟數據(刪除緩存信息,下一次訪問該緩存信息的時候直接在從數據庫中查詢最新數據),避免臟讀
- 緩存的session字段,如果過期了也要及時清除:(可以設置緩存過期時間跟session過期一樣的時間,因為在用戶初次登錄產生session的時候,就會把session緩存起來(通過token獲取wrapper的時候),讓兩者的存在時間保持同步)
總結
- 上一篇: 无线路由器的基础配置(三)
- 下一篇: 基于OAI-PMH的元数据搜索引擎的设计