Skip to content

Commit d0c7e23

Browse files
committed
draft
1 parent 8117972 commit d0c7e23

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

doc/platform/sharding/vshard_admin.rst

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,93 @@ In a router application, you can define the ``put`` function that specifies how
551551

552552
Learn more at :ref:`vshard-process-requests`.
553553

554+
.. _vshard-deduplication:
555+
556+
Deduplication of non-idempotent requests
557+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
558+
559+
**Idempotent requests** produce the same result every time they are called.
560+
For example, a data read request or a multiplication by one are idempotent.
561+
So, increment by one is an example of a non-idempotent operation.
562+
When such an operation is applied again, the value for the field will be increased by 2 instead of 1.
563+
564+
.. note::
565+
566+
Any write requests that are planned to be executed repeatedly should be idempotent.
567+
The idempotency of such operations ensures that the change from the operation are applied **only once**.
568+
569+
A request may need to be re-executed if an error occurs on the server or client side.
570+
In this case:
571+
572+
- Read requests can be executed repeatedly.
573+
To do this, the :ref:`vshard.router.call(mode=read) <router_api-call>` uses the `request_timeout` parameter
574+
(since `vshard` 0.1.28).
575+
The `request_timeout` and `timeout` parameters should be passed together, observing the following condition:
576+
577+
.. code-block:: text
578+
579+
timeout > request_timeout
580+
581+
582+
For example, if ``timeout = 10`` and ``request_timeout = 2``,
583+
within 10 seconds the router is able to make up to 5 attempts to contact (2 seconds each) with a request to different replicas,
584+
until the request finally succeeds.
585+
586+
- Write requests (:ref:`vshard.router.callrw() <router_api-callrw>`) generally **can't be re-executed** without checking
587+
that the request has not been applied before.
588+
Lack of such a check may lead to duplicate records or unplanned data changes.
589+
590+
For example, a client has sent a request to the server, waiting for response within a specified timeout.
591+
If the server sends a response about successful execution after this time has elapsed, the client will receive an error.
592+
When re-executing the request without additional checking, the operation may be applied twice.
593+
594+
A write request can be re-executed without a check only if the error occurred on the server side --
595+
for example, `ER_READONLY`.
596+
597+
**Deduplication examples**
598+
599+
To ensure idempotency of write queries, such as data insert, update, and upsert, as well as autoincrement,
600+
it is necessary to implement a check in the code that the request is being used for the first time.
601+
602+
For example, when adding a new tuple to a space, a unique key by which the insertion is performed can be used for checking.
603+
In such a request within a single transaction:
604+
605+
1. It is checked whether there is a tuple with the key `key` in the `bands` space.
606+
2. If there is no record with such a key in the space, the tuple is inserted.
607+
608+
.. code-block:: lua
609+
610+
box.begin()
611+
if box.space.bands:get{key} == nil then
612+
box.space.bands:insert{key, value}
613+
end
614+
box.commit()
615+
616+
For tuple update requests, a separate *deduplication* space can be created, in which the request IDs will be saved.
617+
*Deduplication space* is a user space that contains a list of unique identifiers.
618+
Each such identifier corresponds to one executed request.
619+
This space can have any name, in the example it is called ``deduplication``.
620+
621+
In the example below, within a single transaction:
622+
623+
1. The ``deduplication`` space is checked for the presence of the ``deduplication_key`` request ID.
624+
2. If there is no such ID, this ID is added to the deduplication space.
625+
3. The request then increments the specified field in the ``bands`` space by one.
626+
627+
This approach ensures that each data modification request will be executed **only once**.
628+
629+
.. code-block:: lua
630+
631+
function update_1(deduplication_key, key)
632+
box.begin()
633+
if box.space.deduplication:get{deduplication_key} == nil then
634+
box.space.deduplication:insert{deduplication_key}
635+
box.space.bands:update(key, {{'+', 'value', 1 }})
636+
end
637+
box.commit()
638+
end
639+
640+
554641
.. _vshard-maintenance:
555642

556643
Sharded cluster maintenance

0 commit comments

Comments
 (0)