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指令包起来

下载与安装

  • 下载并解压缩
  1. wget http://download.redis.io/releases/redis-5.0.3.tar.gz
  2. tar xzf redis-5.0.3.tar.gz
  • 将文件夹移动到/usr/local/中
  1. mv redis-5.0.3 /usr/local/
  • 进入到文件夹中并编译测试
  1. cd /usr/local/redis-5.0.3
  2. sudo make test
  • 编译安装
  1. sudo make install
  • 启动redis
  1. redis-server

若出现以下画面则表示redis数据库已经启动了:
jpg

mysql与redis做二级缓存

  • 对于访问量比较大的数据我们为了能够更快的获取到数据需要对数据库中获取的数据进行数据缓存。
  • 在项目当中使用Redis缓存流程
    1. 查询时先从缓存当中查询
    2. 缓存当中如果没有数据再从数据库查询,并将数据保存进缓存当中
    3. 如果缓存中查询到了数据直接返回,不再需要查询数据库

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

步骤实现
  • 创建redisPool.go文件用于连接池的初始化
  1. package redigo_pool
  2. import (
  3. "flag"
  4. "github.com/garyburd/redigo/redis"
  5. "time"
  6. )
  7. var (
  8. Pool *redis.Pool
  9. RedisServer = flag.String("redisServer", ":6379", "")
  10. )
  11. func init() {
  12. Pool = &redis.Pool{
  13. MaxIdle: 3, //最大空闲链接数,表示即使没有redis链接事依然可以保持N个空闲链接,而不被清除
  14. MaxActive: 3, //最大激活连接数,表示同时最多有多少个链接
  15. IdleTimeout: 240 * time.Second,//最大空闲链接等待时间,超过此时间,空闲将被关闭
  16. Dial: func() (redis.Conn, error) {
  17. c, err := redis.Dial("tcp", *RedisServer)
  18. if err != nil {
  19. return nil, err
  20. }
  21. return c, err
  22. },
  23. TestOnBorrow: func(c redis.Conn, t time.Time) error {
  24. if time.Since(t) < time.Minute {
  25. return nil
  26. }
  27. _, err := c.Do("PING")
  28. return err
  29. },
  30. }
  31. }
  • 创建main.go文件实现二级缓存
  1. package main
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/garyburd/redigo/redis"
  7. _ "github.com/go-sql-driver/mysql"
  8. "strconv"
  9. "web/redis/redigo_pool"
  10. _ "web/redis/redigo_pool"
  11. )
  12. type Person struct {
  13. Id int `db:"id"`
  14. Name string `db:"name"`
  15. Age int `db:"age"`
  16. Rmb int `db:"rmb"`
  17. }
  18. func main() {
  19. var cmd string
  20. for{
  21. fmt.Println("输入命令")
  22. fmt.Scan(&cmd)
  23. switch cmd {
  24. case "getall":
  25. getAll()
  26. default:
  27. fmt.Println("不能识别其他命令")
  28. }
  29. fmt.Println()
  30. }
  31. }
  32. func getAll() {
  33. //从连接池当中获取链接
  34. conn := redigo_pool.Pool.Get()
  35. //先查看redis中是否有数据
  36. //conn,_ :=redis.Dial("tcp","localhost:6379")
  37. defer conn.Close()
  38. values, _ := redis.Values(conn.Do("lrange", "mlist",0,-1))
  39. if len(values) > 0 {
  40. //如果有数据
  41. fmt.Println("从redis获取数据")
  42. //从redis中直接获取
  43. for _,key := range values{
  44. pid :=string(key.([]byte))
  45. id ,_:= strconv.Atoi(pid)
  46. results,_ := redis.Bytes(conn.Do("GET",id))
  47. var p Person
  48. err := json.Unmarshal(results,&p)
  49. if err != nil {
  50. fmt.Println("json 反序列化出错")
  51. }else {
  52. fmt.Printf("name = %s\n",p.Name)
  53. }
  54. }
  55. }else {
  56. fmt.Println("从mysql中获取")
  57. //查询数据库
  58. db,_ := sql.Open("mysql","root:Szt930708@tcp(localhost:3306)/mydb")
  59. defer db.Close()
  60. var persons []Person
  61. rows,_ := db.Query("select id,name,age,rmb from person")
  62. for rows.Next() {
  63. var id int
  64. var name string
  65. var age int
  66. var rmb int
  67. rows.Scan(&id,&name,&age,&rmb)
  68. per := Person{id,name,age,rmb}
  69. persons = append(persons,per)
  70. }
  71. //写入到redis中:将person以hash的方式写入到redis中
  72. for _,p := range persons{
  73. p_byte,_ := json.Marshal(p)
  74. _,err1 := conn.Do("SETNX",p.Id,p_byte)
  75. _,err2 := conn.Do("lpush","mlist",p.Id)
  76. // 设置过期时间
  77. conn.Do("EXPIRE",p.Id,60*5)
  78. if err1 != nil || err2 != nil {
  79. fmt.Println("写入失败")
  80. }else {
  81. fmt.Println("写入成功")
  82. }
  83. }
  84. conn.Do("EXPIRE","mlist",60*5)
  85. }
  86. }
 
