diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 35bf8032..cc1cfa0b 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -720,6 +720,24 @@ jobs: echo "" done + test_heal_local_read: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 10 + run: TEST_NAME=local_read POOLCFG='"local_reads":"random",' /root/vitastor/tests/test_heal.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + test_heal_ec: runs-on: ubuntu-latest needs: build diff --git a/docs/config/client.en.md b/docs/config/client.en.md index 332f9c17..35688d19 100644 --- a/docs/config/client.en.md +++ b/docs/config/client.en.md @@ -24,6 +24,7 @@ affect their interaction with the cluster. - [nbd_max_devices](#nbd_max_devices) - [nbd_max_part](#nbd_max_part) - [osd_nearfull_ratio](#osd_nearfull_ratio) +- [hostname](#hostname) ## client_iothread_count @@ -215,3 +216,12 @@ just one OSD becomes 100 % full! However, unlike in Ceph, 100 % full Vitastor OSDs don't crash (in Ceph they're unable to start at all), so you'll be able to recover from "out of space" errors without destroying and recreating OSDs. + +## hostname + +- Type: string +- Can be changed online: yes + +Clients use host name to find their distance to OSDs when [localized reads](pool.en.md#local_reads) +are enabled. By default, standard [gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html) +function is used to determine host name, but you can also override it with this parameter. diff --git a/docs/config/client.ru.md b/docs/config/client.ru.md index 4357cbc7..a9696225 100644 --- a/docs/config/client.ru.md +++ b/docs/config/client.ru.md @@ -24,6 +24,7 @@ - [nbd_max_devices](#nbd_max_devices) - [nbd_max_part](#nbd_max_part) - [osd_nearfull_ratio](#osd_nearfull_ratio) +- [hostname](#hostname) ## client_iothread_count @@ -219,3 +220,13 @@ RDMA и хотите повысить пиковую производитель заполненные на 100% OSD вообще не могут стартовать), так что вы сможете восстановить работу кластера после ошибок отсутствия свободного места без уничтожения и пересоздания OSD. + +## hostname + +- Тип: строка +- Можно менять на лету: да + +Клиенты используют имя хоста для определения расстояния до OSD, когда включены +[локальные чтения](pool.ru.md#local_reads). По умолчанию для определения имени +хоста используется стандартная функция [gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html), +но вы также можете задать имя хоста вручную данным параметром. diff --git a/docs/config/pool.en.md b/docs/config/pool.en.md index 76ace346..0801eb0e 100644 --- a/docs/config/pool.en.md +++ b/docs/config/pool.en.md @@ -34,6 +34,7 @@ Parameters: - [failure_domain](#failure_domain) - [level_placement](#level_placement) - [raw_placement](#raw_placement) +- [local_reads](#local_reads) - [max_osd_combinations](#max_osd_combinations) - [block_size](#block_size) - [bitmap_granularity](#bitmap_granularity) @@ -133,8 +134,8 @@ Pool name. ## scheme - Type: string -- Required - One of: "replicated", "xor", "ec" or "jerasure" +- Required Redundancy scheme used for data in this pool. "jerasure" is an alias for "ec", both use Reed-Solomon-Vandermonde codes based on ISA-L or jerasure libraries. @@ -289,6 +290,26 @@ Examples: - EC 4+2 in 3 DC: `any, dc=1 host!=1, dc!=1, dc=3 host!=3, dc!=(1,3), dc=5 host!=5` - 1 replica in fixed DC + 2 in random DCs: `dc?=meow, dc!=1, dc!=(1,2)` +## local_reads + +- Type: string +- One of: "primary", "nearest" or "random" +- Default: primary + +By default, Vitastor serves all read and write requests from the primary OSD of each PG. +But it can also serve read requests for replicated pools from secondary OSDs in clean PGs +(active or active+left_on_dead) which may be useful if you have OSDs with different network +latency to the client - for example, if you have a cross-datacenter setup. + +If you set this parameter to "nearest", clients will try to read from the nearest OSD +in the [Placement Tree](#placement-tree), i.e. from an OSD from the same host or datacenter. +Distance to different OSDs will be calculated based on client hostname, determined +automatically or set manually in the [hostname](client.en.md#hostname) parameter. + +If you set this parameter to "random", clients will try to distribute read requests over +all available secondary OSDs. This mode is mainly useful for tests, but, probably, not +really required in production setups. + ## max_osd_combinations - Type: integer @@ -324,7 +345,8 @@ Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-c ## immediate_commit -- Type: string, one of "all", "small" and "none" +- Type: string +- One of: "all", "small" or "none" - Default: none Immediate commit setting for this pool. The value from /vitastor/config/global diff --git a/docs/config/pool.ru.md b/docs/config/pool.ru.md index 34b9b8b6..f20604c1 100644 --- a/docs/config/pool.ru.md +++ b/docs/config/pool.ru.md @@ -33,6 +33,7 @@ - [failure_domain](#failure_domain) - [level_placement](#level_placement) - [raw_placement](#raw_placement) +- [local_reads](#local_reads) - [max_osd_combinations](#max_osd_combinations) - [block_size](#block_size) - [bitmap_granularity](#bitmap_granularity) @@ -133,8 +134,8 @@ OSD игнорируется и OSD не удаляется из распред ## scheme - Тип: строка -- Обязательный - Возможные значения: "replicated", "xor", "ec" или "jerasure" +- Обязательный Схема избыточности, используемая в данном пуле. "jerasure" - синоним для "ec", в обеих схемах используются коды Рида-Соломона-Вандермонда, реализованные на @@ -287,6 +288,27 @@ meow недоступен". - EC 4+2 в 3 датацентрах: `any, dc=1 host!=1, dc!=1, dc=3 host!=3, dc!=(1,3), dc=5 host!=5` - 1 копия в фиксированном ДЦ + 2 в других ДЦ: `dc?=meow, dc!=1, dc!=(1,2)` +## local_reads + +- Тип: строка +- Возможные значения: "primary", "nearest" или "random" +- По умолчанию: primary + +По умолчанию Vitastor обслуживает все запросы чтения и записи с первичного OSD каждой PG. +Однако, в чистых PG (active или active+left_on_dead) реплицированных пулов также есть +возможность обслуживать запросы чтения с вторичных OSD, что может быть полезно, если +у вас сильно отличается время сетевого обращения от клиента к разным OSD - например, +если у вас несколько дата-центров. + +Если данный параметр установлен в значение "nearest", клиенты будут стараться читать с +ближайших по [Дереву размещения](#дерево-размещения) OSD, то есть, с OSD с того же хоста +или датацентра. Расстояние до разных OSD будет рассчитываться с помощью имени хоста клиента, +определяемого автоматически или заданного вручную параметром [hostname](client.ru.md#hostname). + +Если данный параметр установлен в значение "random", клиенты будут стараться распределять +запросы чтения по всем доступным вторичным OSD. Этот режим в основном полезен для тестов, +но, скорее всего, редко нужен в реальных инсталляциях. + ## max_osd_combinations - Тип: целое число @@ -324,7 +346,8 @@ meow недоступен". ## immediate_commit -- Тип: строка "all", "small" или "none" +- Тип: строка +- Возможные значения: "all", "small" или "none" - По умолчанию: none Настройка мгновенного коммита для данного пула. Если не задана, используется diff --git a/docs/config/src/client.yml b/docs/config/src/client.yml index c44d34ca..9f3d72cb 100644 --- a/docs/config/src/client.yml +++ b/docs/config/src/client.yml @@ -271,3 +271,15 @@ заполненные на 100% OSD вообще не могут стартовать), так что вы сможете восстановить работу кластера после ошибок отсутствия свободного места без уничтожения и пересоздания OSD. +- name: hostname + type: string + online: true + info: | + Clients use host name to find their distance to OSDs when [localized reads](pool.en.md#local_reads) + are enabled. By default, standard [gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html) + function is used to determine host name, but you can also override it with this parameter. + info_ru: | + Клиенты используют имя хоста для определения расстояния до OSD, когда включены + [локальные чтения](pool.ru.md#local_reads). По умолчанию для определения имени + хоста используется стандартная функция [gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html), + но вы также можете задать имя хоста вручную данным параметром. diff --git a/docs/intro/architecture.en.md b/docs/intro/architecture.en.md index 9ef26d3a..29c06bb6 100644 --- a/docs/intro/architecture.en.md +++ b/docs/intro/architecture.en.md @@ -125,6 +125,13 @@ All other client-side components are based on the client library: all current read/write operations to it fail with EPIPE error and are retried by clients. - After completing all secondary read/write requests, primary OSD sends the response to the client. +- When [localized reads](../config/pool.en.md#local_reads) are enabled for a PG in a + replicated pool, and the PG is in an active and clean state (active or + active+left_on_dead), the client can send the request to one of secondary OSDs instead + of the primary. Secondary OSD checks the [PG lock](../config/osd.en.md#enable_pg_locks) + and handles the request locally without communicating to the primary. PG lock is required + for the secondary OSD to know for sure that the PG is in clean state and not switching + primary at the moment. ### Nuances of request handling diff --git a/docs/intro/architecture.ru.md b/docs/intro/architecture.ru.md index e301dc86..78edd899 100644 --- a/docs/intro/architecture.ru.md +++ b/docs/intro/architecture.ru.md @@ -125,6 +125,12 @@ и если любое из этих соединений отключается, PG перезапускается, а все текущие запросы чтения и записи в неё завершаются с ошибкой EPIPE, после чего повторяются клиентами. - После завершения всех вторичных операций чтения/записи первичный OSD отправляет ответ клиенту. +- Если в реплицированном пуле включены [локализованные чтения](../config/pool.ru.md#local_reads), + а PG находится в чистом активном состоянии (active или active+left_on_dead), клиент может + послать запрос к одному из вторичных OSD вместо первичного. Вторичный OSD проверяет + [блокировку PG](../config/osd.ru.md#enable_pg_locks) и обрабатывает запрос локально, не + обращаясь к первичному. Блокировка PG здесь нужна, чтобы вторичный OSD мог точно знать, + что PG находится в чистом состоянии и не переключается на другой первичный OSD. ### Особенности обработки запросов diff --git a/docs/intro/features.en.md b/docs/intro/features.en.md index d613c929..3a47d7d8 100644 --- a/docs/intro/features.en.md +++ b/docs/intro/features.en.md @@ -25,6 +25,7 @@ - Recovery of degraded blocks - Rebalancing (data movement between OSDs) - [Lazy fsync support](../config/layout-cluster.en.md#immediate_commit) +- [Localized read support](../config/pool.en.md#local_reads) for cross-datacenter setup optimization - Per-OSD and per-image I/O and space usage statistics in etcd - Snapshots and copy-on-write image clones - [Write throttling to smooth random write workloads in SSD+HDD configurations](../config/osd.en.md#throttle_small_writes) diff --git a/docs/intro/features.ru.md b/docs/intro/features.ru.md index b58e33ac..71696634 100644 --- a/docs/intro/features.ru.md +++ b/docs/intro/features.ru.md @@ -25,6 +25,7 @@ - Восстановление деградированных блоков - Ребаланс, то есть перемещение данных между OSD (дисками) - [Поддержка "ленивого" fsync (fsync не на каждую операцию)](../config/layout-cluster.ru.md#immediate_commit) +- [Локальные чтения](../config/pool.ru.md#local_reads) для оптимизации при нескольких датацентрах - Сбор статистики ввода/вывода в etcd - Статистика операций ввода/вывода и занятого места в разрезе инодов - Именование инодов через хранение их метаданных в etcd diff --git a/docs/usage/cli.en.md b/docs/usage/cli.en.md index 1c85bfbf..df073459 100644 --- a/docs/usage/cli.en.md +++ b/docs/usage/cli.en.md @@ -397,6 +397,7 @@ Optional parameters: | `--immediate_commit none` | Put pool only on OSDs with this or larger immediate_commit (none < small < all) | | `--level_placement ` | Use additional failure domain rules (example: "dc=112233") | | `--raw_placement ` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) | +| `--local_reads primary` | Local read policy for replicated pools: primary, nearest or random | | `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags | | `--scrub_interval