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因为几乎没有一致性的考虑所以最能保证,但业务约束太大。
来源:https://www.cnblogs.com/PattonCCNU/p/6409750.html