Skip to content
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

Revise document for handling exceptions for Two-phase Commit Transactions #934

Merged
merged 10 commits into from Jul 23, 2023

Conversation

brfrn169
Copy link
Collaborator

This PR revises the document for handling exceptions for Two-phase Commit Transactions. Please take a look!

@brfrn169 brfrn169 self-assigned this Jul 11, 2023
@brfrn169 brfrn169 force-pushed the revise-document-for-handling-exceptions-for-2pc branch from 7151c8b to b69b3d5 Compare July 11, 2023 14:46
@brfrn169 brfrn169 force-pushed the revise-document-for-handling-exceptions-for-2pc branch from b69b3d5 to ee57bae Compare July 11, 2023 14:48
// transaction as committed
AtomicReference<Exception> exception = new AtomicReference<>();
boolean anyMatch =
Stream.of(transaction1, transaction2)
Copy link
Contributor

Choose a reason for hiding this comment

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

With this error handling, I think the commits can be executed in parallel as follows

  Stream.of(transaction1, transaction2)
    .parallel()
    .anyMatch(
        ...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, sorry. I found the parallel version code in the next section below.

This code is the sequential version, right? If so, please ignore my comment. But it might be good to mention sequential execution or something here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good!

} catch (Exception e) {
// Rollback the transaction
if (transaction1 != null) {
transaction1.rollback();
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrapping this with try-catch would be safer just in case if rollback() could throw any exception.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 635b41d. Thanks.

}

// Otherwise, throw the first exception
throw exceptions.get(0);
Copy link
Contributor

@komamitsu komamitsu Jul 12, 2023

Choose a reason for hiding this comment

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

[minor] This is a very corner case (and unexpected usage), but this line would throw NPE ArrayIndexOutOfBoundsException if transactions is empty?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, that's a very unexpected usage. We could add validation or an assertion to this method, but I think it might be too verbose since it's a sample code. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think it's okay to go with current simple one 👍

Copy link
Contributor

@Torch3333 Torch3333 left a comment

Choose a reason for hiding this comment

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

It looks good, thanks. I left two suggestions.

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
brfrn169 and others added 2 commits July 12, 2023 16:18
Co-authored-by: Vincent Guilpain <vincent.guilpain@scalar-labs.com>
Copy link
Contributor

@Torch3333 Torch3333 left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

Copy link
Member

@josh-wong josh-wong left a comment

Choose a reason for hiding this comment

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

I've added some comments and suggestions. PTAL!

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
Requests in the same gRPC connection always go to the same server in L3/L4 load balancing.
When using an L7 load balancer, since requests in the same gRPC connection do not necessarily go to the same server, you need to use cookies or similar for routing requests to correct server.
For example, when you use [Envoy](https://www.envoyproxy.io/), you can use session affinity (sticky session) for gRPC.
Or you can also use [Bidirectional streaming RPC in gRPC](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc) since the L7 load balancer distributes requests in the same stream to the same server.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Or you can also use [Bidirectional streaming RPC in gRPC](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc) since the L7 load balancer distributes requests in the same stream to the same server.
Alternatively, you can use [bidirectional streaming RPC in gRPC](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc) since the L7 load balancer distributes requests in the same stream to the same server.


Typically, you use a server-side (proxy) load balancer with HTTP/1.1.
When using an L3/L4 load balancer, you can use the same HTTP connection to send requests in a transaction, which guarantees the requests go to the same server.
When using an L7 load balancer, since requests in the same HTTP connection do not necessarily go to the same server, you need to use cookies or similar for routing requests to correct server.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
When using an L7 load balancer, since requests in the same HTTP connection do not necessarily go to the same server, you need to use cookies or similar for routing requests to correct server.
When using an L7 load balancer, since requests in the same HTTP connection don't necessarily go to the same server, you need to use cookies or similar method to route requests to the correct server.

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
brfrn169 and others added 3 commits July 14, 2023 00:08
Co-authored-by: Josh Wong <joshua.wong@scalar-labs.com>
Co-authored-by: Josh Wong <joshua.wong@scalar-labs.com>
@brfrn169 brfrn169 requested a review from josh-wong July 13, 2023 15:24
Copy link
Contributor

@komamitsu komamitsu left a comment

Choose a reason for hiding this comment

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

LGTM! 👍

Copy link
Member

@josh-wong josh-wong left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you!🙇‍♂️

Copy link
Contributor

@feeblefakie feeblefakie left a comment

Choose a reason for hiding this comment

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

Overall, looking good! Thank you!
And, sorry for the late review.
I left some comments and suggestions.

Also, I think the name Two-phase Commit Transactions might be misleading since readers would think normal transactions don't employ the two-phase commit protocol.
Let's discuss this offline.

@@ -5,6 +5,21 @@ With Two-phase Commit Transactions, you can execute a transaction that spans mul

This document briefly explains how to execute Two-phase Commit Transactions in ScalarDB.

## Overview

ScalarDB transactions normally execute in a single transaction manager instance.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ScalarDB transactions normally execute in a single transaction manager instance.
ScalarDB normally executes transactions in a single transaction manager instance with a one-phase commit interface, which we call normal transactions.

I think we should define normal transactions here because it is referred to in the following sentence.
Also, we should probably note about interfaces.

Maybe, it might be more clear to say something like this since normal transactions don't sound like doing two-phase commits.

Although ScalarDB employs a variant of the two-phase commit protocol, ScalarDB normally executes transactions in a single transaction manager instance with a one-phase commit interface, which we call normal transactions.

Also, it might be helpful to have a diagram like this.
https://speakerdeck.com/scalar/scalar-db-universal-transaction-manager?slide=27

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I applied the suggestion in 0db8458.

Also, it might be helpful to have a diagram like this.
https://speakerdeck.com/scalar/scalar-db-universal-transaction-manager?slide=27

Regarding this, let's do in another PR.

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
Two-phase commit transactions are basically executed by multiple processes/applications (a coordinator and participants).
However, in this example code, you can see multiple transaction managers (`transactionManager1` and `transactionManager2`) in a single process.

The following example code shows how to handle exceptions in Two-phase Commit Transactions:
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have anything to be noted in particular?
(like, If we don't follow the following guide on how to handle exceptions properly, you may face anomalies...)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 272d88b. Can you please check it?

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
When using an L3/L4 load balancer, you can use the same HTTP connection to send requests in a transaction, which guarantees the requests go to the same server.
When using an L7 load balancer, since requests in the same HTTP connection don't necessarily go to the same server, you need to use cookies or similar method to route requests to the correct server.
You can use session affinity (sticky session) in that case.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we introduce ScalarDB Cluster a bit?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, we should. Let's do that in another PR. Thanks.

docs/two-phase-commit-transactions.md Outdated Show resolved Hide resolved
Co-authored-by: Hiroyuki Yamada <mogwaing@gmail.com>
Co-authored-by: Josh Wong <joshua.wong@scalar-labs.com>
@brfrn169
Copy link
Collaborator Author

@feeblefakie As discussed, let's rephrase the terms Two-phase Commit Transactions to (transactions with) Two-phase Commit interface and normal transactions to (transactions with) One-phase Commit interface in a separate PR. Thanks.

@josh-wong
Copy link
Member

@brfrn169 Just one note about the following:

@feeblefakie As discussed, let's rephrase the terms Two-phase Commit Transactions to (transactions with) Two-phase Commit interface and normal transactions to (transactions with) One-phase Commit interface in a separate PR. Thanks.

If Two-phase Commit interface and One-phase Commit interface aren't proper names (in ScalarDB), we should lowercase them. Most mentions of these are lowercased in Google search results, so it doesn't seem to be a term that is often capitalized.

@komamitsu
Copy link
Contributor

normal transactions to (transactions with) One-phase Commit interface

I might be missing something and sorry in advance if this is a silly comment.

If normal transactions means DistributedTransaction in a sense, it sounds a bit weird since ScalarDB's normal transactions are internally 2PC.

@komamitsu
Copy link
Contributor

Ah, I missed #934 (comment). Got the point.

(single service and multi service transactions or something might sound a bit less weird to me...?)

@brfrn169
Copy link
Collaborator Author

If Two-phase Commit interface and One-phase Commit interface aren't proper names (in ScalarDB), we should lowercase them. Most mentions of these are lowercased in Google search results, so it doesn't seem to be a term that is often capitalized.

@josh-wong Thank you for the input. Let's proceed with the lowercase notation.

@brfrn169
Copy link
Collaborator Author

@komamitsu Yes, we should clarify that while ScalarDB uses a variant of the two-phase commit protocol (Consensus Commit), it offers two types of interfaces: one-phase commit interface and two-phase commit interface.

Copy link
Contributor

@feeblefakie feeblefakie left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you!

@feeblefakie feeblefakie merged commit 2ee3c39 into master Jul 23, 2023
13 checks passed
@feeblefakie feeblefakie deleted the revise-document-for-handling-exceptions-for-2pc branch July 23, 2023 11:23
josh-wong added a commit that referenced this pull request Sep 27, 2023
[skip ci]

Change `two-phase commit transactions` to `transactions with a two-phase commit interface` as noted in #934 (comment).
@josh-wong josh-wong mentioned this pull request Sep 27, 2023
6 tasks
josh-wong added a commit to scalar-labs/scalardb-samples that referenced this pull request Sep 27, 2023
[skip ci]

Change `two-phase commit transactions` to `transactions with a two-phase commit interface` as noted in scalar-labs/scalardb#934 (comment).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants