【问题标题】:A good way to replicate _security and _user tables in CouchDB在 CouchDB 中复制 _security 和 _user 表的好方法
【发布时间】:2015-04-27 05:48:33
【问题描述】:

在我们的场景中,我们有一个本地 CouchDB 连接到生成数据的 node.js 服务器。数据包括用户及其对该数据库中某些表的访问。

此本地 CouchDB 实例应复制到云中的远程 CouchDB,包括每个数据库的 _users 和 _security 表中指定的用户和安全规则。

将所有数据复制到远程 CouchDB 有效,但问题是:

  • 只有服务器和数据库管理员可以创建用户。因此,复制任务需要管理员凭据。如果没有其他解决方案,我想我可以接受。

  • _security 文档未进行版本控制,因此无法复制。

即使本地 CouchDB 实例在创建用户时处于脱机状态,是否有一种保持两个数据库同步的好方法。 (用户和安全)。

更新:

我想到的一种方法是在每次创建新用户时调用的服务器上创建一个设计文档。然后,此函数为新创建的用户创建一个新数据库,并将用户名添加到 _security 规则中。

我想避免在服务器上安装额外的应用程序来监听 _changes 提要并根据新的更新进行操作。

【问题讨论】:

    标签: database couchdb replication


    【解决方案1】:

    我刚刚发布了一个名为replicate-couchdb-cluster 的新工具,它提供了一种复制整个数据库集群的容错方式。它还允许并发,因此可以大大加快复制集群所需的时间。

    还有一个docker image,您可以使用它轻松设置连续复制。

    我希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      我想到的一种方法是在每次创建新用户时调用的服务器上创建一个设计文档。然后,此函数为新创建的用户创建一个新数据库并将用户名添加到 _security 规则中。

      有一个名为couch per user 的插件可以让你做到这一点。安装它,对于 _users 数据库中的每个新user,它将自动为该用户创建一个数据库。

      您是对的,_security 文档没有版本控制。但普通文件是。因此,如果将 _security 对象存储为常规的 couchdb 文档,则可以解决复制它们的问题。现在我们需要确保的是,当包含 _security 对象的文档被复制时,它会自动添加到目标数据库的 _security 中。

      如果您将验证函数视为“更新前”事件处理程序,那么它们可以用于此任务。我们需要做的是

      1. 创建一个验证函数来查找包含 _security 对象的文档。
      2. 一旦找到对象,就向数据库的 _security 字段发出 http 请求,并将对象的内容存储在其中。
      3. “通过”对象包含 _security,因此它保存在本地数据库中。

      现在默认的 javascript 验证函数无法进行 http 调用,因此您需要更改您的 query server。我知道至少 erlang 和 python 查询服务器允许您进行 http 调用。但请先尝试使用您最喜欢的语言的那个。

      例子:-

          {
          _id:adsfasf,
          _rev:3-bd25f9790db7a8034d9415da7a4d625,
          "type":"security",
          _security: 
          {
              "admins": {
                  "names": [
                      "superuser"
                  ],
                  "roles": [
                      "admins"
                  ]
              },
              "members": {
                  "names": [
                      "user1",
                      "user2"
                  ],
                  "roles": [
                      "developers"
                  ]
              }
          }
      
          }
      }
      

      验证函数

      function(newDoc,oldDoc,userCtx,secObj){
      
      if(newDoc.type ==="security"){
      //make an http call to db/_security and post the _security field there
      
        }
      }
      

      您无需以这种方式收听更改提要。只需使用普通 couchdb 文档和验证功能(在不同的查询服务器中)的组合,您就可以做您想做的事。

      性能问题

      拥有一个 validate 函数肯定会减慢插入时间,因为它会在插入之前对每个 couchdb 文档进行检查。

      Erlang 验证功能将是不同查询服务器中速度最快、资源效率最高的。用 erlang 编写它应该不会太难,因为它只是一个 if 块和对 http 的请求。此示例未经测试,但它应该可以帮助您入门。

      fun({N_Doc},_Old_Doc,_User,_Sec)->
          case proplists:get_value(<<"type">>,N_Doc) of 
              <<"_serurity">>-> 
                 httpc:request(
                     post,
                     {"http://localhost:5984/yourdb/_security", 
                      [], 
                      "application/json",
                      ejson:encode(proplists:get_value(<<"_security">>))},
                     [],[]),
                   1;
          <<"some_bad_value">>->
              {[{<<"forbidden">>, "Nope this won't do"}]};
          _->
             1
          end
      end.
      

      上面的函数只是等待一个“安全”类型的文档,然后将它发送到数据库的 _security 端点。 1 回复意味着一切正常。该文档已经过验证,现在可以存储了。禁止响应不允许存储文档。希望这可以帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-30
        • 1970-01-01
        • 2019-07-01
        • 1970-01-01
        • 2017-06-24
        • 2017-05-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多