首頁 > 軟體

GoFrame 框架快取查詢結果的範例詳解

2022-06-16 10:01:56

後續幾篇文章再接再厲,仍然為大家介紹GoFrame框架快取相關的知識點,以及自己專案使用中的一些總結思考,GoFrame框架下文簡稱gf。

今天重點為大家介紹:GoFrame 如何優雅的快取查詢結果

查詢快取

gdb支援對查詢結果的快取處理,常用於多讀少寫的查詢快取場景,並支援手動的快取清理。

需要注意的是,查詢快取僅支援鏈式操作,且在事務操作下不可用。

相關方法:

func (m *Model) Cache(duration time.Duration, name ... string) *Model
  • 重要提醒:事務查詢是不支援快取的。
  • 當duration < 0時表示清除快取, duration=0時表示不過期, duration > 0時表示過期時間,duration過期時間單位:秒;
  • name表示自定義的快取名稱,便於業務層精準定位快取項(如果業務層需要手動清理時,必須指定快取名稱)

快取物件

ORM物件預設情況下提供了快取管理物件,該快取物件型別為*gcache.Cache,也就是說同時也支援*gcache.Cache的所有特性。

可以通過GetCache() *gcache.Cache 介面方法獲得該快取物件,並通過返回的物件實現自定義的各種快取操作,例如:g.DB().GetCache().Keys()

快取適配(Redis快取)

預設情況下ORM*gcache.Cache快取物件提供的是單程序記憶體快取,雖然效能非常高效,但是隻能在單程序內使用。

如果服務採用多節點部署,多節點之間的快取可能會產生資料不一致的情況,因此大多數場景下我們都是通過Redis伺服器來實現對資料庫查詢資料的快取。

*gcache.Cache物件採用了介面卡設計模式,可以輕鬆實現從單程序記憶體快取切換為分散式的Redis快取。

範例程式碼如下,是不是非常優雅:

adapter := adapter.NewRedis(g.Redis())
g.DB().GetCache().SetAdapter(adapter)

Redis的快取是基於查詢SQL作為鍵名,查詢結果作為鍵值。

通過Cache鏈式方法對快取的寫入和清除都非常便捷。

使用範例

資料表結構

CREATE TABLE `user` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL DEFAULT '' COMMENT '暱稱',
  `site` varchar(255) NOT NULL DEFAULT '' COMMENT '網站',
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

範例程式碼

package main
import (
    "github.com/gogf/gf/database/gdb"
    "github.com/gogf/gf/frame/g"
    "time"
)
func main() {
    db := g.DB()
    // 開啟偵錯模式,以便於記錄所有執行的SQL
    db.SetDebug(true)

    // 執行2次查詢並將查詢結果快取1小時,並可執行快取名稱(可選)
    for i := 0; i < 2; i++ {
        r, _ := db.Table("user").Cache(time.Hour, "test-user").Where("uid", 1).One()
        g.Log().Print(r.Map())
    }
    // 執行更新操作,並清理指定名稱的查詢快取
    _, err := db.Table("user").Cache(-1, "test-user").Data(gdb.Map{"name": "海賊王"}).Where("uid", 1).Update()
    if err != nil {
        g.Log().Fatal(err)
    }
    // 再次執行查詢,啟用查詢快取特性
    r, _ := db.Table("user").Cache(time.Hour, "test-user").Where("uid", 1).One()
    g.Log().Print(r.Map())
}

執行後輸出結果為(測試表資料結構僅供範例參考):

2022-06-15 21:44:12.228 [DEBU] [1 ms] SELECT * FROM `user` WHERE uid=1 LIMIT 1
2022-06-15 21:44:12.228 {"name":"王中陽","site":"https://juejin.cn/user/2189882892232029","uid":1}
2022-06-15 21:44:12.228 {"name":"王中陽","site":"https://juejin.cn/user/2189882892232029","uid":1}
2022-06-15 21:44:12.299 [DEBU] [1 ms] UPDATE `user` SET `name`='海賊王' WHERE uid=1
2022-06-15 21:44:12.300 [DEBU] [1 ms] SELECT * FROM `user` WHERE uid=1 LIMIT 1
2022-06-15 21:44:12.300 {"name":"海賊王","site":"https://juejin.cn/user/2189882892232029","uid":1}

小技巧

為了方便展示快取效果,這裡開啟了資料debug特性,當有任何的SQL操作時將會輸出到終端。

執行結果分析

  • 執行兩次One方法資料查詢,第一次走了SQL查詢,第二次直接使用到了快取,SQL沒有提交到資料庫執行,因此這裡只列印了一條查詢SQL,並且兩次查詢的結果也是一致的。
  • 注意這裡為該查詢的快取設定了一個自定義的名稱test-user,以便於後續清空更新快取。如果快取不需要清理,那麼可以不用設定快取名稱。
  • 當執行Update更新操作時,同時根據名稱清空指定的快取。
  • 隨後再執行One方法資料查詢,這時重新快取新的資料。

總結

GoFrame的gdb對查詢結果的快取處理是不是非常的優雅。尤其是*gcache.Cache物件採用了介面卡設計模式,可以輕鬆實現從單程序記憶體快取切換為分散式的Redis快取。

到此這篇關於GoFrame 如何優雅的快取查詢結果的文章就介紹到這了,更多相關GoFrame 快取查詢結果內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com