精华内容
下载资源
问答
  • redis做mysql缓存实例
    2021-10-08 20:46:36

    1.为什么使用Redis
    (1)对用表中频繁进行访问但并不修改的SQL记录放入缓存,然后查询时先查询Redis再查询MySQL,实现读写分离,加速和保护MySQL,而缓存中的数据访问相应速度很快;
    (2)在高并发的情况下,大量请求访问数据库,会造成数据库过载,此时就可以先使用Redis做一个缓存操作。
    2.常见问题
    (1)如何保证双写一致性问题:
    通过设置key的过期时间,MySQL更新时,Redis不更新;

    更多相关内容
  • 本文主要向大家介绍了MySQL数据库之初学Redis的用Redis作为Mysql数据库的缓存,通过具体的实例让大家了解,希望对大家学习MySQL数据库有所帮助。用RedisMySQL数据库缓存,必须解决2个问题。首先,应该确定用何种...

    本文主要向大家介绍了MySQL数据库之初学Redis的用Redis作为Mysql数据库的缓存,通过具体的实例让大家了解,希望对大家学习MySQL数据库有所帮助。

    用Redis作MySQL数据库缓存,必须解决2个问题。首先,应该确定用何种数据结构存储来自mysql的数据;在确定数据结构之后,还要考虑用什么标识作为该数据结构的键。

    直观上看,Mysql中的数据都是按表存储的;更微观地看,这些表都是按行存储的。每执行一次select查询,Mysql都会返回一个结果集,这个结果集由若干行组成。所以,一个自然而然的想法就是在redis中找到一种对应于Mysql行的数据结构。Redis中提供了五种基本数据结构,即字符串(string)、列表(list)、哈希(hash)、集合(set)和有序集合(sorted set)。经过调研,发现适合存储行的数据结构有两种,即string和hash。

    要把Mysql的行数据存入string,首先需要对行数据进行格式化。事实上,结果集的每一行都可以看做若干由字段名和其对应值组成的键值对集合。这种键值对结构很容易让我们想起Json格式。因此,这里选用Json格式作为结果集每一行的格式化模板。根据这一想法,我们可以实现将结果集格式化为若干Json对象,并将Json对象转化为字符串存入Redis的代码:[cpp] view plain copy

    // 该函数把结果集中的每一行转换为一个Json格式的字符串并存入Redis的STRING结构中,

    // STRING键应该包含结果集标识符和STRING编号,形式如“cache.string:123456:1”

    string Cache2String(sql::Connection *mysql_connection,

    redisContext *redis_connection,

    sql::ResultSet *resultset,

    const string &resultset_id, int ttl) {

    if (resultset->rowsCount() == 0) {

    throw runtime_error("FAILURE - no rows");

    }

    // STRING键的前缀,包含了结果集的标识符

    string prefix("cache.string:" + resultset_id + ":");

    unsigned int num_row = 1; // STRING编号,附加于STRING键的末尾,从1开始

    sql::ResultSetMetaData *meta = resultset->getMetaData();

    unsigned int num_col = meta->getColumnCount();

    // 将结果集中所有行对应的所有STRING键存入该SET,SET键包含了结果集的标识符

    string redis_row_set_key("resultset.string:" + resultset_id);

    redisReply *reply;

    string ttlstr;

    stringstream ttlstream;

    ttlstream <

    ttlstr = ttlstream.str();

    resultset->beforeFirst();

    // 将结果集中的每一行转为Json格式的字符串,将这些Json字符串存入STRING,

    // 每个STRING对应结果集中的一行

    while (resultset->next()) {

    string redis_row_key; // STRING键名,由前缀和STRING编号组成

    stringstream keystream;

    keystream <

    redis_row_key = keystream.str();

    Json::Value row;

    for (int i = 1; i <= num_col; ++i) {

    string col_label = meta->getColumnLabel(i);

    string col_value = resultset->getString(col_label);

    row[col_label] = col_value;

    }

    Json::FastWriter writer;

    string redis_row_value = writer.write(row);

    // 将STRING键及Json格式的对应值对存入Redis

    reply = static_cast(redisCommand(redis_connection,

    "SET %s %s",

    redis_row_key.c_str(),

    redis_row_value.c_str()));

    freeReplyObject(reply);

    // 将STRING键加入SET中

    reply = static_cast(redisCommand(redis_connection,

    "SADD %s %s",

    redis_row_set_key.c_str(),

    redis_row_key.c_str()));

    freeReplyObject(reply);

    // 设置STRING的过期时间

    reply = static_cast(redisCommand(redis_connection,

    "EXPIRE %s %s",

    redis_row_key.c_str(),

    ttlstr.c_str()));

    freeReplyObject(reply);

    ++num_row;

    }

    // 设置SET的过期时间

    reply = static_cast(redisCommand(redis_connection,

    "EXPIRE %s %s",

    redis_row_set_key.c_str(),

    ttlstr.c_str()));

    freeReplyObject(reply);

    return redis_row_set_key; // 返回SET键,以便于其他函数获取该SET中的内容

    }

    [cpp] view plain copy

    // 该函数把结果集中的每一行都存入一个HASH结构。HASH键应当包括结果集标识符和HASH编号,

    // 形如“cache.string:123456:1”

    string Cache2Hash(sql::Connection *mysql_connection,

    redisContext *redis_connection,

    sql::ResultSet *resultset,

    const string &resultset_id, int ttl) {

    if (resultset->rowsCount() == 0) {

    throw runtime_error("FAILURE - no rows");

    }

    // HASH键的前缀,包含了结果集的标识符

    string prefix("cache.hash:" + resultset_id + ":");

    unsigned int num_row = 1; // HASH编号,附加于HASH键的末尾,从1开始

    sql::ResultSetMetaData *meta = resultset->getMetaData();

    unsigned int num_col = meta->getColumnCount();

    // 将结果集中所有行对应的所有HASH键存入该SET,SET键包含了结果集的标识符

    string redis_row_set_key("resultset.hash:" + resultset_id);

    redisReply *reply;

    string ttlstr;

    stringstream ttlstream;

    ttlstream <

    ttlstr = ttlstream.str();

    // 结果集中的每一行对应于一个HASH,将结果集的所有行都存入相应HASH中

    resultset->beforeFirst();

    while (resultset->next()) {

    string redis_row_key; // HASH键名,由前缀和HASH编号组成

    stringstream keystream;

    keystream <

    redis_row_key = keystream.str();

    for (int i = 1; i <= num_col; ++i) {

    string col_label = meta->getColumnLabel(i);

    string col_value = resultset->getString(col_label);

    // 将结果集中一行的字段名和对应值存入HASH

    reply = static_cast(redisCommand(redis_connection,

    "HSET %s %s %s",

    redis_row_key.c_str(),

    col_label.c_str(),

    col_value.c_str()));

    freeReplyObject(reply);

    }

    // 将HASH键加入SET中

    reply = static_cast(redisCommand(redis_connection,

    "SADD %s %s",

    redis_row_set_key.c_str(),

    redis_row_key.c_str()));

    freeReplyObject(reply);

    // 设置HASH的过期时间

    reply = static_cast(redisCommand(redis_connection,

    "EXPIRE %s %s",

    redis_row_key.c_str(),

    ttlstr.c_str()));

    freeReplyObject(reply);

    ++num_row;

    }

    // 设置SET的过期时间

    reply = static_cast(redisCommand(redis_connection,

    "EXPIRE %s %s",

    redis_row_set_key.c_str(),

    ttlstr.c_str()));

    freeReplyObject(reply);

    return redis_row_set_key; // 返回SET键,以便于其他函数获取该SET中的内容

    }

    至此,我们已经给出了两种存储Mysql结果集的方案,这就是我们在篇首提出的第一个问题,即选择何种数据结构存储Mysql结果集的答案。下一篇文章将研究第二个问题,即数据结构键的标识符选择问题。

    本文由职坐标整理并发布,希望对同学们学习MySQL有所帮助,更多内容请关注职坐标数据库MySQL数据库频道!

    展开全文
  • 一、redis做mysql缓存服务器 在实际项目中,MySQL数据库服务器有时会位于另外一台主机,需要通过网络来访问数据库;即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到磁盘IO操作(MySQL也有一些数据...

    目录

    一、redis做mysql的缓存服务器

    server2为redis server

     server4作为数据库端,安装mariadb-server

    server3安装lamp架构

     首先安装nginx

     做软连接,并更改主配置文件

     安装php-fpm

    进行相关配置

    二、配置gearman实现Redis和MySQL数据同步

    gearman介绍

    配置过程

    测试

    整体过程


    • 本文的主要目的即介绍上文说的这样一种方法,采用redis nosql数据库作为Mysql数据库的缓存,在查找的时候,首先查找redis缓存,如果找到则返回结果;如果在redis中没有找到,那么查找Mysql数据库,找到的话则返回结果并且更新redis;如果没有找到则返回空。对于写入的情况,直接写入mysql数据库,mysql数据库通过触发器及UDF机制自动把变更的内容更新到redis中。

    一、redis做mysql的缓存服务器

    server2为redis server

    必须为master,要能写。

     

    修改后查看server2状态为master

     server4作为数据库端,安装mariadb-server

    启动maridb服务并对test授权

    server3安装lamp架构

    server3之前没有安装过lamp架构,因此我们停掉redis,并设置开机不自启,利用他干净的环境安装lamp架构。

     首先安装nginx

     做软连接,并更改主配置文件

     将文件的php打开。

     之后重启,查看端口,此时并没有9000端口

     安装php-fpm

     

     此时php-mysql安装成功,但还没有redis

     此时有依赖性需要解决

    再次查看php-redis也安装成功。此时便可以启动了。

     此时查看端口,9000已经启动

    进行相关配置

     将test.php放到默认发布目录里。

    server4中,编写mysql触发器脚本test.sql,并导入test数据库 

     

    查看数据库数据,创建了1-9

     

    浏览器访问172.25.0.3/test.php 第一次访问的为mysql

    刷新就会变成redis,刚开始redis没有数据会先从数据库取,刷新后,便从redis中获取。

    在server2master主机中

    server4做为数据库更改id1后,查看已经变更

     

    此时查看server2作为redis的id1并没发生变化,所以是不同步的

     

    因为在test.php中写明先找redis拿数据,只要有就不会找数据库,此时变更便不会同步。

     

    当redis中没有时才会找mysql中拿。现在测试删除redis的id1

    此时再次访问,刷新,从mysql重新获得成为westos

     

    到这里,我们已经实现了redis作为mysql的缓存服务器,但是如果更新了mysql,redis中仍然会有对应的KEY,数据就不会更新,此时就会出现mysql和redis数据不一致的情况。所以接下来就要通过mysql触发器将改变的数据同步到redis中.

    二、配置gearman实现Redis和MySQL数据同步

    gearman介绍

    Gearman是一个支持分布式的任务分发框架:
       Gearman Job Server:Gearman核心程序,需要编译安装并以守护进程形式运行在后台。
       Gearman Client:可以理解为任务的请求者。
       Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行,Gearman Worker接收到Gearman Client传递的任务内容后,会按顺序处理。

    一个Gearman请求的处理过程涉及三个角色:Client -> Job -> Worker。

    Client:请求的发起者,可以是 C,PHP,Perl,MySQL UDF 等等。

    Job:请求的调度者,用来负责协调把 Client 发出的请求转发给合适的 Worker。

    Worker:请求的处理者,可以是 C,PHP,Perl 等等。

    因为 Client,Worker 并不限制用一样的语言,所以有利于多语言多系统之间的集成。

    甚至我们通过增加更多的 Worker,可以很方便的实现应用程序的分布式负载均衡架构。

    大致流程:
    下面要编写的mysql触发器,就相当于Gearman的客户端。修改表,插入表就相当于直接下发任务。然后通过lib_mysqludf_json UDF库函数将关系数据映射为JSON格式,然后在通过gearman-mysql-udf插件将任务加入到Gearman的任务队列中,最后通过redis_worker.php,也就是Gearman的worker端来完成redis数据库的更新。

    mysql中更改id1 为redhat,查看数据库发生变更,但是页面访问并没有。

    配置过程

     在server4上,解压lib_mysqludf_json-master.zip,并安装gcc

     

    安装开发包

     将lib_mysqludf_json-master/lib_mysqludf_json.so模块拷贝到/usr/lib64/mysql/plugin/插件目录下,通过lib_mysqludf_json UDF 库函数将关系映射为JISON格式 注册udf函数,并查看。

    安装libgearman安装包,并安装管理gearman的分布式队列插件,进行编译和安装 

     有依赖性,下载这几个rpm包,并安装

    再次执行 ./configure  --libdir=/usr/lib64/mysql/plugin/

     之后编译安装

    再次注册两个udf函数

     查看server3端口

     server3下载安装gearman(gman的worker端)

    开启gearmand服务并查看其端口号4730是否开启

     在server4指定gearman的服务信息 

    编写mysql触发器脚本test.sql,并导入test数据库 ,查看触发器设置成功。

    编写worker.php脚本,并放到/usr/local目录下 

    此时有redis还没有gearman,安装

    在后台运行worker 

    测试

    在数据库更改

     

     

    整体过程

     

    当数据库有变更时,会通过udf函数结合触发器 ,将数据发送给4730(gearmand),它再分发给worker。

    展开全文
  • RedisMySQL实现多级缓存 多级缓存的存在可以有效的提高数据的读取性能,而且还能起到一定的数据丢失的风险防范。本文使用RedisMySQL实现了微型博客系统中的文章主体内容的多级缓存(也就存了两个数据库)。 ...

    Redis和MySQL实现多级缓存

    多级缓存的存在可以有效的提高数据的读取性能,而且还能起到一定的数据丢失的风险防范。本文使用Redis和MySQL实现了微型博客系统中的文章主体内容的多级缓存(也就存了两个数据库)。

    Redis接口和功能实现

    为Redis接口加上三个函数,分别实现读取删的操作。

        String getUserArticleByAccountAndArticleName(String Account , String ArticleName);
        boolean setUserArticleByAccountAndArticleName(String Account , String ArticleName, String article);
        boolean deleteArticleByAccountAndArticleName(String Account , String ArticleName);
    

    接口的实现:
    key的命名采用的是“article:用户账号:文章名的形式”,value存的就是文章的内容。
    设置的时候顺带也设置了文章的时效时间(热点文章是有时效性的,不能一直存着占Redis的宝贵内存)

    @Override
    public String getUserArticleByAccountAndArticleName(String Account, String ArticleName) {
        String article = jedis.get("article" + ":" + Account + ":" + ArticleName);
        if ("null".equals(article)) return null;
        return article;
    }
    @Override
    public boolean setUserArticleByAccountAndArticleName(String Account, String ArticleName, String article) {
        //set的同时设置过期时间,为了防止集中过期,过期时间应该为一定范围内的随机数
        Random r = new Random();
        int lifeTime = r.nextInt(2 * 60 * 60) + 2 * 60 * 60;
        return "OK".equals(jedis.setex("article" + ":" + Account + ":" + ArticleName, lifeTime, article));
    }
    @Override
    public boolean deleteArticleByAccountAndArticleName(String Account, String ArticleName) {
        return jedis.del("article" + ":" + Account + ":" + ArticleName) == 1L;
    }
    

    Redis与MySQL的多级缓存实现

    这里直接在MySQL的代码中使用了Redis,我觉得应该再建立一个服务器专门用来选择管理多级缓存会更好,但是秋招在即,就不做的那么仔细了,先练练手会用它吧。

    修改MySQL管理文章内容的部分

    读:

    @Override
    public String getUserArticleByAccountAndArticleName(String account, String articleName) {
        //第一遍从Redis中获取
        String article = myRedis.getUserArticleByAccountAndArticleName(account, articleName);
        if (article!=null) return article;
        //Redis没有则从MySQL获取
        article = articlesMapper.selectArticleByAccountAndArticleName(account, articleName);
        if (article!=null){
            //把MySQL的数据同步到Redis
            myRedis.setUserArticleByAccountAndArticleName(account, articleName, article);
        }
        return article;
    }
    

    改:

    @Override
    public Boolean editArticle(String account, String title, String newTitle, String newContent) {
        articlesMapper.editArticle(account, title, newTitle, newContent);
        //更新文章时删除Redis关于文章的缓存
        //这里必须是在修改完MySQL后再删除Redis中的数据,否则多线程时容易出现数据的不一致。
        myRedis.deleteArticleByAccountAndArticleName(account,newTitle);
        return null;
    }
    

    删:

    @Override
    public Boolean deleteAnArticleComment(int comment_id) {
        commentsMapper.deleteByPrimaryKey(comment_id);
        return null;
    }
    

    结果验证

    直接打开一个Redis客户端,查询是否缓存了数据
    在这里插入图片描述可以看见这里缓存了账号的信息和刚刚打开的一个文章的内容。(文章内容里面的xa6\等内容为中文的编码形式。)还可以查看到文章在Redis中的剩余存活时间。

    在这里插入图片描述
    在前端的显示也没有什么问题。

    总结

    这里只实现了部分的功能,还有当用户账号删除、修改时的Redis数据库变动并没有涉及到。如果感兴趣的朋友可以进一步完善这些功能。
    多级缓存可以设计到更多的数据库,再考虑到分布式等因素会更加复杂(这里只有一个服务器在假装是分布式,只有一个Redis,没有实现集群),之后还需要更加深入的学习(深入学习之前我还是先找到工作吧T.T)。

    展开全文
  • 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。这样处理,主要是实时读写redis,而...
  • 使用Redis做mysql缓存

    千次阅读 2019-05-16 20:37:09
    redis做mysql缓存服务器 清理环境 server1: killall redis-server 若没有killall yum install psmisc-22.20-11.el7.x86_64 [root@server1 ~]# cd rhel7/ [root@server1 rhel7]# yum install -y * [root@server1 ...
  • 本文实例讲述了PHP使用redis实现统计缓存mysql压力的方法。分享给大家供大家参考,具体如下: <?php header("Content-Type:text/html;charset=utf-8"); include 'lib/mysql.class.php'; $mysql_obj = mysql::...
  • Redis缓存Mysql模拟用户登录Java实现实例https://jingyan.baidu.com/article/09ea3ede1dd0f0c0aede3938.htmlredis+mysql有几种用法?https://www.zhihu.com/question/20734566初学Redis(3)——用Redis作为Mysql...
  • 主要给大家介绍了关于Spring Boot中使用Redis做缓存的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
  • 我们开发中经常用到Redis作为缓存,将高频数据放在Redis中能够提高业务性能,降低MySQL等关系型数据库压力,甚至一些系统使用Redis进行数据持久化,Redis松散的文档结构非常适合业务系统开发,在精确查询,数据统计...
  • Java+MySQL+redis缓存

    热门讨论 2016-12-18 14:17:34
    案例中数据来自MySQL数据库,对查询出来的数据缓存redis,redis缓存工具可以将缓存string,bean,list,map等类型,代码中有详细的注释,而且还将要缓存的数据进行了序列化,大家可以借鉴,进而更改成自己想要的格式...
  • redis cluster && Redismysql缓存服务器
  • redis 配置及缓存案例

    2020-03-17 12:58:01
    spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.d...
  • 使用redis做MySQL缓存

    千次阅读 2018-08-27 11:30:16
    即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到磁盘IO操作(MySQL也有一些数据预读技术,能够减少磁盘IO读写,此部分后续继续研究),总之,直接从MySQL中读取数据不如直接从内存中读取数据来的效率高...
  • 首先声明一下,我是在一个SSM项目的基础上进行优化的,所以就不进行基础的介绍了。 下面我也补充一些知识点: redis: 内存型数据库,有持久化功能,...所有的查询结果都放进了缓存,也就是把MySQL查询的结果放...
  • MySQLRedis缓存的同步的方案

    千次阅读 2021-09-07 00:12:33
    本文介绍MySQLRedis缓存的同步的两种方案 方案1:通过MySQL自动同步刷新RedisMySQL触发器+UDF函数实现 方案2:解析MySQL的binlog实现,将数据库中的数据同步到Redis 方案3: 业务代码同时写入mysqlredis ...
  • 作者:董少、链接:https://dongshao.blog.csdn.net/article/details/107190925本文介绍MySQLRedis缓存的同步的两种方案通过My...
  • 简单的进行redis缓存

    2022-06-09 19:28:09
    简单的进行redis缓存
  • 本篇文章主要介绍了Spring Boot项目利用Redis实现集中式缓存实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的应用场景适用于缓存无需持久化...
  • 本篇文章主要介绍了Java自定义注解实现Redis自动缓存的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
  • mysql缓存redis

    2017-04-02 21:59:27
    Mysq需要注意的地方:mysql主从复制 延迟来自于 sql线程(解决:myslq5.7 可设置成多线程并行)数据库监控:lepus大型数据库的删除(安全快速的方法 一部分一部分删除)(不推荐暴力的删除 DELETE DROP 会造成主从不...
  • *因为rediscache本身是由mybatis进行实例化的,所以不能用spring工厂创建. *也就不能用spring的注入语法. 所以需要开发一个工具类 */ @Component public class ApplicationContextUtils implements ...
  • redis实现二级缓存

    2021-02-03 18:14:38
    Mybatis也会做缓存,也会有一级缓存和二级缓存:一级缓存:是SqlSession级别的缓存,使用HashMap数据结构来用于存储缓存数据的二级缓存:是mapper级别的缓存,其作用域是mapper的同一个namespace,不同的SqlSess...
  • 更多内容关注微信公众号:fullstack888本文介绍MySQLRedis缓存的同步的两种方案方案1:通过MySQL自动同步刷新RedisMySQL触发器+UDF函数实现方案2:解析...
  • 一、redis的安装先在下载安装包解压后进入目录应为已经有Makefile了所以直接make编译这里会报错,需要gcc编译器安装好gcc,再次make编译,还是会报错;这个错误根据 Readme 可知需要执行 make MALLOC=libcmake完成后...
  • Redis 服务器用途非常广泛,例如我们可以基于 Redis 服务器实现缓存系统。缓存系统可以缓解客户端访问压力,当缓存有效时只需直接将缓存结果返回给客户端而不用执行真正的后端逻辑。尝试在 Python 中实现一个简单的...
  • Redis只能做缓存?太out了!

    万次阅读 2022-06-28 14:55:31
    谁说Redis只能做缓存
  • - RedisMySQL 双写一致性 - 高并发高可用方案 - Join语句还能不能用? - 主从同步有延迟怎么办? - .frm .myi .myd .ibd 文件 - 为什么表数据删掉一半,表文件大小不变? - 误删表数据除了跑路,还能干啥? - MySQL...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,123
精华内容 17,649
关键字:

redis做mysql缓存实例

mysql 订阅