Chinaunix首页 | 论坛 | 博客
  • 博客访问: 621346
  • 博文数量: 116
  • 博客积分: 6078
  • 博客等级: 准将
  • 技术积分: 1214
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 10:09
文章分类

全部博文(116)

文章存档

2016年(1)

2015年(4)

2011年(2)

2010年(21)

2009年(88)

分类: NOSQL

2015-02-06 12:48:41

最近在考虑如何把c++ 和java,python,go lang在内存中进行数据交换,想到了redis,所以了解下,而Protobuf是一个很好的跨语言的序列化及反序列化工具,故而用网友的此文作一个参考:
原贴:http://blog.csdn.net/eclipser1987/article/details/8534669

google protocol buffer 可以将对象序列化,而redis作为优秀的NOSQL数据库,这里我将以实例方式介绍,将C++对象序列化,并存放在redis数据库中!

 

google protocol buffer 的安装以及基础使用可以阅读我上一片文章.

redis的安装使用,可以查阅,这里不再描述.我使用redis的官方C client: hiredis.

 

protobuf 对象模型:

  1. package cn.vicky.model.seri;  
  2.   
  3. message User {  
  4.     required int32 id = 1; // 主键,唯一  
  5.     required string username = 2; // 帐号  
  6.     required string password = 3; // 密码  
  7.     optional string email = 4; // 邮箱(可选)  
  8.     repeated Person person = 5; // 账户拥有的角色(可以重复)  
  9. }  
  10.   
  11. message Person {   
  12.     required int32 id = 1; // 主键,唯一  
  13.     required string name = 2; // 角色名字  
  14.   
  15.     repeated PhoneNumber phone = 3; // 电话号码(可以重复)  
  16. }   
  17.   
  18. // 枚举类型  
  19. enum PhoneType {   
  20.     MOBILE = 0;   
  21.     HOME = 1;   
  22.     WORK = 2;   
  23. }   
  24.   
  25. message PhoneNumber {   
  26.     required string number = 1;   
  27.     optional PhoneType type = 2 [default = HOME];   
  28. }   


 

创建工程:

在生成对应的model.pb.h  model.pb.cc 更多请阅读我上一篇文章.

将hiredis.h以及依赖库引入项目中.这里以静态链接库形式  /usr/lib/libhiredis.a

