{"action":"created","issue":{"url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/4898","repository_url":"https://api.github.com/repos/rethinkdb/rethinkdb","labels_url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/4898/labels{/name}","comments_url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/4898/comments","events_url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/4898/events","html_url":"https://github.com/rethinkdb/rethinkdb/issues/4898","id":108925339,"number":4898,"title":"Proposal: Avoid table/db name conflicts in fully connected clusters","user":{"login":"danielmewes","id":505365,"avatar_url":"https://avatars.githubusercontent.com/u/505365?v=3","gravatar_id":"","url":"https://api.github.com/users/danielmewes","html_url":"https://github.com/danielmewes","followers_url":"https://api.github.com/users/danielmewes/followers","following_url":"https://api.github.com/users/danielmewes/following{/other_user}","gists_url":"https://api.github.com/users/danielmewes/gists{/gist_id}","starred_url":"https://api.github.com/users/danielmewes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielmewes/subscriptions","organizations_url":"https://api.github.com/users/danielmewes/orgs","repos_url":"https://api.github.com/users/danielmewes/repos","events_url":"https://api.github.com/users/danielmewes/events{/privacy}","received_events_url":"https://api.github.com/users/danielmewes/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rethinkdb/rethinkdb/labels/cp:clustering","name":"cp:clustering","color":"207de5"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/rethinkdb/rethinkdb/milestones/120","html_url":"https://github.com/rethinkdb/rethinkdb/milestones/2.4","labels_url":"https://api.github.com/repos/rethinkdb/rethinkdb/milestones/120/labels","id":1690485,"number":120,"title":"2.4","description":"","creator":{"login":"danielmewes","id":505365,"avatar_url":"https://avatars.githubusercontent.com/u/505365?v=3","gravatar_id":"","url":"https://api.github.com/users/danielmewes","html_url":"https://github.com/danielmewes","followers_url":"https://api.github.com/users/danielmewes/followers","following_url":"https://api.github.com/users/danielmewes/following{/other_user}","gists_url":"https://api.github.com/users/danielmewes/gists{/gist_id}","starred_url":"https://api.github.com/users/danielmewes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielmewes/subscriptions","organizations_url":"https://api.github.com/users/danielmewes/orgs","repos_url":"https://api.github.com/users/danielmewes/repos","events_url":"https://api.github.com/users/danielmewes/events{/privacy}","received_events_url":"https://api.github.com/users/danielmewes/received_events","type":"User","site_admin":false},"open_issues":25,"closed_issues":15,"state":"open","created_at":"2016-04-07T18:34:44Z","updated_at":"2016-09-09T01:45:20Z","due_on":null,"closed_at":null},"comments":7,"created_at":"2015-09-29T18:07:25Z","updated_at":"2016-09-30T23:59:21Z","closed_at":null,"body":"In particular ORMs currently suffer from the issue that database and table creation in RethinkDB are not atomic. If a table/database is created from multiple clients concurrently, this will result in a name conflict that needs to be manually resolved.\r\n\r\nIf we could fix this, https://github.com/rethinkdb/rethinkdb/issues/2355 and https://github.com/rethinkdb/rethinkdb/issues/2975 would also become practical.\r\n\r\nThe difficulty with this is that the set of tables and databases is currently eventually consistent, and there are some good reasons to keep it that way. It is one of the core design decisions that allows us to avoid the notion of a server being a \"member\" of the cluster.\r\n\r\nHere's a proposal for a solution that should be relatively easy to do and works without impeding on the availablity of meta operations. It does *not* guarantee immediate metadata consistency in the general case. However it does guarantee consistency if all servers are connected.\r\n\r\nWhen creating/dropping/renaming a table/database follow the following steps:\r\n1. Srv1: Contact the currently connected server with the *smallest* server UUID. Let's call that server srv2. The information that srv1 sends to srv2 includes the type of operation it's trying to perform, and the name of the table/database it's trying to modify.\r\n2. Upon request, srv2 acquires a local mutex and verifies that the operation can be performed successfully. In particular it checks for table/database name conflicts. If the verification passes, it sends a ticket back to srv1.\r\n3. Upon receiving the ticket, srv1 performs the actual operation. When it is done, it returns the ticket to srv2.\r\n4. Srv2 holds on to the mutex after receiving the ticket, until it can verify that the operation performed by srv1 has been reflected in its local meta data. It then releases the mutex\r\n\r\nIf the servers disconnect in the middle of the process, srv1 releases the mutex immediately and srv2 goes ahead with the operation without waiting for a ticket (alternatively it could fail).\r\n\r\nI believe this guarantees consistency as long as all servers in the cluster are fully connected. If a server is missing or connectivity is inconsistent (like in a network partition), it essentially falls back to the current behavior of eventually consistent metadata.\r\n\r\n@VeXocide and others: Any thoughts on this?"},"comment":{"url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/comments/250878016","html_url":"https://github.com/rethinkdb/rethinkdb/issues/4898#issuecomment-250878016","issue_url":"https://api.github.com/repos/rethinkdb/rethinkdb/issues/4898","id":250878016,"user":{"login":"jlhawn","id":1441929,"avatar_url":"https://avatars.githubusercontent.com/u/1441929?v=3","gravatar_id":"","url":"https://api.github.com/users/jlhawn","html_url":"https://github.com/jlhawn","followers_url":"https://api.github.com/users/jlhawn/followers","following_url":"https://api.github.com/users/jlhawn/following{/other_user}","gists_url":"https://api.github.com/users/jlhawn/gists{/gist_id}","starred_url":"https://api.github.com/users/jlhawn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlhawn/subscriptions","organizations_url":"https://api.github.com/users/jlhawn/orgs","repos_url":"https://api.github.com/users/jlhawn/repos","events_url":"https://api.github.com/users/jlhawn/events{/privacy}","received_events_url":"https://api.github.com/users/jlhawn/received_events","type":"User","site_admin":false},"created_at":"2016-09-30T23:59:21Z","updated_at":"2016-09-30T23:59:21Z","body":"I've also got an idea for how to possibly fix this issue. I have some experience implementing other distributed systems, but I admit I have almost no idea of how the systems tables are currently implemented. So at the risk of sounding totally ignorant, here is my idea:\r\n\r\nHow about having the systems tables (i.e., the `rethinkdb` database) be a single Raft consensus group? Just as not every server in a cluster today hosts a replica of a table shard, not every server in the cluster need be a member of this consensus group. For example: in a cluster with 10 servers an operator can designate 3 servers to be \"cluster config managers\". This subset of the servers would be responsible for managing a replica of all of the systems tables. This replication can be managed by an operator just like any other table. These manager servers could also host shards for other tables as configured by an operator.\r\n\r\nAll queries on the systems tables would by routed from any server to the primary replica of the `rethinkdb` systems tables for up-to-date reads and writes. All other servers would connect to one (or all) of these cluster managers to \"discover\" which table shard replicas they are responsible for and how to connect to peers for the corresponding consensus groups. The other servers could then consume a change feed for the systems tables to be notified of changes to server, db, and table configuration.\r\n\r\nAs long as a majority of these manager servers are available then these operations can succeed. Note that this is *not* the same as a majority of all servers in the cluster. If a majority of these manager servers do become unavailable for some reason then an operator could perform a reconfigure with the `emergencyRepair` option - as they would with any other table. While the majority of manager servers are unavailable, you would not be able to join new servers or reconfigure any other tables, I don't know yet if this affects the availability of the other tables. I also haven't thought much about what to do in the event that all of the manager servers fail permanently. I guess you would have to pick an existing server to \"promote\" to the new role with the most recent view of the system tables that it had and then restart all other servers to `--join` this new manager. As usual, designating more (5, or 7) manager servers (from different racks, availability zones, etc) would provide higher likelihood of availability of the cluster config.\r\n\r\nJust as before, there is not really any hard notion of a server being a \"member\" of the cluster other than the servers which host a replica of the cluster config. I guess you can think of it as one Raft consensus group which coordinates other Raft Consensus groups?"}}
{"actor":{"display_login":"jlhawn"}}