2016-02-15 104 views
2

以下是我用来创建从数据库/ memcached获取数据的GRPC系统的原始文件。如何在memcached中存储protobuf对象?

message CMSContent 
{ 
    repeated ArticleSummary Articles = 1; 
    uint32 RecordCount = 2; 
} 

service Article 
{ 
    rpc ListByCategory(ArticleByCatURI) returns (CMSContent){} 
} 

message ArticleByCatURI 
{ 
    uint32 ApplicationId = 1;   
} 

message ArticleSummary 
{ 
    uint32 ArticleId = 1; 
    string ArticleName = 2; 
} 

我创建了相应的C#类,详见GRPC Getting Started。我在Server上使用这些类来存储数据库查询的结果并尝试将这些对象保存到memcached。不幸的是protobuf对象没有被添加到memcached中。以下是我将其添加到memcached的方式,当我尝试添加它时,isKeyFirstTimeCreated的值为false。

isKeyFirstTimeCreated = mc.Store(StoreMode.Add, key, t, DateTime.Now.Add(cacheDuration)); 

根据memcached的要求,必须存储在memcached中的所有对象都需要Serializable。但自动生成的protobuf类不是可序列化的(至少是c#使用的二进制格式化程序)。现在,由于类是部分实现,所以我将它们设置为可序列化,但由于RepeatedField不是可序列化的,所以这没有帮助。

IMO,应该有一个更好的方法或一些机制,这将允许我将protobuf对象直接保存到memcached中,但不幸的是,谷歌在这方面没有多大帮助。

我可以以两种方式

  • 通过复制protobuf的对象数据的序列化对象实现这一目标,然后将其保存到memcached中供将来

  • 将数据复制到一个serilizable对象并使用该对象来填充protobuf对象。

但是这两个走近需要额外的工作。有没有更好的方法来实现这一目标?

[PS:我使用proto3因此它支持C#]

回答

1

几乎所有的高速缓存存储支持byte[]。像protobuf的工具借给自理直接存储在一个byte[],所以最常见的二进制序列化方式在这里基本上是:

byte[] raw; 
using(var ms = new MemoryStream(ms)) { 
    YourChosenSerializer.Serialize(ms, obj); 
    raw = ms.ToArray(); 
} 
// now store raw 

如果您的存储工具不支持byte[],然后string通常是一个很好的替代品,但二进制串行器应该使用类似base-64编码(通过Convert.ToBase64StringConvert.FromBase64String)进行存储。

至于直接支持这个的memcached库(或类似的):我会建议反对这个分离担忧的原因。但是,扩展方法通常可以很容易地在你自己的代码中用辅助方法在几行中提供。

+0

是的,这对我来说确实有效,比我之前的两种方法好得多。但我想知道我们是否可以做得比这更好。你如何在_protobuf-net_中实现相同的结果?这种方法仍然需要我将Object转换为byte []数组,然后存储数组。我认为protobuf类可以以protobuf格式进行序列化,可能有一种方法可以直接存储这些对象,而不是通过调整某些属性或通过像使用protobuf-net一样设置代码转换器来将它们转换为字节数组。 – GawdePrasad