Skip to content

When the configuration file changes, reload the connection pool of the distributed table#25768

Closed
ljcui wants to merge 2 commits intoClickHouse:masterfrom
ljcui:fix_distributed_table
Closed

When the configuration file changes, reload the connection pool of the distributed table#25768
ljcui wants to merge 2 commits intoClickHouse:masterfrom
ljcui:fix_distributed_table

Conversation

@ljcui
Copy link
Copy Markdown

@ljcui ljcui commented Jun 28, 2021

I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
When the address of remote_servers in the configuration file changes, reload the connection pool of the distributed table using the new compact format

Detailed description / Documentation draft:
Use configuration item use_compact_format_in_distributed_parts_names , set to 1.
The directory name of distributed table uses the new compact format,like this shard1_replica1 or shard1_all_replicas.
When the address of remote_servers in the configuration file changes, the address in the connection pool of distributed table is still old and must be restarted at this time to take effect.
This pr enables the connection pool to be automatically updated when the configuration file is reloaded.

@robot-clickhouse robot-clickhouse added the pr-improvement Pull request with some product improvements label Jun 28, 2021
Copy link
Copy Markdown
Member

@azat azat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#25768 (comment)

Also it looks like worth adding an integration test

Comment on lines 939 to 941
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::lock_guard lock(cluster_nodes_mutex);
for (auto & node : cluster_nodes_data)
node.second.directory_monitor->requestUpdatePool();
std::lock_guard lock(cluster_nodes_mutex);
for (auto & node : cluster_nodes_data)
node.second.directory_monitor->requestUpdatePool();

Lots of coding style issues here and in other hunks of the patch.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing out the problem, I will modify it later

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving this into .cpp

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
need_update_pool= true;
need_update_pool = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The major comment is that this patch will reload the pool only for use_compact_format_in_distributed_parts_names=1 and internal_replication=true, so it will reload only replicas (I'm not sure that it is OK, plus at least description does not say anything about this).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (need_update_pool) {
if (need_update_pool)
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So update will happen on any config reload regardless was cluster definition had been changed or not, right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems that the isSameConfiguration function can be used to judge in advance, and update only when the remote_servers changes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
};
}

@alexey-milovidov alexey-milovidov changed the title When the configuration file changes, reload the connection pool of th… When the configuration file changes, reload the connection pool of the distributed table Jun 28, 2021
@ljcui ljcui force-pushed the fix_distributed_table branch from f5fe2fc to fd4ab25 Compare June 29, 2021 03:45
@ljcui ljcui requested a review from azat June 29, 2021 09:14
@azat
Copy link
Copy Markdown
Member

azat commented Jun 30, 2021

It fails CI checks, some NULL derefence:

