使用简单的map-reduce列出桶中所有键与bucket.get_keys()的对比?

0 投票
2 回答
2494 浏览
提问于 2025-04-17 03:20

根据Riak的文档(使用Python绑定),get_keys()这个方法非常耗费资源,不适合在生产环境中使用。我的问题是,使用一个非常简单的map查询是否合适。例如,只用一个map阶段和这个函数:

function(v) { return [v.key]; }

这样做的性能会比get_keys()好吗?为什么Riak不直接提供这个实现,而是继续使用现在的get_keys()版本?有没有更好的方法来列出一个桶里的键?

2 个回答

2

如果你使用的是eleveldb这个后端(它是用LevelDB库实现的),那么你的键(也就是数据的标识符)会按照顺序存储。这样你就可以做一些类似于以下的操作:

def get_bucket_keys(riak_client, bucket_name, start='0', stop='Z'):
    for record_key in riak_client.index(bucket_name, '$key', start, stop).run():
        yield record_key

for key in get_bucket_keys(riak.RiakClient(), 'mybucket'):
    print key

使用eleveldb时,riak会在所有节点中只扫描你指定的范围。所以,如果你能控制你的桶(数据存储的地方)中的键的范围,那么列出桶中的键会非常高效。

不过,有一个缺点就是你不能为每个节点处理的键的数量设置一个限制。这就是为什么你需要控制你想要列出键的桶中的键。

2

get_keys()这个函数在后台调用了list_keys,这个操作被认为是比较耗费资源的,因为它需要对所有的键进行全面扫描。根据你使用的Riak后端,这个操作可能还需要对存储在磁盘上的数据进行全面扫描(比如InnoStore)。不过,默认的存储后端(Bitcask)会把所有的键都存储在内存中,所以性能问题不会太大。

另外,list_keys被认为耗费资源的原因是,它以前是一个阻塞操作,涉及到Basho开发者所说的对所有键进行“折叠”。现在,list_keys使用的是桶的快照(而不是实时读取键空间),这使得这个操作变得更轻便。

升级到Riak 1.0后,这个操作变得更简单。如果你使用的是LevelDB后端,可以在一个桶上启用二级索引,并使用$key索引(Riak自动提供的)来获取桶中所有键的列表。

至于为什么Riak没有提供更好的实现,关键在于这个功能的用途。在关系型数据库中,获取一个表的所有主键需要对整个表进行扫描。而在Riak中,从一个桶中获取所有键需要扫描每个节点中的所有数据,然后把键名传回原始节点,合并这些数据,再发送给调用的客户端。由于Riak是分布式的、无序的状态,这个操作无论怎么做都是比较耗费资源的。不过,正如我上面提到的,还是有一些方法可以改善这个问题。

撰写回答