视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
MySQL和Redis实现二级缓存的方法详解
2020-11-09 20:20:34 责编:小采
文档


redis简介

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
  • Redis支持数据的备份,即master-slave模式的数据备份
  • 优势

  • 性能极高 - Redis能读的速度是110000次/s,写的速度是81000次/s
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作
  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来
  • 下载与安装

    下载并解压缩

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

    将文件夹移动到/usr/local/中

    mv redis-5.0.3 /usr/local/

    进入到文件夹中并编译测试

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

    编译安装

    sudo make install

    启动redis

    redis-server

    mysql与redis做二级缓存

    对于访问量比较大的数据我们为了能够更快的获取到数据需要对数据库中获取的数据进行数据缓存。

    在项目当中使用Redis缓存流程

  • 查询时先从缓存当中查询
  • 缓存当中如果没有数据再从数据库查询,并将数据保存进缓存当中
  • 如果缓存中查询到了数据直接返回,不再需要查询数据库
  • 数据缓存应该考虑同步问题:如果对数据进行了缓存,当查询数据时,如果缓存中有数据则直接返回缓存数据不会查询数据库,当数据库数据改变的时候就有可能出现数据库不一致的问题。可以考虑在每次修改数据库的时候同时将对应的缓存数据删除,这样重新查询的时候就会查询数据库并缓存

    步骤实现

    创建redisPool.go文件用于连接池的初始化

    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, //最大空闲链接数,表示即使没有redis链接事依然可以保持N个空闲链接,而不被清除
     MaxActive: 3, //最大激活连接数,表示同时最多有多少个链接
     IdleTimeout: 240 * time.Second,//最大空闲链接等待时间,超过此时间,空闲将被关闭
     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
     },
     }
    }

    创建main.go文件实现二级缓存

    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("输入命令")
     fmt.Scan(&cmd)
     switch cmd {
     case "getall":
     getAll()
     default:
     fmt.Println("不能识别其他命令")
     }
     fmt.Println()
     }
    }
    
    func getAll() {
     //从连接池当中获取链接
     conn := redigo_pool.Pool.Get()
     //先查看redis中是否有数据
     //conn,_ :=redis.Dial("tcp","localhost:6379")
     defer conn.Close()
     values, _ := redis.Values(conn.Do("lrange", "mlist",0,-1))
    
     if len(values) > 0 {
     //如果有数据
     fmt.Println("从redis获取数据")
     //从redis中直接获取
     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 反序列化出错")
     }else {
     fmt.Printf("name = %s\n",p.Name)
     }
     }
     }else {
     fmt.Println("从mysql中获取")
    
     //查询数据库
     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)
    
     }
     //写入到redis中:将person以hash的方式写入到redis中
     for _,p := range persons{
    
     p_byte,_ := json.Marshal(p)
     _,err1 := conn.Do("SETNX",p.Id,p_byte)
     _,err2 := conn.Do("lpush","mlist",p.Id)
     // 设置过期时间
     conn.Do("EXPIRE",p.Id,60*5)
     if err1 != nil || err2 != nil {
     fmt.Println("写入失败")
     }else {
     fmt.Println("写入成功")
     }
     }
     conn.Do("EXPIRE","mlist",60*5)
     }
    }

    总结

    下载本文
    显示全文
    专题