Details
2021.06.29 15:03:10.025911 [ 5549 ] {} <Fatal> BaseDaemon: ########################################
2021.06.29 15:03:10.026036 [ 5549 ] {} <Fatal> BaseDaemon: (version 21.8.1.7304, build id: E60FD3C998B21B6424236513074ED5B796047327) (from thread 4004) (query_id: 0a3a9abf-29c3-49bf-b441-ea82f1987a94) Received signal Segmentation fault (11)
2021.06.29 15:03:10.026150 [ 5549 ] {} <Fatal> BaseDaemon: Address: NULL pointer. Access: read. Address not mapped to object.
2021.06.29 15:03:10.026262 [ 5549 ] {} <Fatal> BaseDaemon: Stack trace: 0x2243046c 0x22421e86 0x21cc528c 0x21282f64 0x2127123d 0x216c49b5 0x216c0763 0x22d3b1de 0x22d611dd 0x2a32478f 0x2a325353 0x2a5fedf5 0x2a5f9117 0x7fb3e3cc1609 0x7fb3e3be8293
2021.06.29 15:03:10.248423 [ 5549 ] {} <Fatal> BaseDaemon: 3. ./obj-x86_64-linux-gnu/../src/Storages/Distributed/DirectoryMonitor.cpp:627: DB::StorageDistributedDirectoryMonitor::processFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) @ 0x2243046c in /usr/bin/clickhouse
2021.06.29 15:03:10.448913 [ 5549 ] {} <Fatal> BaseDaemon: 4.1. inlined from ./obj-x86_64-linux-gnu/../contrib/libcxx/include/__tree:182: std::__1::__tree_end_node<std::__1::__tree_node_base<void*>*>* std::__1::__tree_next_iter<std::__1::__tree_end_node<std::__1::__tree_node_base<void*>*>*, std::__1::__tree_node_base<void*>*>(std::__1::__tree_node_base<void*>*)
2021.06.29 15:03:10.449091 [ 5549 ] {} <Fatal> BaseDaemon: 4.2. inlined from ../contrib/libcxx/include/__tree:923: std::__1::__tree_const_iterator<std::__1::__value_type<unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::__value_type<unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void*>*, long>::operator++()
2021.06.29 15:03:10.449201 [ 5549 ] {} <Fatal> BaseDaemon: 4.3. inlined from ../contrib/libcxx/include/map:867: std::__1::__map_const_iterator<std::__1::__tree_const_iterator<std::__1::__value_type<unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::__value_type<unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void*>*, long> >::operator++()
2021.06.29 15:03:10.449325 [ 5549 ] {} <Fatal> BaseDaemon: 4.4. inlined from ../src/Storages/Distributed/DirectoryMonitor.cpp:599: DB::StorageDistributedDirectoryMonitor::processFiles(std::__1::map<unsigned long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&)
2021.06.29 15:03:10.449397 [ 5549 ] {} <Fatal> BaseDaemon: 4. ../src/Storages/Distributed/DirectoryMonitor.cpp:394: DB::StorageDistributedDirectoryMonitor::flushAllData() @ 0x22421e86 in /usr/bin/clickhouse
2021.06.29 15:03:10.883745 [ 5549 ] {} <Fatal> BaseDaemon: 5.1. inlined from ./obj-x86_64-linux-gnu/../contrib/libcxx/include/iterator:1496: std::__1::__wrap_iter<std::__1::shared_ptr<DB::StorageDistributedDirectoryMonitor>*>::operator++()
2021.06.29 15:03:10.883870 [ 5549 ] {} <Fatal> BaseDaemon: 5. ../src/Storages/StorageDistributed.cpp:1160: DB::StorageDistributed::flushClusterNodesAllData(std::__1::shared_ptr<DB::Context const>) @ 0x21cc528c in /usr/bin/clickhouse
2021.06.29 15:03:11.261577 [ 5549 ] {} <Fatal> BaseDaemon: 6. ./obj-x86_64-linux-gnu/../src/Interpreters/InterpreterSystemQuery.cpp:680: DB::InterpreterSystemQuery::flushDistributed(DB::ASTSystemQuery&) @ 0x21282f64 in /usr/bin/clickhouse
2021.06.29 15:03:11.637640 [ 5549 ] {} <Fatal> BaseDaemon: 7. ./obj-x86_64-linux-gnu/../src/Interpreters/InterpreterSystemQuery.cpp:393: DB::InterpreterSystemQuery::execute() @ 0x2127123d in /usr/bin/clickhouse
2021.06.29 15:03:11.936359 [ 5549 ] {} <Fatal> BaseDaemon: 8. ./obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:0: DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, bool, DB::ReadBuffer*) @ 0x216c49b5 in /usr/bin/clickhouse
2021.06.29 15:03:12.265150 [ 5549 ] {} <Fatal> BaseDaemon: 9. ./obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:933: DB::executeQuery(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, bool) @ 0x216c0763 in /usr/bin/clickhouse
2021.06.29 15:03:12.539036 [ 5549 ] {} <Fatal> BaseDaemon: 10. ./obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:312: DB::TCPHandler::runImpl() @ 0x22d3b1de in /usr/bin/clickhouse
2021.06.29 15:03:12.903245 [ 5549 ] {} <Fatal> BaseDaemon: 11. ./obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:1624: DB::TCPHandler::run() @ 0x22d611dd in /usr/bin/clickhouse
2021.06.29 15:03:12.906234 [ 5549 ] {} <Fatal> BaseDaemon: 12. ./obj-x86_64-linux-gnu/../contrib/poco/Net/src/TCPServerConnection.cpp:57: Poco::Net::TCPServerConnection::start() @ 0x2a32478f in /usr/bin/clickhouse
2021.06.29 15:03:12.926769 [ 5549 ] {} <Fatal> BaseDaemon: 13. ./obj-x86_64-linux-gnu/../contrib/poco/Net/src/TCPServerDispatcher.cpp:114: Poco::Net::TCPServerDispatcher::run() @ 0x2a325353 in /usr/bin/clickhouse
2021.06.29 15:03:12.943551 [ 5549 ] {} <Fatal> BaseDaemon: 14. ./obj-x86_64-linux-gnu/../contrib/poco/Foundation/src/ThreadPool.cpp:0: Poco::PooledThread::run() @ 0x2a5fedf5 in /usr/bin/clickhouse
2021.06.29 15:03:12.958534 [ 5549 ] {} <Fatal> BaseDaemon: 15. ./obj-x86_64-linux-gnu/../contrib/poco/Foundation/src/Thread_POSIX.cpp:0: Poco::ThreadImpl::runnableEntry(void*) @ 0x2a5f9117 in /usr/bin/clickhouse
2021.06.29 15:03:12.958682 [ 5549 ] {} <Fatal> BaseDaemon: 16. start_thread @ 0x9609 in /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
2021.06.29 15:03:12.958812 [ 5549 ] {} <Fatal> BaseDaemon: 17. __clone @ 0x122293 in /usr/lib/x86_64-linux-gnu/libc-2.31.so
2021.06.29 15:03:13.550404 [ 5549 ] {} <Fatal> BaseDaemon: Calculated checksum of the binary: 374C9133CD40C6F71044B217987B21C8. There is no information about the reference checksum.
2021.06.29 15:03:30.258003 [ 174 ] {} <Fatal> Application: Child process was terminated by signal 11.

