@@ -551,6 +551,90 @@ In a router application, you can define the ``put`` function that specifies how
551
551
552
552
Learn more at :ref: `vshard-process-requests `.
553
553
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
+ 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 will be applied **only once **.
568
+
569
+ Re-invoking queries
570
+
571
+ A query may need to be re-executed if an error occurs on the server or client side.
572
+ In this case:
573
+
574
+ - Read requests can be executed repeatedly. To do this, the method
575
+ [vshard.router.call()](https://www.tarantool.io/ru/doc/latest/reference/reference_rock/vshard/vshard_router/#router-api-call)
576
+ in the `read ` mode (`mode=read `) uses the `request_timeout ` parameter (available since `vshard ` 0.1.28).
577
+ The `request_timeout ` and `timeout ` parameters must be passed together, observing the following condition:
578
+
579
+ For example, if ``timeout = 10 ``, and ``request_timeout = 2 ``,
580
+ then within 10 seconds the router is able to make up to 5 attempts to contact (2 seconds each) with a request to different replicas,
581
+ until the request finally succeeds.
582
+
583
+ - Write requests ([vshard.router.callrw()](https://www.tarantool.io/ru/doc/latest/reference/reference_rock/vshard/vshard_router/#router-api-callrw))
584
+ in general **cannot be re-executed ** without checking that the request has not been applied before.
585
+ Lack of such a check may lead to duplicate records or unplanned data changes.
586
+
587
+ For example, a client has sent a request to the server and is waiting for a response within a specified time.
588
+ If the server sends a response about successful execution after this time has elapsed, the client will receive an error and when
589
+ re-sending the request without additional checking, the operation may be applied twice.
590
+
591
+ A write request can be re-executed without a check only if the error occurred on the server side --
592
+ for example, `ER_READONLY `.
593
+
594
+ Methods of deduplicating queries
595
+
596
+ To ensure idempotency of write queries, such as data insert, update, and upsert, as well as autoincrement,
597
+ it is necessary to implement a check in the code that the query is being used for the first time.
598
+
599
+ For example, when adding a new tuple to a space, a unique key by which the insertion is performed can be used for checking.
600
+ In such a query within a single transaction:
601
+
602
+ 1. It is checked whether there is a tuple with the key `key ` in the `bands ` space.
603
+ 2. If there is no record with such a key in the space, the tuple is inserted.
604
+
605
+ .. code-block :: lua
606
+
607
+ box.begin()
608
+ if box.space.bands:get{key} == nil then
609
+ box.space.bands:insert{key, value}
610
+ end
611
+ box.commit()
612
+
613
+ For tuple update requests, a separate _deduplication_ space can be created, in which the query IDs will be saved.
614
+ _deduplication_ space is a user space that contains a list of unique identifiers.
615
+ Each such identifier corresponds to one executed query.
616
+ This space can have any name, in the example it is called `deduplication `.
617
+
618
+ In the example below, within a single transaction:
619
+
620
+ 1. The `deduplication ` space is checked for the presence of the `deduplication_key ` request ID.
621
+ 2. If there is no such ID, this ID is added to the deduplication space.
622
+ 3. The request then increments the specified field in the `bands ` space by one.
623
+
624
+ This approach ensures that each data modification request will be executed **only once **.
625
+
626
+ .. code-block :: lua
627
+
628
+ function update_1(deduplication_key, key)
629
+ box.begin()
630
+ if box.space.deduplication:get{deduplication_key} == nil then
631
+ box.space.deduplication:insert{deduplication_key}
632
+ box.space.bands:update(key, {{'+', 'value', 1 }})
633
+ end
634
+ box.commit()
635
+ end
636
+
637
+
554
638
.. _vshard-maintenance :
555
639
556
640
Sharded cluster maintenance
0 commit comments