前言:
手上的專案有一些數值經常需要修改
例如wallet表的balance
主要是一些設計缺陷吧,容易出現死鎖,就算沒鎖,也會很慢
一個坑需要反覆填
就想直接做一個侵入性比較小的,不需要太多改動原始碼的外掛
能夠將Model的指定屬性進行快取,並且所有更改只在快取裡更改
等沒事了,統籌一下再一起儲存到資料庫
於是就有了這個專案
然後本人其實基礎不咋地,所以有什麼問題希望大家能夠多多幫助
然後如果這玩意是有前人的肩膀可以站,請告訴我,我就不用那麼累寫半天,阿里嘎多
Github
https://github.com/light-speak/laravel_model_cache
安裝
composer require linty/laravel_model_cache
說明
本外掛全部用的Cache, Cache使用的Redis儲存 功能為,對某個模型的物件的某個欄位進行代理,使用Cache維護 一段時間(暫時為10分鐘)內的修改全部在Cache進行, 以此優化效能
使用
- 佇列新增一個queue,名稱為:model-cache ,用於維護欄位, 當模型第一次被建立快取時,會建立一個延時10分鐘的Job,10分鐘後(或者更久)進行資料庫儲存操作
- 在需要使用的Model類使用:
這時候模型的use ModelCacheTrait;
getAttributeFromArray
方法就會被攔截, 進行一些快取讀取的操作 - 在原來的模型後面增加->cache(), 例如
$wallet = Wallet::query()->first()->cache();
- 如果需要事務,則:
$wallet = Wallet::query()->first()->cache(true);
此功能僅在屬性為數值型時有效,其他的應該會報錯,因為沒寫判斷,我寫這個文章的時候是凌晨4點,下次寫吧
詳細使用
修改資料,並使用Redis代理
$wallet = Wallet::query()->first()->cache(); $wallet->balance_cache = 100;
// 修改balance欄位的值,並開始快取
修改 balance
或者 balance_cache
的效果等值,都是對快取進行修改
建議使用_cache
字尾,用於分辨普通模型的修改,以免老眼昏花
此時常規模型 Wallet::query()->first()->balance;
也會獲取到最新的快取資料
優先順序: 快取 > 資料庫
代理修改了資料,普通模型也修改了資料
$wallet1 = Wallet::query()->first()->cache(); $wallet1->balance_cache = 88;
// 這裡的修改,會在10分鐘後才儲存到資料庫
$wallet = Wallet::query()->first(); info($wallet->balance);
// 但是這裡能讀到哦 88 $wallet->balance = 200; $wallet->save();
// 這裡儲存新的值為200 ,放棄之前的修改,快取就失效了
info($wallet1->balance_cache);
// 200 , 如果你在其他模型更新了,這裡會硬生生同步
不想修改就生效怎麼辦, 開事務
$wallet1 = Wallet::query()->first()->cache(true);
// 這裡這樣就必須得儲存才有用了
$wallet1->balance_cache = 88;
// 本來是200 這裡是無效修改
$wallet = Wallet::query()->first();
info($wallet->balance); // 200
$wallet1 = Wallet::query()->first()->cache(true);
$wallet1->balance_cache = 88;
$wallet1->saveCache();
$wallet = Wallet::query()->first();
info($wallet->balance); // 88
關於事務提交
$wallet = Wallet::query()->first();
$wallet->balance = 0; $wallet->save(); // 初始值為0,
$wallet1 = Wallet::query()->first()->cache(true); $wallet1->balance_cache += 10;
debug($wallet1->balance_cache); // 10
$wallet2 = Wallet::query()->first()->cache(true); $wallet2->balance_cache += 10;
debug($wallet2->balance_cache);
// 10, 因為上一步的事務是沒提交的
$wallet1->saveCache(); debug($wallet2->balance_cache);
// 20, 提交了上一步的事務,一樣能夠得到最新的值,不要讓大哥的錢白花
$wallet3 = Wallet::query()->first()->cache(true); $wallet3->balance_cache += 10;
debug($wallet3->balance_cache); // 20, 因為wallet2 一樣沒提交 它不提交就是莫得效果
$wallet3->saveCache();
debug($wallet1->balance_cache); // 20, 1 這裡一樣能拿到最新值, 由於2沒提交,所以這裡是20
debug($wallet2->balance_cache); // 30, 2 這裡一樣能拿到最新值
$wallet2->saveCache();
debug($wallet1->balance_cache); // 30, 1 這裡一樣能拿到最新值
debug($wallet3->balance_cache); // 30, 3 這裡一樣能拿到最新值
本作品採用《CC 協議》,轉載必須註明作者和本文連結