Comment on lines +431 to +442
if (!pool)
{
pool = StorageDistributedDirectoryMonitor::createPool(name, storage);
}
else
{
if (need_update_pool)
{
need_update_pool = false;
pool = StorageDistributedDirectoryMonitor::createPool(name, storage);
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be written in a single branch, i.e.

Suggested change
if (!pool)
{
pool = StorageDistributedDirectoryMonitor::createPool(name, storage);
}
else
{
if (need_update_pool)
{
need_update_pool = false;
pool = StorageDistributedDirectoryMonitor::createPool(name, storage);
}
}
if (!pool || need_update_pool)
{
pool = StorageDistributedDirectoryMonitor::createPool(name, storage);
need_update_pool = false;
}

Or if it was splitted, worth adding some log.

auto distributed_table = dynamic_cast<StorageDistributed *>(table.get());
if (!distributed_table)
continue;
distributed_table->updateConnectionPool();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this is a bit uncontrolled, when I though about this my concern was that cluster definition can be changed at any time, and once it was changed it should atomically sync all existing pending blocks for distributed send and then re-create all directory monitors.

Not sure, but maybe making this asynchronously is enough...

void StorageDistributedDirectoryMonitor::requestUpdatePool()
{
const char * user_pw_end = strchr(name.data(), '@');
if (!user_pw_end && startsWith(name, "shard"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that re-creating pool is enough, since changing the cluster definition can change the destination server, but you may still have pending blocks.

So suppose you have the following cluster:

<remote_servers>
  <main_cluster>
    <shard>
      <internal_replication>true</internal_replication>
      <replica>
        <host>foo-1</host>
        <port>9000</port>
      </replica>
      <replica>
        <host>foo-2</host>
        <port>9000</port>
      </replica>
    </shard>
    <shard>
      <internal_replication>true</internal_replication>
      <replica>
        <host>bar-1</host>
        <port>9000</port>
      </replica>
      <replica>
        <host>bar-2</host>
        <port>9000</port>
      </replica>
    </shard>
  </main_cluster>
</remote_servers>

And the foo* shard removed from the cluster definition.
In this case shard1 will became bar* not foo*, but all pending blocks should be sent to foo* not bar*, and during this time any INSERT should be blocked since you cannot write new blocks until you sync old one.
And also there are some trickery with internal_replication=false.

So that said that it is not that simple, and it looks to me that it is better to re-create DirectryMonitor objects, plus it requires good integration test, that will cover all possible variants.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


ZhiYong Wang seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@alexey-milovidov
Copy link
Copy Markdown
Member

Please resubmit.

@alexey-milovidov
Copy link
Copy Markdown
Member

@azat is was abandoned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-improvement Pull request with some product improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants