ホームページ >バックエンド開発 >Golang >Golang でのデータベース アクセス効率を向上させるためにキャッシュを使用する実践。

Golang でのデータベース アクセス効率を向上させるためにキャッシュを使用する実践。

WBOY
WBOYオリジナル
2023-06-20 10:12:101577ブラウズ

Golang でキャッシュを使用してデータベース アクセス効率を向上させる実践

Web アプリケーションがますます複雑になるにつれて、データベースへのアクセスもますます頻繁になります。データベースへのアクセスは、通常、特にデータ量が多い場合には非常に時間がかかる操作です。データベース アクセスの効率を向上させるために、キャッシュなどの戦略を使用してデータベース アクセスを最適化できます。

この記事では、Golang でのデータベース アクセスを高速化するためにキャッシュを使用する方法を紹介します。開発言語としてGolang、キャッシュサーバーとしてRedis、データベースサーバーとしてMySQLを実験用に使用します。

1. 環境をセットアップする

始める前に、環境をセットアップする必要があります。まず、Golang、MySQL、Redis サーバーをインストールしますが、ここでは説明しません。

次に、Golang でローカル Redis と MySQL 用の Go ドライバーをインストールします:

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

2. コードを作成します

次に、データベース アクセスを高速化するためのキャッシュを実装するコードを作成します。 。

最初はデータベースアクセス用のコードです。 MySQL に接続するための DB というグローバル変数を定義しました。次に、MySQL からユーザーの情報をクエリする関数 getUserByID を定義しました。

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
}

次に、キャッシュ ロジックを getUserByID 関数に追加しました。具体的には、まず getUserByID 関数を使用して、要求されたユーザー情報を Redis キャッシュから読み取ろうとします。 Redis にユーザーの情報レコードがない場合、ユーザー情報は MySQL から読み取られ、次回のアクセスのために Redis に保存されます。ユーザー情報が Redis に記録されている場合、ユーザー情報は 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. Test

これでキャッシュ ロジックの作成が完了しました。次に、このコードをテストして、どのように動作するかを見てみましょう。

まず、テスト プログラムは初めて 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)
}

プログラムを実行すると、出力は次のようになります:

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

You MySQLからプログラムが読み込まれていることがわかります。 ユーザー情報が取り出してRedisキャッシュに保存されています。

同じユーザーに 2 回目のクエリを実行すると、プログラムは MySQL データベースにアクセスする代わりに、Redis からユーザー情報を読み取ります。

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)
}

プログラムを実行すると、出力は次のようになります。

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

プログラムが MySQL データベースにアクセスせずに、Redis からユーザー情報を直接読み取ることがわかります。これは、キャッシュの実用性を証明しています。

概要

この記事では、Golang で Redis キャッシュ メカニズムを使用してデータベース アクセス効率を最適化する方法を紹介しました。 getUserByID 関数を記述することで、ユーザー情報をクエリする際、まず Redis から情報を読み込んでクエリを高速化しますが、Redis にユーザー情報が存在しない場合は、MySQL から読み取って Redis に保存します。データがキャッシュされた後、プログラムが同じデータに複数回アクセスする場合、毎回データベースにアクセスすることなく、キャッシュから直接読み取ることができます。

キャッシュを使用する場合は、ダーティ データの生成を回避する必要があることに注意してください。データに対する CRUD 操作の場合、キャッシュとデータベース内のデータの一貫性を確保するために、キャッシュもデータ操作に従う必要があります。

一般に、キャッシュ メカニズムを使用するとプログラムのパフォーマンスが大幅に向上し、大量のデータを処理する場合に特に効果的です。この戦略は、同時実行性の高いシステムでも非常に実用的であるため、開発者は試してみることをお勧めします。

以上がGolang でのデータベース アクセス効率を向上させるためにキャッシュを使用する実践。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。