***********转摘:https://www.cnblogs.com/develop-SZT/p/10344594.html

MySQL与Redis实现二级缓存的更多相关文章

  1. Spring + MySQL + Mybatis + Redis【二级缓存】

    一.Redis环境 Redis 官网 :http://redis.io/ windows下载:https://github.com/dmajkic/redis/downloads 1.文件解压缩 2. ...

  2. Spring + MySQL + Mybatis + Redis【二级缓存】执行流程分析

    一级缓存基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就 ...

  3. SpringMVC + MyBatis + Mysql + Redis(作为二级缓存) 配置

    2016年03月03日 10:37:47 标签: mysql / redis / mybatis / spring mvc / spring 33805 项目环境: 在SpringMVC + MyBa ...

  4. SpringMVC +Spring + MyBatis + Mysql + Redis(作为二级缓存) 配置

    转载:http://blog.csdn.net/xiadi934/article/details/50786293 项目环境: 在SpringMVC +Spring + MyBatis + MySQL ...

  5. redis实现二级缓存

    缓存的作用就是降低数据库的使用率,来减轻数据库的负担.我们平常的操作一般都是查>改,所以数据库的有些查操作是重复的,如果一直使用数据库就会有负担.Mybatis也会做缓存,也会有一级缓存和二级缓 ...

  6. mybatis plus使用redis作为二级缓存

    建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现.为了方便,这里我们将缓存放到mapper层.mybatis-plus整合redi ...

  7. mybatis 使用redis实现二级缓存(spring boot)

    mybatis 自定义redis做二级缓存 前言 如果关注功能实现,可以直接看功能实现部分 何时使用二级缓存 一个宗旨---不常变的稳定而常用的 一级是默认开启的sqlsession级别的. 只在单表 ...

  8. Mybatis的二级缓存、使用Redis做二级缓存

    目录 什么是二级缓存? 1. 开启二级缓存 如何使用二级缓存: userCache和flushCache 2. 使用Redis实现二级缓存 如何使用 3. Redis二级缓存源码分析 什么是二级缓存? ...

  9. springboot+mybatis 用redis作二级缓存

    1.加入相关依赖包: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

随机推荐

  1. c语言define和typedef区别和使用

    define完全可以理解替换,typedef代表别名.听着差不多的意思,那2者区别在哪? 先来个简单例子查看基本使用. //define和typedef区别 #define DB double //替 ...

  2. 如果使用mybatis的逆向工程生成的po类及mapper,如果我们想要进行的对数据库的操作在mapper中没有对应的接口函数:比如生成的mapper接口中没有按照姓名及性别混合条件查询。我们的解决办法是:使用逆向工程生成的对应表的Example文件。

    1.使用mybatis逆向工程生成的po类中包含UserExample文件(我的数据库表名为User). 2. 创建UserExample对象,然后对加入条件.对应的测试代码为: /* * 通过姓名和 ...

  3. centos环境下创建数据库和表的方法

    centos环境下创建数据库和表的方法 //查询数据库的命令: mysql> SHOW DATABASES; +--------------------+ | Database         ...

  4. UVa 818Cutting Chains (暴力dfs+位运算+二进制法)

    题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...

  5. CMake使用技巧集

    1.注意CMake不允许出现相同的目标名称,即使是不同的目录下的CMakeLists.txt 2.将头文件搜索路径插入到其它的前面: include_directories(BEFORE /tmp) ...

  6. 大数据技术之_19_Spark学习_05_Spark GraphX 应用解析 + Spark GraphX 概述、解析 + 计算模式 + Pregel API + 图算法参考代码 + PageRank 实例

    第1章 Spark GraphX 概述1.1 什么是 Spark GraphX1.2 弹性分布式属性图1.3 运行图计算程序第2章 Spark GraphX 解析2.1 存储模式2.1.1 图存储模式 ...

  7. (转)SQL Server内存遭遇操作系统进程压榨案例

    原文地址:http://www.cnblogs.com/zc_0101/p/3592259.html 场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没 ...

  8. jmeter 计数器 (可自动生成新数字、注册专用)

    1.打开jmeter,创建好线程组后,添加计数器 2.设置计数器 3.添加HTTP请求,验证所设置的计数器 4.填写对应参数 5.添加查看结果树,查看结果 6.修改一下线程属性 7.跑一下,看下结果就 ...

  9. [label][转载][JavaSript]querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?

     轉載出處: http://www.zhihu.com/question/24702250 querySelectorAll 相比下面这些方法有什么区别? getElementsByTagName g ...

  10. Solr 使用自定义 Query Parser(短语查询,精准查询)

    原文出处:http://blog.chenlb.com/2010/08/solr-use-custom-query-parser.html 由于 Solr 默认的 Query Parser 生成的 Q ...