在CouchDB中有巨大的b树数据结构和多个进程(每个请求一个)。
Erlang进程不能共享状态——所以似乎应该有专门的进程负责访问BTree并通过消息与其他进程通信。但是这将是低效的——因为只有一个进程可以访问数据。那么在Erland中如何处理这些情况,在CouchDB中如何处理这些情况呢?
问得好。如果你想要一个权威的答案问关于couchdb内部的问题最好的地方是couchdb邮件列表,他们非常快,其中一个核心开发人员可能会给你一个更好的答案。我将尽我所能回答这个问题,只是记住我可能是错的:)
第一条线索由couchdb配置文件提供。在shell模式下启动couchdb
couchdb -i
将浏览器指向
http://localhost:5984/_utils/config.html
您会发现在daemon
部分下有一个键值对
index_server {couch_index_server, start_link, []}
啊哈!所以索引是由服务器提供的。什么样的服务器?我们将不得不深入研究代码:-
是一个gen_server。对couchdb视图的所有操作都由这个gen_server处理。gen_server是客户机服务器模型的erlang通用实现。默认情况下是并发的。所以你的观察是正确的。所有对视图的请求都是在gen_server的帮助下管理的不同进程。
index_server定义了三个et表。您可以通过输入
来验证这一点在我们之前开始的erlang shell中 ets:i()
,您应该看到:-
couchdb_indexes_by_db couchdb_indexes_by_db bag 1 320 couch_index_server
couchdb_indexes_by_pid couchdb_indexes_by_pid set 1 316 couch_index_server
couchdb_indexes_by_sig couchdb_indexes_by_sig set 1 316 couch_index_server
当index_server获得call
到get_index
时,它将Waiters
列表添加到ets couchdb_indexes_by_sig中。或者如果一个进程请求它,它只是发送一个包含索引位置的reply
。
当index_server得到一个call
到async_open
时,它只是迭代Waiters
的列表,并向它们发送一个reply
,其中包含索引
同样,在索引上调用reset_indexes
和其他操作也会发送一个索引位置的回复。
当第一次创建索引时,couchdb调用async_open
将索引提供给所有等待的进程。之后,每个进程都可以访问索引。
这里需要注意的重要一点是,索引服务器除了将索引提供给其他进程(例如couch_mr_view_util.erl)之外,没有做任何特殊的事情。在这方面,它起到了门户的作用。索引写操作由couch_index处理。话务量,couch-index_updater。Erl和couch_index_compactor。哦,这些都是gen_server !
当视图第一次被创建时,只有一个进程可以访问它。query_server进程(默认为couchjs)。在构建视图之后,可以以并发的方式读取和更新视图。视图的实际查询由couch_mr_view处理,它作为我们熟悉的http api公开给我们。