Skip to content

[docs] consolidate the coordination nodes content #12314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions ydb/docs/en/core/concepts/datamodel/coordination-node.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Coordination node

A coordination node is an object in {{ ydb-short-name }} that allows client applications to coordinate their actions in a distributed manner. Typical use cases for coordination nodes include:

* Distributed [semaphores](https://en.wikipedia.org/wiki/Semaphore_(programming)) and [mutexes](https://en.wikipedia.org/wiki/Mutual_exclusion).
* Service discovery.
* Leader election.
* Task queues.
* Publishing small amounts of data with the ability to receive change notifications.
* Ephemeral locking of arbitrary entities not known in advance.

## Semaphores {#semaphore}

Coordination nodes allow you to create and manage semaphores within them. Typical operations with semaphores include:

* Create.
* Acquire.
* Release.
* Describe.
* Subscribe.
* Delete.

A semaphore can have a counter that limits the number of simultaneous acquisitions, as well as a small amount of arbitrary data attached to it.

{{ ydb-short-name }} supports two types of semaphores: persistent and ephemeral. A persistent semaphore must be created before acquisition and will exist either until it is explicitly deleted or until the coordination node in which it was created is deleted. Ephemeral semaphores are automatically created at the moment of their first acquisition and deleted at the last release, which is convenient to use, for example, in distributed locking scenarios.

{% note info %}

Semaphores in {{ ydb-short-name }} are **not** recursive. Thus, semaphore acquisition and release are idempotent operations.

{% endnote %}

## Usage {#usage}

Working with coordination nodes and semaphores is done through [dedicated methods in {{ ydb-short-name }} SDK](../../reference/ydb-sdk/coordination.md).

## Similar systems {#similar-systems}

{{ ydb-short-name }} coordination nodes can solve tasks that are traditionally performed using systems such as [Apache Zookeeper](https://zookeeper.apache.org/), [etcd](https://etcd.io/), [Consul](https://www.consul.io/), and others. If a project uses {{ ydb-short-name }} for data storage along with one of these third-party systems for coordination, switching to {{ ydb-short-name }} coordination nodes can reduce the number of systems that need to be operated and maintained.
9 changes: 5 additions & 4 deletions ydb/docs/en/core/concepts/datamodel/toc_i.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
items:
- { name: Directory, href: dir.md }
- { name: Table, href: table.md }
- { name: View, href: view.md }
- { name: Topic, href: ../topic.md }
- { name: Directories, href: dir.md }
- { name: Tables, href: table.md }
- { name: Views, href: view.md }
- { name: Topics, href: ../topic.md }
- { name: Coordination nodes, href: coordination-node.md }
- { name: Secrets, href: secrets.md }
- { name: External tables, href: external_table.md }
- { name: External data source, href: external_data_source.md }
8 changes: 8 additions & 0 deletions ydb/docs/en/core/concepts/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ A **consumer** is an entity that reads messages from a topic.

**Replica object** is a mirror copy of the replicated object, automatically created by an [asynchronous replication instance](#async-replication-instance). Replica objects are typically read-only.

### Coordination node {#coordination-node}

A **coordination node** is a schema object that allows client applications to create semaphores for coordinating their actions. Learn more about [coordination nodes](./datamodel/coordination-node.md).

#### Semaphore {#semaphore}

A **semaphore** is an object within a [coordination node](#coordination-node) that provides a synchronization mechanism for distributed applications. Semaphores can be persistent or ephemeral and support operations like creation, acquisition, release, and monitoring. Learn more about [semaphores in {{ ydb-short-name }}](./datamodel/coordination-node.md#semaphore).

### YQL {#yql}

**YQL ({{ ydb-short-name }} Query Language)** is a high-level language for working with the system. It is a dialect of [ANSI SQL](https://en.wikipedia.org/wiki/SQL). There's a lot of content covering YQL, including a [tutorial](../dev/yql-tutorial/index.md), [reference](../yql/reference/syntax/index.md), and [recipes](../recipes/yql/index.md).
Expand Down
10 changes: 10 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/config-publication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Configuration publication

Let's consider a scenario where we need to publish a small configuration for multiple application instances that should promptly react to its changes.

This scenario can be implemented using semaphores in [{{ ydb-short-name }} coordination nodes](../../reference/ydb-sdk/coordination.md) as follows:

1. A semaphore is created (for example, named `my-service-config`).
1. The updated configuration is published through `UpdateSemaphore`.
1. Application instances call `DescribeSemaphore` with `WatchData=true`. In the result, the `Data` field will contain the current version of the configuration.
1. When the configuration changes, `OnChanged` is called. In this case, application instances make a similar `DescribeSemaphore` call and receive the updated configuration.
42 changes: 42 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/distributed-lock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Distributed lock

Consider a scenario where it is necessary to ensure that only one instance of a client application accesses a shared resource at any given time. To achieve this, the semaphore mechanism in [{{ ydb-short-name }} coordination nodes](../../reference/ydb-sdk/coordination.md) can be utilized.

## Semaphore lease mechanism

In contrast to local multithreaded programming, clients in distributed systems do not directly acquire locks or semaphores. Instead, they lease them for a specified duration, which can be periodically renewed. Due to reliance on physical time which can vary between machines, clients and the server might encounter situations where multiple clients believe they have acquired the same semaphore simultaneously, even if the server's perspective differs. To reduce the likelihood of such occurrences, it is crucial to configure automatic time synchronization beforehand, both on servers hosting client applications and on the {{ ydb-short-name }} side, ideally using a unified time source.

Therefore, while distributed locking through such mechanisms cannot guarantee the complete absence of simultaneous resource access, it can significantly lower the probability of such events. This approach serves as an optimization to prevent unnecessary competition among clients for a shared resource. Absolute guarantees against concurrent resource requests сould be implemented on the resource side.

## Code example

{% list tabs %}

- Go

```go
for {
if session, err := db.Coordination().CreateSession(ctx, path); err != nil {
return fmt.Errorf("cannot create session: %v", err);
}

if lease, err := session.AcquireSemaphore(ctx,
semaphore,
coordination.Exclusive,
options.WithEphemeral(true),
); err != nil {
// the session is likely lost, try to create a new one and get the lock in it
session.Close(ctx);
continue;
}

// lock acquired, start processing
select {
case <-lease.Context().Done():
}

// lock released, end processing
}
```

{% endlist %}
7 changes: 7 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ Table of contents:
- [Inserting data](upsert.md)
- [Bulk upsert of data](bulk-upsert.md)
- [Setting up the transaction execution mode](tx-control.md)
- Coordination

- [Distributed lock](distributed-lock.md)
- [Service discovery](service-discovery.md)
- [Configuration publication](config-publication.md)
- [Leader election](leader-election.md)

- [Troubleshooting](debug.md)

- [Enable logging](debug-logs.md)
Expand Down
11 changes: 11 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/leader-election.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Leader election

Consider a scenario where multiple application instances need to elect a leader among themselves and be aware of the current leader at any given time.

This scenario can be implemented using semaphores in [{{ ydb-short-name }} coordination nodes](../../reference/ydb-sdk/coordination.md) as follows:

1. A semaphore is created (for example, named `my-service-leader`) with `Limit=1`.
1. All application instances call `AcquireSemaphore` with `Count=1`, specifying their endpoint in the `Data` field.
1. Only one application instance's call will complete quickly, while others will be queued. The application instance whose call completes successfully becomes the current leader.
1. All application instances call `DescribeSemaphore` with `WatchOwners=true` and `IncludeOwners=true`. The result's `Owners` field will contain at most one element, from which the current leader's endpoint can be determined via its `Data` field.
1. When the leader changes, `OnChanged` is called. In this case, application instances make a similar `DescribeSemaphore` call to learn about the new leader.
12 changes: 12 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/service-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Service discovery

Consider a scenario where application instances are dynamically started and publish their endpoints, while other clients need to receive this list and respond to its changes.

This scenario can be implemented using semaphores in [{{ ydb-short-name }} coordination nodes](../../reference/ydb-sdk/coordination.md) as follows:

1. Create a semaphore (for example, named `my-service-endpoints`) with `Limit=Max<ui64>()`.
1. All application instances call `AcquireSemaphore` with `Count=1`, specifying their endpoint in the `Data` field.
1. Since the semaphore limit is very high, all `AcquireSemaphore` calls should complete quickly.
1. At this point, publication is complete, and application instances only need to respond to session stops by republishing themselves through a new session.
1. Clients call `DescribeSemaphore` with `IncludeOwners=true` and optionally with `WatchOwners=true`. In the result, the `Owners` field's `Data` will contain the endpoints of registered application instances.
1. When the list of endpoints changes, `OnChanged` is called. In this case, clients make a similar `DescribeSemaphore` call and receive the updated list.
10 changes: 10 additions & 0 deletions ydb/docs/en/core/recipes/ydb-sdk/toc_i.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ items:
href: bulk-upsert.md
- name: Setting up the transaction execution mode
href: tx-control.md
- name: Coordination
items:
- name: Distributed lock
href: distributed-lock.md
- name: Leader election
href: leader-election.md
- name: Service discovery
href: service-discovery.md
- name: Configuration publication
href: config-publication.md
- name: Troubleshooting
items:
- name: Overview
Expand Down
Loading
Loading