Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Amalan menggunakan cache untuk mempercepatkan kecekapan capaian pangkalan data di Golang.

Amalan menggunakan cache untuk mempercepatkan kecekapan capaian pangkalan data di Golang.

WBOY
WBOYasal
2023-06-20 10:12:101516semak imbas

Amalan menggunakan cache untuk mempercepatkan kecekapan capaian pangkalan data di Golang

Apabila aplikasi web menjadi semakin kompleks, akses kepada pangkalan data menjadi semakin kerap. Mengakses pangkalan data biasanya merupakan operasi yang sangat memakan masa, terutamanya apabila jumlah data adalah besar. Untuk meningkatkan kecekapan capaian pangkalan data, strategi seperti caching boleh digunakan untuk mengoptimumkan capaian pangkalan data.

Artikel ini akan memperkenalkan amalan menggunakan cache untuk mempercepatkan capaian pangkalan data di Golang. Kami akan menggunakan Golang sebagai bahasa pembangunan, Redis sebagai pelayan cache, dan MySQL sebagai pelayan pangkalan data untuk eksperimen.

1. Sediakan persekitaran

Sebelum kita mula, kita perlu menyediakan persekitaran. Mula-mula pasang pelayan Golang dan MySQL dan Redis, yang tidak akan diterangkan di sini.

Kemudian pasang pemacu Go untuk Redis tempatan dan MySQL di Golang:

go get github.com/go-redis/redis/v8
go get github.com/go-sql-driver/mysql

2. Tulis kod

Seterusnya, kami tulis kod untuk melaksanakan caching untuk mempercepatkan akses pangkalan data .

Yang pertama ialah kod untuk akses pangkalan data. Kami menentukan pembolehubah global yang dipanggil DB untuk menyambung ke MySQL. Kemudian, kami mentakrifkan fungsi getUserByID untuk menanyakan maklumat pengguna daripada MySQL:

package main
 
import (
   "database/sql"
   "fmt"
   "log"
 
   _ "github.com/go-sql-driver/mysql"
)
 
var DB *sql.DB
 
type User struct {
   ID       int
   Username string
   Password string
   Age      int
}
 
func init() {
   db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8")
   if err != nil {
      log.Fatal("Open mysql failed,err:", err)
      return
   }
   DB = db
   fmt.Println("Connect to mysql success")
}
 
func getUserByID(id int) (*User, error) {
   var user User
   query := "SELECT id, username, password, age FROM users WHERE id=?"
   err := DB.QueryRow(query, id).Scan(&user.ID, &user.Username, &user.Password, &user.Age)
   if err != nil {
      log.Println(err)
      return nil, err
   }
   return &user, nil
}

Kemudian, kami menambah logik caching pada fungsi getUserByID ini. Khususnya, kami mula-mula cuba membaca maklumat pengguna yang diminta daripada cache Redis melalui fungsi getUserByID. Jika tiada rekod maklumat untuk pengguna dalam Redis, maklumat pengguna dibaca daripada MySQL dan disimpan dalam Redis untuk akses seterusnya. Jika maklumat pengguna direkodkan dalam Redis, maklumat pengguna dikembalikan terus daripada Redis:

package main
 
import (
   "database/sql"
   "encoding/json"
   "fmt"
   "log"
   "strconv"
 
   "github.com/go-redis/redis/v8"
   _ "github.com/go-sql-driver/mysql"
)
 
var DB *sql.DB
var RedisClient *redis.Client
 
type User struct {
   ID       int
   Username string
   Password string
   Age      int
}
 
func init() {
   db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8")
   if err != nil {
      log.Fatal("Open mysql failed,err:", err)
      return
   }
   DB = db
   fmt.Println("Connect to mysql success")
 
   RedisClient = redis.NewClient(&redis.Options{
      Addr: "127.0.0.1:6379",
   })
   pong, err := RedisClient.Ping(RedisClient.Context()).Result()
   if err != nil {
      panic(err)
      return
   }
   fmt.Println("Connect to redis success: ", pong)
}
 
