mysql+redis探究

风格不统一 提交于 2020-04-06 21:21:03

1. mysql部署

      mysql下载:https://dev.mysql.com/downloads/mysql/  这里下载的是mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz。

     安装过程参考http://blog.csdn.net/live006/article/details/53725666,这个实际操作可行。

     安装成功后,在linux终端控制台直接敲入mysql -u root -p后会提示输入密码,表示能正常登录。而如果提示命令不识别,可能是/usr/bin下面找不到mysql的软链接,执行ln -s /usr/local/mysql/bin/mysql mysql即可。

2.c++连接mysql

     c++代码中要连上mysql服务器,必须有mysql的客户端api。这次我在windows上测试连接,选择一个靠谱的方式是:下载一个mysql客户端(mysql_installer_community_V5.6.21.1_setup.1418020972.msi),安装后在安装目录MySQL\MySQL Connector.C 6.1路径下可以找到相应的头文件和依赖库文件,加入到工程中即可。之所以采用这种方式,因为下载客户端后可以用客户端先测试连接,如果正常则说明api可用。

     本次测试,我采用qt中间库,在\qt-4.7.0\src\plugins\sqldrivers\mysql下面加入上面的mysql头文件和静态库文件后,即可编译生成qt的mysql插件:qsqlmysqld4.lib qsqlmysqld4.dll,这样就可以自在的用QSqlDatabase连接并操作mysql数据库了。

3. redis部署

     redis下载:http://download.redis.io/releases/redis-3.2.4.tar.gz  这里可以通过wget或者用浏览器down下来。

     安装过程参考http://jingyan.baidu.com/article/03b2f78c0408e55ea237ae35.html,这个实际操作可行。

     安装完成后,输入redis-cli即可进入redis命令行输入模式。而如果提示Connection refused,可能是redis服务未启动,通过service redis start启动redis服务。

4.c++连接redis

     c++代码中要连接上redis服务器,我采用的是hiredis库,测试环境为centos6.0。hiredis下载地址:https://github.com/redis/hiredis,hiredis库处理可以参考http://www.tuicool.com/articles/YNjIRre,主要就是提供头文件和动态库。

     之后就可以编写客户端代码了,这里参考上面帖子《C++操作Redis数据库》中的代码并进行修改完善后给出一个简单的测试类封装:

#ifndef _REDIS_H_

#define _REDIS_H_

#include <iostream>

#include <string.h>

#include <string>

#include <stdio.h>

#include <hiredis/hiredis.h>

class Redis

{

public:

    Redis() : m_connect(NULL), m_reply(NULL)

       {

       }

    ~Redis()

       {

              if (NULL != m_connect)

              {

                     redisFree(m_connect);

                     m_connect = NULL;

              }

              if (NULL != m_reply)

              {

                     freeReplyObject(m_reply);

                     m_reply = NULL;

              }        

       }

 

       bool connect(std::string host, int port)

       {

           m_connect = redisConnect(host.c_str(), port);

              if(m_connect != NULL && m_connect->err)

              {

                  printf("connect to redisServer error: %s\n", m_connect->errstr);

                     return false;

              }

              return true;

       }

       bool set(std::string key, std::string value)

       {

              if (NULL == m_connect)

                     return false;

              redisReply* reply = (redisReply*)redisCommand(m_connect, "set %s %s", key.c_str(), value.c_str());

              if( NULL == reply)

              {

                     printf("Execut set command failure\n");

                     return false;

              }

              if( !(reply->type == REDIS_REPLY_STATUS && 0 == strcasecmp(reply->str,"OK")))

              {

                     printf("Failed to execute set command\n");

                     freeReplyObject(reply);

                     m_reply = NULL;

                     return false;

              }     

              freeReplyObject(reply);

              m_reply = NULL;

              return true;

       }

    std::string get(std::string key)

       {

              std::string str;

              if (NULL == m_connect)

                     return str;

              m_reply = (redisReply*)redisCommand(m_connect, "get %s", key.c_str());

              if (m_reply->type != REDIS_REPLY_STRING)

              {

                     printf("Failed to execute get command\n");

                     freeReplyObject(m_reply);

                     m_reply = NULL;

                     return str;

              }

              str = m_reply->str;

              freeReplyObject(m_reply);

              m_reply = NULL;

              return str;

       }

private:

    redisContext* m_connect;

       redisReply* m_reply;

};

#endif  //_REDIS_H_

     这个测试类经测试可用,一个简单的测试代码是:

#include "redis.h"

int main()

{

       Redis *redis_clie = new Redis();

       if(!redis_clie->connect("127.0.0.1", 6379))

       {

              printf("connect error!\n");

              return 0;

       }

       redis_clie->set("a", "111");

       printf("Get the name is %s\n", redis_clie->get("a").c_str());

       delete redis_clie;

       redis_clie = NULL;

       return 0;

}

     在测试中发现一个吊诡的事,connect的目标IP如果不是127.0.0.1的话,要么连接被拒绝,要么set数据失败,而127.0.0.1却十分正常,后来看了看redis.conf中的说明,大约明白一点了:

# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES

# JUST COMMENT THE FOLLOWING LINE.

bind 127.0.0.1

     大概意思是把redis所有接口暴露给所有的网络客户端是个危险的事情,默认只能接收本地客户端的连接。

     另外,如果修改了redis.conf配置文件的话,要想配置生效,不能采用service的方式,而需要采用运行程序加参数的方式,在redis.conf的开头就有说明:

# Note that in order to read the configuration file, Redis must be

# started with the file path as first argument:

#

# ./redis-server /path/to/redis.conf

5. mysql + redis

     mysql是传统关系数据库,redis是nosql的内存数据库,后者的出现主要是为了解决前者IO效率的问题。单独作为数据库解决方案,二者都能独当一面(redis也能做数据持久化,只是数据总容量受内存限值),由于mysql+redis是目前用的比较多的一个方案,这里搜集了下网友在用该方案的心得:

  • mysql作为主要数据库存储所有业务数据,对于访问量很大的特殊业务,将mysql数据读到redis中,客户端在这些特殊业务中直接读redis,其它业务还是与mysql交互。当这些特殊业务的数据有增删改时,同步修改mysql和redis即可;
  • 数据使用情形同情况1,但当特殊业务的数据有增删改时,只操作mysql,对redis的相应数据做失效处理(删除),redis中缺的数据在需要时找mysql再同步过来;
  • 根据实际业务场景,redis只一次性同步mysql中基本不需要增删改的某类数据,即使用中不用考虑二者数据同步的问题,保证高一致性。

     以上三种情况中,mysql与redis的数据一致性是递增的。情况1中同步mysql和redis的过程有可能失败,导致二者数据不一致;情况2中失效处理本身需要保证二者的同步性,如果处理不好也会出现不一致的可能;情况3因为几乎没有一致性的考虑所以最能保证,但业务约束太大。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!