protobuf 与 redis 的结合

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了protobuf 与 redis 的结合相关的知识,希望对你有一定的参考价值。

这是一个很不错的想法。

于是我去验证了一下。

然后我如愿以偿的失败了。

接着我验证了前辈的代码。

学习一下前辈代码中的框架,拿来在自己的业务中使用,八年前的代码,还是比较全面的。


msg.proto

使用的是 PB2,我比较海纳百川,那就用PB2吧(其实就是懒,不想改代码)

package cn.vicky.model.seri;
 
message User 
    required int32 id = 1; // 主键,唯一
    required string username = 2; // 帐号
    required string password = 3; // 密码
    optional string email = 4; // 邮箱(可选)
    repeated Person person = 5; // 账户拥有的角色(可以重复)

 
message Person  
    required int32 id = 1; // 主键,唯一
    required string name = 2; // 角色名字
 
    repeated PhoneNumber phone = 3; // 电话号码(可以重复)
 
 
// 枚举类型
enum PhoneType  
    MOBILE = 0; 
    HOME = 1; 
    WORK = 2; 
 
 
message PhoneNumber  
    required string number = 1; 
    optional PhoneType type = 2 [default = HOME]; 
 

test.cc

为啥用个cc呢,一会儿编译起来比较简单。

/* 
 * File:   main.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 */
#include <iostream>
#include <fstream>
#include "model.pb.h"
#include "hiredis.h"
 
int main(void) 
 
    // 创建User对象
    cn::vicky::model::seri::User u;
    u.set_id(1);
    u.set_username("Jack");
    u.set_password("123456");
    u.set_email("289997171@qq.com");
 
    // 创建User中的一个角色
    cn::vicky::model::seri::Person* _person1 = u.add_person();
    _person1->set_id(1);
    _person1->set_name("P1");
 
    // 创建角色中的一个电话号码:1
    cn::vicky::model::seri::PhoneNumber* _phone1 = _person1->add_phone();
    _phone1->set_number("+8613618074943");
    _phone1->set_type(cn::vicky::model::seri::MOBILE);
 
    // 创建角色中的一个电话号码:2
    cn::vicky::model::seri::PhoneNumber* _phone2 = _person1->add_phone();
    _phone2->set_number("02882334717");
    _phone2->set_type(cn::vicky::model::seri::WORK);
 
 
    // 创建User中的一个角色
    cn::vicky::model::seri::Person* _person2 = u.add_person();
    _person2->set_id(2);
    _person2->set_name("P2");
 
    // 创建角色中的一个电话号码:1
    cn::vicky::model::seri::PhoneNumber* _phone3 = _person2->add_phone();
    _phone3->set_number("+8613996398667");
    _phone3->set_type(cn::vicky::model::seri::MOBILE);
 
    // 创建角色中的一个电话号码:2
    cn::vicky::model::seri::PhoneNumber* _phone4 = _person2->add_phone();
    _phone4->set_number("02882334717");
    _phone4->set_type(cn::vicky::model::seri::WORK);
 
 
    // 将对象以二进制保存
    const int byteSize = u.ByteSize();
    std::cout << "byteSize = " << byteSize << std::endl;
    char buf[byteSize];
    bzero(buf, byteSize);
    u.SerializeToArray(buf, byteSize);
 
 
    // 建立redis链接
    redisContext *c;
    redisReply *reply;
 
    struct timeval timeout = 1, 500000; // 1.5 seconds
    c = redisConnectWithTimeout((char*) "127.0.0.1", 3307, timeout);
    if (c->err) 
        printf("Connection error: %s\\n", c->errstr);
        exit(1);
    
 
//    第一次执行:将对象写入redis数据库
//    reply = (redisReply*) redisCommand(c, "SET %b %b", u.username().c_str(), (int) u.username().length(), buf, byteSize); // 重点!!!
//    printf("SET (binary API): %s\\n", reply->str);
//    freeReplyObject(reply);
 
//    第二次执行:从redis数据库读取对象数据
    reply = (redisReply*) redisCommand(c, "Get Jack");
    std::cout << "reply->len = " << reply->len << "\\nreply->str : \\n" << reply->str << std::endl; // 这里打印不完
 
    std::cout << "---------------------------" << std::endl;
 
    cn::vicky::model::seri::User u2;
    u2.ParseFromArray(reply->str, reply->len);
 
    std::cout << u2.id() << std::endl;
    std::cout << u2.username() << std::endl;
    std::cout << u2.password() << std::endl;
    std::cout << u2.email() << std::endl;
 
    std::cout << "---------------------------" << std::endl;
    for (int i = 0; i < u2.person_size(); i++) 
        cn::vicky::model::seri::Person* p = u2.mutable_person(i);
        std::cout << p->id() << std::endl;
        std::cout << p->name() << std::endl;
        for (int j = 0; j < p->phone_size(); j++) 
            cn::vicky::model::seri::PhoneNumber* phone = p->mutable_phone(j);
            std::cout << phone->number() << std::endl;
        
        std::cout << "---------------------------" << std::endl;
    
    return 0;

使用的时候呢,先把那个插入数据的代码放出来,把数据插进去,再用后面读的去读(其实也可以一气呵成,我就直接放出来了)


主要是这个框架,自己剥一下拿去用吧。

以上是关于protobuf 与 redis 的结合的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 使用 Redis 和 Protobuf

grpc和protobuf结合的示例

python中的Protobuf文件版本控制

连信的protobuf数据格式

SpringSpring缓存机制与Redis的结合

Redis学习之旅--与SpringBoot的结合