windows环境下通过c++使用redis

1.Windows下Redis的安装使用

Redis是一个key-value存储系统。Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。本文中,作者分享了在Windows下进行安装和使用Redis的技巧。

Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sortedset --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave。

前言

因为是初次使用,所以是在windows下进行安装和使用,参考了几篇博客,下面整理一下:

安装Redis

官方网站:http://redis.io/   具体使用redis命令和方法请参考官网

官方下载:http://redis.io/download 可以根据需要下载不同版本

windows版:https://github.com/MSOpenTech/redis/tree/2.6

github的资源可以ZIP直接下载的(这个是给不知道的同学友情提示下)。

下载完成后 可以右键解压到 某个硬盘下 比如D:\Redis\redis-2.6。

在D:\Redis\redis-2.6\bin\release下 有两个zip包 一个32位一个64位。

根据自己windows的位数 解压到D:\Redis\redis-2.6根目录下。

2.启动Redis

进入redis目录后 开启服务  (注意加上redis.conf)

1.  redis-server.exe redis.conf

这个窗口要保持开启  关闭时redis服务会自动关闭

redis会自动保存数据到硬盘 所以图中是我第二次开启时 多了一个 DB loaded from disk

3.测试使用

另外开启一个命令行窗口 进入redis目录下 (注意修改自己的ip)

1.  redis-cli.exe -h 192.168.10.61 -p 6379

2.   windows环境下通过c++使用redis

环境:VS2010

1.  新建一个Win32 ConsoleApplication工程

2.  将工程属性->C/C++->CodeGeneration->Runtime Library设置为Multi-threadedDebug(Debug版本)或Multi-threaded(Release版本)

3.  将hiredis.h文件放到工程目录下,将hiredis.lib文件放到Debug或Release目录下,总之让程序能找到hiredis.lib文件

程序如下:

#include"stdafx.h"

#include"hiredis.h"

#pragmacomment(lib, "hiredis.lib")

#pragmacomment(lib, "ws2_32.lib")

void doTest()

{

//初始化ws2_32库

WSADATA wsaData;

WSAStartup(MAKEWORD(2,1), &wsaData);

int timeout = 10000;

struct timeval tv;

tv.tv_sec = timeout /1000;

tv.tv_usec = timeout *1000;

//以带有超时的方式链接Redis服务器,同时获取与Redis连接的上下文对象。

//该对象将用于其后所有与Redis操作的函数。

redisContext* c = redisConnect((char*)"127.0.0.1",6379);

if (c->err) {

redisFree(c);

return;

}

const char* command1 ="set stest1 value9";

redisReply* r =(redisReply*)redisCommand(c,command1);

//需要注意的是,如果返回的对象是NULL,则表示客户端和服务器之间出现严重错误,必须重新链接。

//这里只是举例说明,简便起见,后面的命令就不再做这样的判断了。

if (NULL == r) {

redisFree(c);

return;

}

//不同的Redis命令返回的数据类型不同,在获取之前需要先判断它的实际类型。

//至于各种命令的返回值信息,可以参考Redis的官方文档,或者查看该系列博客的前几篇

//有关Redis各种数据类型的博客。:)

//字符串类型的set命令的返回值的类型是REDIS_REPLY_STATUS,然后只有当返回信息是"OK"

//时,才表示该命令执行成功。后面的例子以此类推,就不再过多赘述了。

if (!(r->type == REDIS_REPLY_STATUS &&(strcmp(r->str,"OK")== 0 || strcmp(r->str, "ok") == 0))) {

printf("Failed to execute command[%s].\n",command1);

freeReplyObject(r);

redisFree(c);

return;

}

//由于后面重复使用该变量,所以需要提前释放,否则内存泄漏。

freeReplyObject(r);

printf("Succeed toexecute command[%s].\n",command1);

const char* command2 ="strlen stest1";

r = (redisReply*)redisCommand(c,command2);

if (r->type !=REDIS_REPLY_INTEGER) {

printf("Failed to execute command[%s].\n",command2);

freeReplyObject(r);

redisFree(c);

return;

}

int length =r->integer;

freeReplyObject(r);

printf("The lengthof ‘stest1‘ is %d.\n",length);

printf("Succeed toexecute command[%s].\n",command2);

const char* command3 ="get stest1";

r =(redisReply*)redisCommand(c,command3);

if (r->type !=REDIS_REPLY_STRING) {

printf("Failed to execute command[%s].\n",command3);

freeReplyObject(r);

redisFree(c);

return;

}

printf("The valueof ‘stest1‘ is %s.\n",r->str);

freeReplyObject(r);

printf("Succeed toexecute command[%s].\n",command3);

const char* command4 ="get stest2";

r =(redisReply*)redisCommand(c,command4);

//这里需要先说明一下,由于stest2键并不存在,因此Redis会返回空结果,这里只是为了演示。

if (r->type !=REDIS_REPLY_NIL) {

printf("Failed to execute command[%s].\n",command4);

freeReplyObject(r);

redisFree(c);

return;

}

freeReplyObject(r);

printf("Succeed toexecute command[%s].\n",command4);

const char* command5 ="mget stest1 stest2";

r = (redisReply*)redisCommand(c,command5);

//不论stest2存在与否,Redis都会给出结果,只是第二个值为nil。

//由于有多个值返回,因为返回应答的类型是数组类型。

if (r->type !=REDIS_REPLY_ARRAY) {

printf("Failed to execute command[%s].\n",command5);

freeReplyObject(r);

redisFree(c);

//r->elements表示子元素的数量,不管请求的key是否存在,该值都等于请求是键的数量。

assert(2== r->elements);

return;

}

int i;

for (i = 0; i <r->elements; ++i) {

redisReply* childReply = r->element[i];

//之前已经介绍过,get命令返回的数据类型是string。

//对于不存在key的返回值,其类型为REDIS_REPLY_NIL。

if(childReply->type == REDIS_REPLY_STRING)

printf("The value is %s.\n",childReply->str);

}

//对于每一个子应答,无需使用者单独释放,只需释放最外部的redisReply即可。

freeReplyObject(r);

printf("Succeed toexecute command[%s].\n",command5);

printf("Begin totest pipeline.\n");

//该命令只是将待发送的命令写入到上下文对象的输出缓冲区中,直到调用后面的

//redisGetReply命令才会批量将缓冲区中的命令写出到Redis服务器。这样可以

//有效的减少客户端与服务器之间的同步等候时间,以及网络IO引起的延迟。

//至于管线的具体性能优势,可以考虑该系列博客中的管线主题。

/* if (REDIS_OK !=redisAppendCommand(c,command1)

||REDIS_OK != redisAppendCommand(c,command2)

||REDIS_OK != redisAppendCommand(c,command3)

||REDIS_OK != redisAppendCommand(c,command4)

||REDIS_OK != redisAppendCommand(c,command5)) {

redisFree(c);

return;

}

*/

redisAppendCommand(c,command1);

redisAppendCommand(c,command2);

redisAppendCommand(c,command3);

redisAppendCommand(c,command4);

redisAppendCommand(c,command5);

redisReply* reply =NULL;

//对pipeline返回结果的处理方式,和前面代码的处理方式完全一直,这里就不再重复给出了。

if (REDIS_OK !=redisGetReply(c,(void**)&reply)) {

printf("Failed to execute command[%s] withPipeline.\n",command1);

freeReplyObject(reply);

redisFree(c);

}

freeReplyObject(reply);

printf("Succeed toexecute command[%s] with Pipeline.\n",command1);

if (REDIS_OK !=redisGetReply(c,(void**)&reply)) {

printf("Failed to execute command[%s] withPipeline.\n",command2);

freeReplyObject(reply);

redisFree(c);

}

freeReplyObject(reply);

printf("Succeed toexecute command[%s] with Pipeline.\n",command2);

if (REDIS_OK !=redisGetReply(c,(void**)&reply)) {

printf("Failed to execute command[%s] withPipeline.\n",command3);

freeReplyObject(reply);

redisFree(c);

}

freeReplyObject(reply);

printf("Succeed toexecute command[%s] with Pipeline.\n",command3);

if (REDIS_OK !=redisGetReply(c,(void**)&reply)) {

printf("Failed to execute command[%s] withPipeline.\n",command4);

freeReplyObject(reply);

redisFree(c);

}

freeReplyObject(reply);

printf("Succeed toexecute command[%s] with Pipeline.\n",command4);

if (REDIS_OK !=redisGetReply(c,(void**)&reply)) {

printf("Failed to execute command[%s] withPipeline.\n",command5);

freeReplyObject(reply);

redisFree(c);

}

freeReplyObject(reply);

printf("Succeed toexecute command[%s] with Pipeline.\n",command5);

//由于所有通过pipeline提交的命令结果均已为返回,如果此时继续调用redisGetReply,

//将会导致该函数阻塞并挂起当前线程,直到有新的通过管线提交的命令结果返回。

//最后不要忘记在退出前释放当前连接的上下文对象。

redisFree(c);

return;

}

int main()

{

doTest();

return 0;

}

3.将Redis做为windows服务

Redis的服务器运行时总有个窗口, 感觉很讨厌,发布软件给人的感觉不正规,本打算自己写个服务程序,把Redis-server封装一下,可是发现一篇文章。http://www.cnblogs.com/shanyou/archive/2013/01/17/redis-on-windows.html,原来人家早就有这个功能了。

https://github.com/MSOpenTech/redis下载了一份Redis 2.6

打算编译一个RedisWatcher,使Redis做为Windows的服务运行。

编译失败。

需要安装Wix,在http://wix.codeplex.com/下载了一个3.8的版本。

安装后进入VS2010重新编译,出现错误LGHT0094,Google了好久,终于找到办法

<EnableProjectHarvesting>True</EnableProjectHarvesting> ,编译成功。

我的系统是XP,运行InstallWatcher.msi,安装成功,在服务里也出现了redis watcher启动类型为自动。

运行服务失败。1053 服务没有及时响应启动或控制请求。

重启系统也没用什么作用。

在Win7下安装InstallWatcher.msi正常,启动服务正常,Redis也可以正常使用。

开始以为是Wix版本太高,降回到3.6还是老样子。

实在没有办法了,用Dependency Walker看了一下,发现使用ADVAPI32.DLL中的EventRegister、EventUnregister、EventWrite三个函数,而我的系统中的advapi32.dll没有这三个函数。查了一下,发现这几个函数要求的最低版本是WidnowsVista。

没办法,手工把这几个函数去掉吧。

在RedisWatcher.h中,将使用这几个函数的位置都直接注释掉,直接返回ERROR_SUCCESS。

编译……成功,然后VS2010会提示,RedisWatcher.h在外部被修改,是否需要更新,更新进来一看。

RedisWatcher.h又回复了我修改之前的状态。

编译出来的exe文件还是老样子

反复了几次,这个文件还是会被自动恢复。

实在没有办法,用Filemon监控哪些进程读写了RedisWatcher.h,大部分都是cl.exe和devenv.exe,偶然发现有个mc.exe

查了一下,发现这个很奇妙的东西。

http://technet.microsoft.com/zh-cn/library/aa385638

在服务程序中将服务的运行的状态写到日志里,这时就要自己生成一个消息表,将这些消息放到程序里,用ReportEvent就能将记录写到日志里

MC.exe是一个可以生成消息资源文件的工具,生成后的文件可以供应用程序或者DLL使用。

会自动生成*.h,*.rc,*.bin 。

在工程的设置里BuildEvents->Pre-Build Event中存在

mc -um $(ProjectName).man -h "$(ProjectDir)\" -z $(ProjectName)

大致看了下mc的文档,发现有个-mof参数,可以生成支持vsita以前的版本。

mc -um -mof $(ProjectName).man -h "$(ProjectDir)\" -z $(ProjectName)

再次生成的RedisWatcher.h的确没有了那三个函数,可是编译出了一堆错误。也没有心情和时间去细研究Wix和mc,就把正常生成的RedisWatcher.h里自动生成的关于写日志的函数全都去掉。再把mc也去掉。

这次编译成功了,安装后服务也能正常启动。暂时算是成功。

InstallWatcher.msi

redis-benchmark.exe

redis-check-aof.exe

redis-check-dump.exe

redis-cli.exe

redis-server.exe

redis.conf

RedisWatcher.exe

RedisWatcher.man

watcher.conf

这些文件复制到redis-2.6\msvs\install\x32目录

然后编译RedisInstall.sln,将会直接生成一个RedisInstall32.msi就可以直接安装,同时选择安装做为服务了。

1.   测试结果

自己写了一个小程序测试下redis数据库的速度如下:

执行100000次hmset user%d key1 value1key2 value2命令用时6.8秒左右

执行1000000次hmset user%d key1value1 key2 value2命令用时70.9秒左右

参考资料:

1.Windows下Redis的安装使用

http://os.51cto.com/art/201403/431103.htm

2.c++使用redis

http://www.360doc.com/content/13/0606/11/10072361_290882627.shtml

3.Redis做为windows服务的曲折过程

http://blog.csdn.net/yuanyingtanxi/article/details/17145163

时间: 2024-10-04 12:28:19

windows环境下通过c++使用redis的相关文章

windows环境下配置php和redis

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. 一.Window 下安装 下载地址:https://github.com/dmajkic/redis/downloads. 下载到的Redis支持32bit和64bit.根据自己实际情况选择,将64bit的内容cp到自定义盘符安装目录取名redis. 如 C:\reids 打开一个cmd窗口 使用cd命令切换目录到 C:\redis 运行 redis-server.exe redis.conf 如果想方便的话

Windows环境下使用Redis缓存工具的图文详细方法

网上找了两篇关于Redis的博客,记录下! Java 使用Redis缓存工具的图文详细方法 Windows环境下使用Redis缓存工具的图文详细方法

Windows环境下搭建Redis

当网站从数据库加载大量数据的时候会遇到页面响应速度特别缓慢的情形,为了能够更快的从数据库中取得数据加载至内存中,可以考虑使用Memcached来做数据缓存,或者使用内存数据库(比如Redis)将数据库的内容加载至内存中以键值对的形式存储,当页面请求数据的时候可以直接从内存数据库中获取,从而提高了网站的响应速度. Redis在官方文档中声明推荐在Linux环境下安装部署,但实际情况下会有很多开发者需要在Windows环境下解决以上类似的问题并想要采取Redis方案来解决问题,好在微软开放了这方面的

在windows环境下安装redis和phpredis的扩展

在windows环境下安装redis和phpredis的扩展 1.首先配置php: 需要在windows的集成环境中找到php的扩展文件夹,ext,然后在网上寻找自己的php对应的.dll文件 比如说的我的phpinfo里面显示是Arti..:x86,所以需要选择X86,这个跟系统无关,我的系统还是64位的呢! 然后我的集成环境是ts而不是nts这个都可以在phpinfo文件中找到! 下载文件php_igbinary.dll,php_redis.dll 然后修改配置文件php.ini(php文件

Windows环境下Redis

Redis 是一个高性能的key-value数据库, 使用内存作为主存储,数据访问速度非常快,当然它也提供了两种机制支持数据持久化存储.比较遗憾的是,Redis项目不直接支持Windows,Windows版项目是由微软开放技术团队建立和维护一个实验性项目(支持32,64位),所以并不适用生产环境,但可在Windows环境下用于开发测试. 1.下载安装 猛戳这里就到了开源首页,下载源码包,解压ZIP包后进入msvs\bin\release文件夹有三个文件分别对应32,64位,windows服务三个

windows环境下Redis的应用

Redis(REmote DIctionary Server)是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型. Redis下载

定制windows环境下cmd替代软件ConEmu

定制windows环境下cmd替代软件ConEmu 公认的是Windows环境下命令行界面太难用. 不管是cmd还是powershell都不顺手!!窗口宽度不能全屏,字体太难看还不能调整,窗口背景不能更换,永远的黑白配,最痛苦的是复制和粘贴.都不知道MS是怎么想的?搞个这么个反人类的东西出来,还万年不变,从Windows诞生到Windows7不论是桌面版还是服务器版都一样,到了windows8/windows10换成powershell一样的鸡肋. 在百度搜了一下,找到cmd的替代软件conem

《高可用MySQL》1 – Windows环境下压缩版MySQL安装

近日在读O'REILIY系列的<高可用MySQL>, 自然少不了主从(Master-Slave)配置和横向扩展相关的内容. Master-Slave这东西吧.在很多公司都是标配.开发中基本天天都用.遇到的问题自然也不少(如主从不同步,Master宕机).但操作权限很有限.有些东西,仅仅有自己看了.做了,才干真正知道原理是什么,也才干更好的去把握. 本文是高可用MySQL的第一篇读书笔记,主要记录Windows环境下压缩版MySQL(基于安装版的傻瓜式安装过程这里不再提及)的安装过程. 1. 从

python MySQLdb在windows环境下的快速安装、问题解决方式

使用Python访问MySQL,需要一系列安装 Linux下MySQLdb安装见 Python MySQLdb在Linux下的快速安装 http://blog.csdn.net/wklken/article/details/7271019 ------------------------------------------------------------- 以下是windows环境下的: 1.      安装数据库mysql 下载地址:http://www.mysql.com/downloa