mysql+redis探究


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因為幾乎沒有一致性的考慮所以最能保證,但業務約束太大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM