diff options
author | Ilya Maximets <i.maximets@ovn.org> | 2021-12-19 15:09:39 +0100 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-03-03 15:21:21 +0100 |
commit | a3e97b1af1bdcaa802c6caa9e73087df7077d2b1 (patch) | |
tree | 874bc2376b871a5987605eab6b7365f7d8f7ef26 /ovsdb | |
parent | 999ba294fb4f9a39db77070f0b2045bf166c2287 (diff) | |
download | openvswitch-a3e97b1af1bdcaa802c6caa9e73087df7077d2b1.tar.gz |
ovsdb: relay: Add transaction history support.
Even though relays can be scaled to the big number of servers to
handle a lot more clients, lack of transaction history may cause
significant load if clients are re-connecting.
E.g. in case of the upgrade of a large-scale OVN deployment, relays
can be taken down one by one forcing all the clients of one relay to
jump to other ones. And all these clients will download the database
from scratch from a new relay.
Since relay itself supports monitor_cond_since connection to the
main cluster, it receives the last transaction id along with each
update. Since these transaction ids are 'eid's of actual transactions,
they can be used by relay for a transaction history.
Relay may not receive all the transaction ids, because the main cluster
may combine several changes into a single monitor update. However,
all relays will, likely, receive same updates with the same transaction
ids, so the case where transaction id can not be found after
re-connection between relays should not be very common. If some id
is missing on the relay (i.e. this update was merged with some other
update and newer id was used) the client will just re-download the
database as if there was a normal transaction history miss.
OVSDB client synchronization module updated to provide the last
transaction id along with the update. Relay module updated to use
these ids as a transaction id. If ids are zero, relay decides that
the main server doesn't support transaction ids and disables the
transaction history accordingly.
Using ovsdb_txn_replay_commit() instead of ovsdb_txn_propose_commit_block(),
so transactions are added to the history. This can be done, because
relays has no file storage, so there is no need to write anything.
Relay tests modified to test both standalone and clustered database
as a main server. Checks added to ensure that all servers receive the
same transaction ids in monitor updates.
Acked-by: Mike Pattrick <mkp@redhat.com>
Acked-by: Han Zhou <hzhou@ovn.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r-- | ovsdb/ovsdb-server.c | 8 | ||||
-rw-r--r-- | ovsdb/relay.c | 28 | ||||
-rw-r--r-- | ovsdb/transaction.c | 9 |
3 files changed, 33 insertions, 12 deletions
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 9fe90592e..b975c17fc 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -729,9 +729,11 @@ open_db(struct server_config *config, const char *filename) db->db = ovsdb_create(schema, storage); ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db); - /* Enable txn history for clustered mode. It is not enabled for other mode - * for now, since txn id is available for clustered mode only. */ - ovsdb_txn_history_init(db->db, ovsdb_storage_is_clustered(storage)); + /* Enable txn history for clustered and relay modes. It is not enabled for + * other modes for now, since txn id is available for clustered and relay + * modes only. */ + ovsdb_txn_history_init(db->db, + is_relay || ovsdb_storage_is_clustered(storage)); read_db(config, db); diff --git a/ovsdb/relay.c b/ovsdb/relay.c index ef0e44d34..2df393403 100644 --- a/ovsdb/relay.c +++ b/ovsdb/relay.c @@ -222,7 +222,8 @@ ovsdb_relay_process_row_update(struct ovsdb_table *table, static struct ovsdb_error * ovsdb_relay_parse_update__(struct ovsdb *db, - const struct ovsdb_cs_db_update *du) + const struct ovsdb_cs_db_update *du, + const struct uuid *last_id) { struct ovsdb_error *error = NULL; struct ovsdb_txn *txn; @@ -254,8 +255,17 @@ exit: ovsdb_txn_abort(txn); return error; } else { - /* Commit transaction. */ - error = ovsdb_txn_propose_commit_block(txn, false); + if (uuid_is_zero(last_id)) { + /* The relay source doesn't support unique transaction ids, + * disabling transaction history for relay. */ + ovsdb_txn_history_destroy(db); + ovsdb_txn_history_init(db, false); + } else { + ovsdb_txn_set_txnid(last_id, txn); + } + /* Commit transaction. + * There is no storage, so ovsdb_txn_replay_commit() can be used. */ + error = ovsdb_txn_replay_commit(txn); } return error; @@ -266,6 +276,7 @@ ovsdb_relay_clear(struct ovsdb *db) { struct ovsdb_txn *txn = ovsdb_txn_create(db); struct shash_node *table_node; + struct ovsdb_error *error; SHASH_FOR_EACH (table_node, &db->tables) { struct ovsdb_table *table = table_node->data; @@ -276,7 +287,14 @@ ovsdb_relay_clear(struct ovsdb *db) } } - return ovsdb_txn_propose_commit_block(txn, false); + /* There is no storage, so ovsdb_txn_replay_commit() can be used. */ + error = ovsdb_txn_replay_commit(txn); + + /* Clearing the transaction history, and re-enabling it. */ + ovsdb_txn_history_destroy(db); + ovsdb_txn_history_init(db, true); + + return error; } static void @@ -304,7 +322,7 @@ ovsdb_relay_parse_update(struct relay_ctx *ctx, error = ovsdb_relay_clear(ctx->db); } if (!error) { - error = ovsdb_relay_parse_update__(ctx->db, du); + error = ovsdb_relay_parse_update__(ctx->db, du, &update->last_id); } } ovsdb_cs_db_update_destroy(du); diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c index db86d847c..090068603 100644 --- a/ovsdb/transaction.c +++ b/ovsdb/transaction.c @@ -40,7 +40,7 @@ struct ovsdb_txn { struct ovsdb *db; struct ovs_list txn_tables; /* Contains "struct ovsdb_txn_table"s. */ struct ds comment; - struct uuid txnid; /* For clustered mode only. It is the eid. */ + struct uuid txnid; /* For clustered and relay modes. It is the eid. */ size_t n_atoms; /* Number of atoms in all transaction rows. */ ssize_t n_atoms_diff; /* Difference between number of added and * removed atoms. */ @@ -1143,9 +1143,10 @@ ovsdb_txn_complete(struct ovsdb_txn *txn) /* Applies 'txn' to the internal representation of the database. This is for * transactions that don't need to be written to storage; probably, they came - * from storage. These transactions shouldn't ordinarily fail because storage - * should contain only consistent transactions. (One exception is for database - * conversion in ovsdb_convert().) */ + * from storage or from relay. These transactions shouldn't ordinarily fail + * because storage should contain only consistent transactions. (One exception + * is for database conversion in ovsdb_convert().) Transactions from relay + * should also be consistent, since relay source should have verified them. */ struct ovsdb_error * OVS_WARN_UNUSED_RESULT ovsdb_txn_replay_commit(struct ovsdb_txn *txn) { |