Laravel_Model_Cache(針對快速更新的數值屬性進行快取優化的外掛)

linty發表於2021-12-13

前言:
手上的專案有一些數值經常需要修改
例如wallet表的balance
主要是一些設計缺陷吧,容易出現死鎖,就算沒鎖,也會很慢
一個坑需要反覆填
就想直接做一個侵入性比較小的,不需要太多改動原始碼的外掛
能夠將Model的指定屬性進行快取,並且所有更改只在快取裡更改
等沒事了,統籌一下再一起儲存到資料庫
於是就有了這個專案
然後本人其實基礎不咋地,所以有什麼問題希望大家能夠多多幫助
然後如果這玩意是有前人的肩膀可以站,請告訴我,我就不用那麼累寫半天,阿里嘎多

Github

https://github.com/light-speak/laravel_model_cache

安裝

composer require linty/laravel_model_cache

說明

本外掛全部用的Cache, Cache使用的Redis儲存 功能為,對某個模型的物件的某個欄位進行代理,使用Cache維護 一段時間(暫時為10分鐘)內的修改全部在Cache進行, 以此優化效能

使用

  1. 佇列新增一個queue,名稱為:model-cache ,用於維護欄位, 當模型第一次被建立快取時,會建立一個延時10分鐘的Job,10分鐘後(或者更久)進行資料庫儲存操作
  2. 在需要使用的Model類使用:
    use ModelCacheTrait;
    這時候模型的getAttributeFromArray方法就會被攔截, 進行一些快取讀取的操作
  3. 在原來的模型後面增加->cache(), 例如
 $wallet = Wallet::query()->first()->cache();
  1. 如果需要事務,則:
    $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 協議》,轉載必須註明作者和本文連結

相關文章