编写main,cpp

  1. /*  
  2.  * File:   main.cpp 
  3.  * Author: Vicky.H 
  4.  * Email:  eclipser@163.com 
  5.  */  
  6. #include   
  7. #include   
  8. #include "model.pb.h"  
  9. #include "hiredis.h"  
  10.   
  11. /* 
  12.  *  
  13.  */  
  14. int main(void) {  
  15.   
  16.     // 创建User对象  
  17.     cn::vicky::model::seri::User u;  
  18.     u.set_id(1);  
  19.     u.set_username("Jack");  
  20.     u.set_password("123456");  
  21.     u.set_email("289997171@qq.com");  
  22.   
  23.     // 创建User中的一个角色  
  24.     cn::vicky::model::seri::Person* _person1 = u.add_person();  
  25.     _person1->set_id(1);  
  26.     _person1->set_name("P1");  
  27.   
  28.     // 创建角色中的一个电话号码:1  
  29.     cn::vicky::model::seri::PhoneNumber* _phone1 = _person1->add_phone();  
  30.     _phone1->set_number("+8613618074943");  
  31.     _phone1->set_type(cn::vicky::model::seri::MOBILE);  
  32.   
  33.     // 创建角色中的一个电话号码:2  
  34.     cn::vicky::model::seri::PhoneNumber* _phone2 = _person1->add_phone();  
  35.     _phone2->set_number("02882334717");  
  36.     _phone2->set_type(cn::vicky::model::seri::WORK);  
  37.   
  38.   
  39.     // 创建User中的一个角色  
  40.     cn::vicky::model::seri::Person* _person2 = u.add_person();  
  41.     _person2->set_id(2);  
  42.     _person2->set_name("P2");  
  43.   
  44.     // 创建角色中的一个电话号码:1  
  45.     cn::vicky::model::seri::PhoneNumber* _phone3 = _person2->add_phone();  
  46.     _phone3->set_number("+8613996398667");  
  47.     _phone3->set_type(cn::vicky::model::seri::MOBILE);  
  48.   
  49.     // 创建角色中的一个电话号码:2  
  50.     cn::vicky::model::seri::PhoneNumber* _phone4 = _person2->add_phone();  
  51.     _phone4->set_number("02882334717");  
  52.     _phone4->set_type(cn::vicky::model::seri::WORK);  
  53.   
  54.   
  55.     // 将对象以二进制保存  
  56.     const int byteSize = u.ByteSize();  
  57.     std::cout << "byteSize = " << byteSize << std::endl;  
  58.     char buf[byteSize];  
  59.     bzero(buf, byteSize);  
  60.     u.SerializeToArray(buf, byteSize);  
  61.   
  62.   
  63.     // 建立redis链接  
  64.     redisContext *c;  
  65.     redisReply *reply;  
  66.   
  67.     struct timeval timeout = {1, 500000}; // 1.5 seconds  
  68.     c = redisConnectWithTimeout((char*) "127.0.0.1", 3307, timeout);  
  69.     if (c->err) {  
  70.         printf("Connection error: %s\n", c->errstr);  
  71.         exit(1);  
  72.     }  
  73.   
  74. //    第一次执行:将对象写入redis数据库  
  75. //    reply = (redisReply*) redisCommand(c, "SET %b %b", u.username().c_str(), (int) u.username().length(), buf, byteSize); // 重点!!!  
  76. //    printf("SET (binary API): %s\n", reply->str);  
  77. //    freeReplyObject(reply);  
  78.   
  79. //    第二次执行:从redis数据库读取对象数据  
  80.     reply = (redisReply*) redisCommand(c, "Get Jack");  
  81.     std::cout << "reply->len = " << reply->len << "\nreply->str : \n" << reply->str << std::endl; // 这里打印不完  
  82.   
  83.     std::cout << "---------------------------" << std::endl;  
  84.   
  85.     cn::vicky::model::seri::User u2;  
  86.     u2.ParseFromArray(reply->str, reply->len);  
  87.   
  88.     std::cout << u2.id() << std::endl;  
  89.     std::cout << u2.username() << std::endl;  
  90.     std::cout << u2.password() << std::endl;  
  91.     std::cout << u2.email() << std::endl;  
  92.   
  93.     std::cout << "---------------------------" << std::endl;  
  94.     for (int i = 0; i < u2.person_size(); i++) {  
  95.         cn::vicky::model::seri::Person* p = u2.mutable_person(i);  
  96.         std::cout << p->id() << std::endl;  
  97.         std::cout << p->name() << std::endl;  
  98.         for (int j = 0; j < p->phone_size(); j++) {  
  99.             cn::vicky::model::seri::PhoneNumber* phone = p->mutable_phone(j);  
  100.             std::cout << phone->number() << std::endl;  
  101.         }  
  102.         std::cout << "---------------------------" << std::endl;  
  103.     }  
  104.     return 0;  
  105. }  


 

首先:

[root@localhost ~]# redis-cli -p 3307
redis 127.0.0.1:3307> DEL Jack
(integer) 1
redis 127.0.0.1:3307> 

运行第一个注释,将对象写入redis:

byteSize = 124
SET (binary API): OK
0

这里已经成功将User u的对象写入到redis中了,我们可以通过redis查看:

redis 127.0.0.1:3307> GET Jack
"\b\x01\x12\x04Jack\x1a\x06123456\"\x10289997171@qq.com*+\b\x01\x12\x02P1\x1a\x12\n\x0e+8613618074943\x10\x00\x1a\x0f\n\x0b02882334717\x10\x02*+\b\x02\x12\x02P2\x1a\x12\n\x0e+8613996398667\x10\x00\x1a\x0f\n\x0b02882334717\x10\x02"

 

运行第二个注释,从redis中读取Jack数据,并反序列化生成User u2;

结果:

byteSize = 124
reply->len = 124
reply->str : 
Jack123456"289997171@qq.com*P1           直接打印二进制数据是不正确的!!!
+8613618074943
---------------------------
1
Jack
123456

---------------------------
1
P1
+8613618074943
02882334717
---------------------------
2
P2
+8613996398667
02882334717
---------------------------

 

Great...那么,protobuf 与 redis的结合成功了!

个人认为,这种面向对象,并且跨语言,在存储和读取依赖redis内存数据库的基础上是非常的高性能!

阅读(2350) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~