在memcached中,对象的最佳序列化方法是什么?

25

我的Python应用程序当前使用python-memcached API在memcached中设置和获取对象。该API使用Python本地的pickle模块来序列化和反序列化Python对象。

这个API使得在memcached中存储嵌套的Python列表、字典和元组变得简单快捷,并且将这些对象读回应用程序时完全透明——它只是正常工作。

但我不想仅限于使用Python,如果所有的memcached对象都使用pickle进行序列化,那么使用其他语言编写的客户端就无法工作了。

以下是我考虑过的跨平台序列化选项:

  1. XML-主要优点是它易于阅读,但在这个应用程序中并不重要。而且XML占用很多空间,解析起来也很昂贵。
  2. JSON-看起来是一个很好的跨平台标准,但我不确定它在从memcached读回时是否保留了对象类型的特征。例如,根据这篇文章,当使用simplejson时,元组会被转换为列表;而且似乎向JSON结构添加元素可能会破坏写入旧结构的代码。
  3. Google Protocol Buffers-我对这个非常感兴趣,因为它似乎非常快速、紧凑——至少比XML小10倍,而且似乎设计用于支持扩展结构而不破坏旧代码。

考虑到这个应用程序的优先级,什么是memcached的理想对象序列化方法?

  1. 跨平台支持(Python、Java、C#、C++、Ruby、Perl)
  2. 处理嵌套数据结构
  • 快速序列化/反序列化

  • 最小的内存占用

  • 可以更改结构而不破坏旧代码的灵活性

  • 1
    我认为你首先必须定义要存储的对象类型。你已经指出了元组/列表问题,对于任意数据类型,你会遇到任意问题;-) - max
    1
    我认为重点在于对象类型是任意的。 - cletus
    5个回答

    7
    一个主要的考虑因素是“你是否想要指定每个结构定义”?
    如果您可以接受这一点,那么您可以看一下:
    1. 协议缓冲区 - http://code.google.com/apis/protocolbuffers/docs/overview.html
    2. Thrift - http://developers.facebook.com/thrift/(更加面向服务)
    这两种解决方案都需要支持文件来定义每个数据结构。
    如果您不想承担预定义每个结构的开发人员开销,那么可以看看以下内容:
    1. JSON(通过Python cjson和本机PHP json)。如果您不需要传输二进制内容(例如图像等),则两者都非常快。
    2. Yet Another Markup Language @ http://www.yaml.org/。如果选择正确的库,也非常快。
    但是,我认为这两种方法在传输二进制内容方面都存在问题,这就是为什么它们被排除在我们的使用范围之外的原因。注意:YAML可能具有良好的二进制支持,您将需要检查客户端库——请参见这里:http://yaml.org/type/binary.html
    在我们公司,我们自己开发了一个跨语言序列化库(Extruct),支持二进制。我们目前在Python和PHP中实现了(相当)快速的版本,但由于在所有字符串上使用base64(二进制支持),它不太容易阅读。最终,我们将把它们移植到C,并使用更标准的编码。
    对于循环中有太多迭代或需要查看每个字符的情况,PHP和Python等动态语言会变得非常慢。而C则在这些操作方面表现出色。
    如果您想查看Extruct的实现,请告诉我。(联系信息位于http://blog.gahooa.com/ 的“关于我”中)

    6
    我尝试了几种方法,并选择压缩JSON作为速度和内存占用的最佳平衡点。Python的本地Pickle函数稍微更快,但生成的对象不能与非Python客户端一起使用。
    我看到3:1的压缩比,因此所有数据都适合于memcache,应用程序获得小于10毫秒的响应时间,包括页面呈现。
    以下是JSON、Thrift、Protocol Buffers和YAML的比较,包括有和没有压缩的情况:

    http://bouncybouncy.net/ramblings/posts/more_on_json_vs_thrift_and_protocol_buffers/

    看起来这个测试得出了我使用压缩JSON时的相同结果。由于我不需要预定义每个结构,这似乎是跨平台最快和最小的答案。


    3

    "跨平台支持(Python,Java,C#,C ++,Ruby,Perl)"

    很遗憾这是第一标准。大多数语言背后的意图是以不同的方式表达基本数据结构和处理方式。这就是使多种语言成为“问题”的原因:它们都不同。

    一个在许多语言中都很好的单一表示通常是不可能的。在表示的丰富性、性能或歧义方面存在妥协。

    JSON 很好地满足了其余标准。消息紧凑且解析快速(不像 XML)。嵌套处理得很好。更改结构而不破坏代码始终是棘手的——如果您删除某些内容,旧代码将会失效。如果您更改所需的某些内容,则旧代码将会失效。然而,如果您要添加内容,JSON 也可以处理。

    我喜欢人类可读性。它有助于许多调试和故障排除。

    Python 元组变成列表的微妙之处并不是一个有趣的问题。接收应用程序已经知道正在接收的结构,并且可以进行调整(如果有必要)。


    性能编辑。

    http://developers.de/blogs/damir_dobric/archive/2008/12/27/performance-comparison-soap-vs-json-wcf-implementation.aspx解析XML和JSON文档。

    xmlParse 0.326 jsonParse 0.255

    相同内容下,JSON似乎更快。我使用了Python 2.5.2中的SimpleJSON和ElementTree模块。


    -1 抱歉,但通常情况下XML更快,例如http://dev.robertmao.com/2007/10/01/json-vs-xml-parsing-performance/。当您更新后我会将其删除。人们只是喜欢JSON,因为在Javascript中处理它更容易。 - cletus
    此外,http://developers.de/blogs/damir_dobric/archive/2008/12/27/performance-comparison-soap-vs-json-wcf-implementation.aspx。 - cletus
    有趣的。在这里,JSON更快:http://www.crossedconnections.org/w/index.php/2006/06/20/json-vs-xml-performance-update/ - S.Lott
    虽然有点过时,但是FF 1.5,IE6并没有太大的差别。 - cletus

    2

    如果你愿意放弃可读性,那么一定要去了解一下 msgpack。 - Josh Bleecher Snyder
    Pinterest使用MessagePack来实现这个目的。查看文章:http://engineering.pinterest.com/posts/2012/memcache-games/ - Kazuki Ohta

    1

    我想知道将mustaine修改为支持pickle的所有相同对象类型,特别是Python对象,并添加元组和列表之间的区别有多困难。在当前状态下,它无法用于透明序列化。 - Erik Kaplun

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接