func getUserByID(id int) (*User, error) {
   var user User
   key := "user-" + strconv.Itoa(id)
 
   // 1.尝试从Redis中读取用户信息
   val, err := RedisClient.Get(RedisClient.Context(), key).Result()
   if err == redis.Nil {
      fmt.Println("Cache miss")
   } else if err != nil {
      log.Println("Get from Redis fail:", err)
   } else {
      fmt.Println("Get from Redis:", val)
      if err := json.Unmarshal([]byte(val), &user); err != nil { // 将json字符串转换为结构体
         log.Panicln("Unmarshal to user fail:", err)
      }
      return &user, nil
   }
 
   // 2.如果Redis中没有,从MySQL中查询
   query := "SELECT id, username, password, age FROM users WHERE id=?"
   err = DB.QueryRow(query, id).Scan(&user.ID, &user.Username, &user.Password, &user.Age)
   if err != nil {
      log.Println(err)
      return nil, err
   }
 
   // 3.然后更新Redis缓存
   val, err = json.Marshal(user) // 将结构体转换为json字符串
   if err != nil {
      log.Panicln("Marshal user fail:", err)
   }
   err = RedisClient.Set(RedisClient.Context(), key, val, 0).Err()
   if err != nil {
      log.Panicln("Cache to Redis fail:", err)
   }
   return &user, nil
}

3. Ujian

Kami telah menyelesaikan penulisan logik cache. Sekarang mari kita uji kod ini dan lihat cara ia berfungsi.

Pertama sekali, program ujian kami perlu membaca maklumat pengguna daripada MySQL buat kali pertama:

func main() {
   id := 1
   user, err := getUserByID(id)
   if err != nil {
      log.Fatal(err)
      return
   }
   fmt.Printf("User info: id=%d, username=%s, password=%s, age=%d
",
      user.ID, user.Username, user.Password, user.Age)
}

Jalankan program dan output adalah seperti berikut:

Cache miss
User info: id=1, username=kirito, password=123456, age=18

Anda boleh melihat bahawa program membaca daripada MySQL Maklumat pengguna dikeluarkan dan disimpan dalam cache Redis.

Selepas menyoal pengguna yang sama untuk kali kedua, atur cara akan membaca maklumat pengguna daripada Redis dan bukannya mengakses pangkalan data MySQL:

func main() {
   id := 1
   user, err := getUserByID(id)
   if err != nil {
      log.Fatal(err)
      return
   }
   fmt.Printf("User info: id=%d, username=%s, password=%s, age=%d
",
      user.ID, user.Username, user.Password, user.Age)
}

Jalankan atur cara, output adalah seperti berikut:

Get from Redis: {"ID":1,"Username":"kirito","Password":"123456","Age":18}
User info: id=1, username=kirito, password=123456, age=18

Anda dapat melihat bahawa program membaca maklumat pengguna terus dari Redis tanpa mengakses pangkalan data MySQL, yang membuktikan kepraktisan caching.

Ringkasan

Dalam artikel ini, kami memperkenalkan amalan menggunakan mekanisme caching Redis di Golang untuk mengoptimumkan kecekapan akses pangkalan data. Dengan menulis fungsi getUserByID, apabila menanyakan maklumat pengguna, kami mula-mula cuba membaca maklumat daripada Redis untuk mempercepatkan pertanyaan Jika maklumat pengguna tidak wujud dalam Redis, kami membacanya daripada MySQL dan menyimpannya dalam Redis. Selepas data dicache, apabila program mengakses data yang sama beberapa kali, ia boleh membaca terus dari cache tanpa mengakses pangkalan data setiap kali.

Perlu diingatkan bahawa penggunaan cache perlu mengelakkan penjanaan data kotor. Untuk operasi CRUD pada data, cache juga perlu mengikuti operasi data untuk memastikan konsistensi data dalam cache dan pangkalan data.

Secara amnya, menggunakan mekanisme caching boleh meningkatkan prestasi program dengan sangat baik, dan amat berkesan apabila memproses sejumlah besar data. Strategi ini juga sangat praktikal dalam sistem konkurensi tinggi, dan pembangun disyorkan untuk mencubanya.

Atas ialah kandungan terperinci Amalan menggunakan cache untuk mempercepatkan kecekapan capaian pangkalan data di Golang.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn