Detailed Explanation of MySQL and Redis Methods for Realizing L2 Cache

  • 2021-11-13 03:02:16
  • OfStack

Introduction to redis

Redis is fully open source and free, complies with BSD protocol, and is a high performance key-value database

Redis and other key-value cache products have the following three features:

Redis supports the persistence of data, which can save the data in memory in disk, and can be reloaded for use when restarting Redis not only supports simple key-value type data, but also provides storage of list, set, zset, hash and other data structures Redis supports data backup, that is, data backup in master-slave mode

Advantage

Extremely high performance-Redis can read 110000 times/s and write 81000 times/s Rich data type Redis supports Strings, Lists, Hashes, Sets and Ordered Sets data type operations in binary cases All of the operations of the atomic Redis are atomic, meaning that they either succeed or fail to do nothing at all. Individual operations are atomic. Multiple operations also support transactions, i.e. atomicity, wrapped by MULTI and EXEC instructions

Download and install

Download and unzip


wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar xzf redis-5.0.3.tar.gz

Move the folder to/usr/local/


mv redis-5.0.3 /usr/local/

Enter the folder and compile the test


cd /usr/local/redis-5.0.3
sudo make test

Compile and install


sudo make install

Start redis


redis-server

mysql and redis do level 2 cache

In order to get the data more quickly, we need to cache the data in the database.

Using the Redis caching process in a project

When querying, query from the cache first If there is no data in the cache, query from the database and save the data in the cache If the data found in the cache is returned directly, it is no longer necessary to query the database

Data caching should consider the synchronization problem: if the data is cached, when querying data, if there is data in the cache, it will directly return the cached data without querying the database, and when the database data changes, there may be a problem of database inconsistency. Consider deleting the corresponding cached data at the same time when modifying the database, so that the database will be queried and cached when re-querying

Step implementation

Create an redisPool. go file for connection pool initialization


package redigo_pool

import (
 "flag"
 "github.com/garyburd/redigo/redis"
 "time"
)
var (
 Pool *redis.Pool
 RedisServer = flag.String("redisServer", ":6379", "")
 
)
func init() {
 Pool = &redis.Pool{
  MaxIdle:  3, // Maximum number of free links, indicating that even if there are no redis Links can still be maintained N Idle links without being cleared 
  MaxActive: 3, // Maximum number of active connections, indicating the maximum number of links at a time 
  IdleTimeout: 240 * time.Second,// Maximum idle link wait time, beyond which idle will be turned off 
  Dial: func() (redis.Conn, error) {
   c, err := redis.Dial("tcp", *RedisServer)
   if err != nil {
    return nil, err
   }
   return c, err
  },
  TestOnBorrow: func(c redis.Conn, t time.Time) error {
   if time.Since(t) < time.Minute {
    return nil
   }
   _, err := c.Do("PING")
   return err
  },
 }
}

Create main. go file to realize level 2 cache


package main

import (
 "database/sql"
 "encoding/json"
 "fmt"
 "github.com/garyburd/redigo/redis"
 _ "github.com/go-sql-driver/mysql"
 "strconv"
 "web/redis/redigo_pool"
 _ "web/redis/redigo_pool"
)

type Person struct {
 Id int `db:"id"`
 Name string `db:"name"`
 Age int `db:"age"`
 Rmb int `db:"rmb"`
}

func main() {
 var cmd string
 for{
  fmt.Println(" Input command ")
  fmt.Scan(&cmd)
  switch cmd {
  case "getall":
   getAll()
  default:
   fmt.Println(" Unable to recognize other commands ")
  }
  fmt.Println()
 }
}

func getAll() {
 // Get links from the connection pool 
 conn := redigo_pool.Pool.Get()
 // Check first redis Is there data in 
 //conn,_ :=redis.Dial("tcp","localhost:6379")
 defer conn.Close()
 values, _ := redis.Values(conn.Do("lrange", "mlist",0,-1))

 if len(values) > 0 {
  // If there is data 
  fmt.Println(" From redis Get data ")
  // From redis Direct access in 
  for _,key := range values{
   pid :=string(key.([]byte))
   id ,_:= strconv.Atoi(pid)
   results,_ := redis.Bytes(conn.Do("GET",id))
   var p Person
   err := json.Unmarshal(results,&p)
   if err != nil {
    fmt.Println("json  Error in deserialization ")
   }else {
    fmt.Printf("name = %s\n",p.Name)
   }
  }
 }else {
  fmt.Println(" From mysql Get from ")

  // Query database 
  db,_ := sql.Open("mysql","root:Szt930708@tcp(localhost:3306)/mydb")
  defer db.Close()

  var persons []Person

  rows,_ := db.Query("select id,name,age,rmb from person")
  for rows.Next() {
   var id int
   var name string
   var age int
   var rmb int
   rows.Scan(&id,&name,&age,&rmb)
   per := Person{id,name,age,rmb}
   persons = append(persons,per)

  }
  // Write to redis Medium : Will person With hash Write to the redis Medium 
  for _,p := range persons{

   p_byte,_ := json.Marshal(p)
   _,err1 := conn.Do("SETNX",p.Id,p_byte)
   _,err2 := conn.Do("lpush","mlist",p.Id)
   //  Set expiration time 
   conn.Do("EXPIRE",p.Id,60*5)
   if err1 != nil || err2 != nil {
    fmt.Println(" Write failure ")
   }else {
    fmt.Println(" Write successful ")
   }
  }
  conn.Do("EXPIRE","mlist",60*5)
 }
}

Summarize


Related articles: