redis中读取字符串最简单的方式是get key,对于同一时间读取多个key的情况,如果是循环读取,那么代价会很大,特别是使用云服务或者远程网络连接的额定带宽下的redis。此时,最常用的是通过批batch处理的方法,两种加速的方法:(mset、mget)和pipeline。首先看下如何通过hiredis接口调用这几个指令,关于hiredis其本功能介绍,可以参考之前的文章:hiredis接口分析 hiredis读写二进制 异步接口。

首先看下mset指令为:

mset key1 value1 key2 value2 ........

依次设定各个key以及对应的值,该指令比较容易实现:

int mSetCmd(redisContext* rc, vector<std::string> keys, vector<std::string> values)
{if(keys.size()!=values.size())return -1;std::string strCmd = "MSET";for(int i = 0; i < keys.size(); i++){strCmd += " "+keys[i]+" "+values[i];}redisReply *reply=(redisReply*)redisCommand(rc, strCmd.c_str());if (reply == NULL) return -1;return 0;
}

这里实现很简单,通过vector传送多个键值以及对应的值。mget指令为:

mget key1 key2 .....

依次请求各个key的值,会按照key值依次按行返回value,实现代码如下:

int mGetCmd(redisContext* rc,vector<std::string> keys,vector<std::string>& values)
{std::string strCmd = "MGET";for(int i=0;i<keys.size();i++){strCmd += " "+keys[i];}redisReply *reply=(redisReply*)redisCommand(rc, strCmd.c_str());if(reply->type != REDIS_REPLY_ARRAY)//返回必须是数列的形式{printf("mget failed!");return -1;} for (int i = 0; i < reply->elements; ++i) {  redisReply* childReply = reply->element[i]; if (childReply->type == REDIS_REPLY_STRING){std::string strTmp(childReply->str);values.push_back(strTmp);       }}return 0;
}

与之前的hiredis指令不同,这里返回的不是连续的一块缓存,而是数列的形式,每一个reply的数组成员element[],每一个值对应一个键值对。

下面我们来看pipeline,其原理很简单,pipeline就是把所有的命令一次发过去,避免频繁的发送、接收带来的网络开销,redis在打包接收到一堆命令后,依次执行,然后把结果再打包返回给客户端,实现代码如下:

int pipeLineCmd(redisContext* rc,std::vector<std::string> & pipeLineCmd, std::vector<std::string> &pipeLineReq, std::vector<bool> &pipeLineReqStatus)
{for(int i=0;i<pipeLineCmd.size();i++){redisAppendCommand(rc, pipeLineCmd[i].c_str());}for (int i = 0; i < pipeLineCmd.size();i++){bool status = false;std::string resp_str = "";redisReply *reply = 0;if(redisGetReply(rc, (void **)&reply) == REDIS_OK&& reply != NULL&& reply->type == REDIS_REPLY_STRING){status = true;resp_str = reply->str;}//freefreeReplyObject(reply);pipeLineReqStatus.push_back(status);pipeLineReq.push_back(resp_str);}
}

在之前的分析文章中可以知道,只是将待发送的命令写入到上下文对象的输出缓冲区中,即将命令拷贝到context的obuf里,直到调用后面的redisGetReply命令才会批量将缓冲区中的命令写出到Redis服务器。这样可以有效的减少客户端与服务器之间的同步等候时间,以及网络IO引起的延迟。redisGetReply依次执行如下步骤:1.从reply队列里面返回最前面的reply,如果队列为空,继续后面的操作;2.如果发现obuf中有数据没有发送,那么发送cmd;3.等待回包(server会把cmd中所有的处理做完,然后回包,appand过几次,server就会返回几个reply);收到回包后,redisGetReply里面解析回包为reply(可能为多个,具体数量跟appand次数相同)。

对于两种操作的性能可以参考:https://github.com/redis/redis-rb/tree/master/benchmarking

对10k个记录进行读,其性能测试结果如下

user system total real
get 1.46 0.580226 2.050099 ( 12.701514)
pipeline with 10 each  0.74 0.300464 1.041347 ( 2.975966)
pipeline with 100 each  0.54 0.219881 0.766023 ( 1.368800)
pipeline with 1000 each  0.51 0.200081 0.716371 ( 1.403288)
pipeline with 10000 each  0.47 0.200489 0.672237 ( 1.201756)
mget with 10 each  0.22 0.061788 0.289068 ( 2.317538)
mget with 100 each  0.08 0.008353 0.092111 ( 0.240111)
mget with 1000 each  0.06 0.001894 0.063780 ( 0.085815)
mget with 10000 each  0.05 0.001459 0.057561 ( 0.070013)

从测试结果来看,mget的性能要更好一点,这与其处理的简化和高效有关。

redis批处理操作:基于hiredis实现相关推荐

  1. C/C++编程操作Redis数据库,hiredis包装redis数据库操作接口及测试(增删改查与连接)

    介绍一个实际应用场景,对于客户频繁需要查询的信息,可以将其放在redis内存数据库中,相当于一个缓存,每次查的时候先去redis内存数据库中去查询,如果查询不到再去oracle数据库中查询,这样提高了 ...

  2. python redis连接池获取后关闭_python通过连接池连接redis,操作redis队列

    在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用 ...

  3. redis php操作日志,php-redis笔记

    php-redis笔记 介绍 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使 ...

  4. 批处理 操作mysql_超简单使用批处理(batch)操作数据库

    超简单使用批处理(batch)操作数据库 批处理(batch)是什么 批处理的执行就好比快递员的工作: 未使用批处理的时候,快递员一次从分发点将一件快递发给客户: 使用批处理,则是快递员将所有要派送的 ...

  5. python连接redis有中文_Python连接Redis并操作

    首先开启redis的外连 sch01ar@ubuntu:~$ sudo vim /etc/redis/redis.conf 把bind 127.0.0.1这行注释掉 然后重启redis sudo /e ...

  6. Redis-学习笔记02【Redis命令操作】

    Java后端 学习路线 笔记汇总表[黑马程序员] Redis-学习笔记01[Redis环境搭建] Redis-学习笔记02[Redis命令操作] Redis-学习笔记03[Redis持久化] Redi ...

  7. php连接redis的操作库predis操作大全

    predis是php连接redis的操作库,由于它完全使用php编写,大量使用命名空间以及闭包等功能,只支持php5.3以上版本,故实测性能一般,每秒25000次读写,相信改换c语言编写的php扩展后 ...

  8. Python Redis pipeline操作(秒杀实现)

    Python Redis pipeline操作(秒杀实现) 设想这样的一个场景,你要批量的执行一系列redis命令,例如执行100次get key,这时你要向redis请求100次+获取响应100次. ...

  9. Redis数据库操作指令

    # 1.Redis中库说明 - 使用redis的默认配置器动redis服务后,默认会存在16个库,编号从0-15 - 可以使用select 库的编号 来选择一个redis的库# 2.Redis中操作库 ...

最新文章

  1. C# 常用正责表达式
  2. 综述论文要写英文摘要吗_速成本科毕业论文初稿!!!
  3. SAP plant and location
  4. Android:IntentService的学习
  5. WebSocket 实现前后端通信的笔记
  6. 微信重大更新,mac版可刷朋友圈!可以看,可以评论! 支持M1
  7. android多个单选按钮互斥使用,在GUI设计中,单选按钮用来实现用户在多个选项中的互斥选择,在同一组内多个选项中只能选择一个,当...
  8. Unity3D学习1--Unity基础
  9. vue中的数据可视化(echarts)和highcharts
  10. 在Word中快速插入分隔线
  11. Android10.0应用图标隐藏方案(7.0-10.0)
  12. ff14服务器延迟滑步,ff14 5.0黑魔怎么玩_最终幻想14 5.0黑魔输出手法
  13. python如何爬有道翻译_Python网络爬虫(八) - 利用有道词典实现一个简单翻译程序...
  14. ZBrush中常用3D笔触效果
  15. k m kb mb计算机组成,为什么对计算机存储单位(K,M,G,T)换算,总是糊里又糊涂?
  16. python实例豆瓣代码_Python实例:通过selenium模拟登陆豆瓣
  17. 尼尔机械纪元安卓机器人_尼尔机械纪元安卓正版下载-尼尔机械纪元steam下载-k73游戏之家...
  18. StarUML用户手册
  19. 麦当劳中国开心乐园餐重磅升级:由三件套升级为四件套
  20. ADA语言Hello World

热门文章

  1. 规模最小的计算机网络至少有几台,【单选题】按照网络规模大小定义计算机网络,其中规模最小的是 A. 广域网 B. Internet C. 城域网 D. 局域网...
  2. mkv to mp4
  3. 网吧技术维护服务合同书
  4. JavaScript知识点总结(十一)- 内置对象
  5. AJAX之二级联动下拉列表
  6. 黑马程序员-集合(Map)
  7. UnityWebRequest带中文路径找不到
  8. 【编译原理】【实验】利用子集法构造DFA
  9. 在java给别人邮箱发邮件
  10. Vite+ts全局引入scss与实际使用