raft order

56 views
Skip to first unread message

Terry Tan

unread,
Aug 5, 2016, 12:36:28 AM8/5/16
to raft-dev
Hey,

I have seen the open source project like copy cat , but i did not find any machanism to keep the order of the request ,
let's say we have two requests accepted by the leader parallelly , then two requests may be assigned the same index,
how to avoid this thing from happening ,is there anyone who can help me to find the answer ?

Jordan Halterman

unread,
Aug 5, 2016, 1:22:37 AM8/5/16
to raft...@googlegroups.com
There's no chance two requests will be assigned the same index. It would be a very serious bug if that were to happen, and I would love to see that. 

When concurrent requests from a single client are submitted via the Copycat client, the client assigned sequence numbers to the requests. The sequence numbers are used by the leader to ensure the requests are written to the log in the order in which they occurred on the client.

http://atomix.io/copycat/docs/client-interaction/#preserving-program-order

When requests are received by the leader, they're sequenced on a single thread where they're appended to the log and assigned a sequential index. For concurrent requests from a single client, the sequencing will be in the client's program order. For concurrent requests from multiple clients they'll be interleaved, but each will get a unique index.

--
You received this message because you are subscribed to the Google Groups "raft-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to raft-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Terry Tan

unread,
Aug 5, 2016, 5:50:19 AM8/5/16
to raft-dev

Hey,

I have gone thought the doc ,i found there is another problem ,let's say , if there are 3 commands , we received 1 and 
3 ,and server will process command 1 ,and command 3 will be queued , meanwhile ,if 2 by any chance is lost , then the rest of the commands will never get a chance to be executed . because the request no. will never be less than nextsequence any more, i dont know if i am right?
To unsubscribe from this group and stop receiving emails from it, send an email to raft-dev+u...@googlegroups.com.

jordan.h...@gmail.com

unread,
Aug 5, 2016, 10:16:35 PM8/5/16
to raft...@googlegroups.com
That would be true without some additional mechanisms. Those requests are idempotent, so clients are just designed to timeout and resend requests after x milliseconds. So, if 1 and 3 make it to the leader but 2 gets lost, the client will resend 2. But this is why maintaining order is so important, particularly with retries. In this case the leader receives 1, 3, then 2 and will then reorder them as 1, 2, and 3. More accurately, the leader will process 1 then wait for 2 before processing 3. In the event a command is resent by the client but has already been written to the leader's log it will simply return a cached output for the command without actually applying it to the state machine. This is the mechanism for linearizable semantics described in section 6.3 of the Raft dissertation. Copycat simply expands upon that mechanism to ensure that concurrent requests from a single client are handled by the leader in proper order.

Terry Tan

unread,
Aug 6, 2016, 4:20:46 AM8/6/16
to raft-dev
Hey Jordan,

Thank you for your reply , i found another problem that is you have got code like below, the read part is not sychronized ,let's say if two clients doing operation, it may have got the same index ,how do you deal with this thing?



 /**
   * Applies the given command to the log.
   */
  private void applyCommand(CommandRequest request, ServerSessionContext session, CompletableFuture<CommandResponse> future) {
    final Command command = request.command();

    final long term = context.getTerm();
    final long timestamp = System.currentTimeMillis();
    final long index;

    // Create a CommandEntry and append it to the log.
    try (CommandEntry entry = context.getLog().create(CommandEntry.class)) {
      entry.setTerm(term)
        .setSession(request.session())
        .setTimestamp(timestamp)
        .setSequence(request.sequence())
        .setCommand(command);
      index = context.getLog().append(entry);
      LOGGER.debug("{} - Appended {} to log at index {}", context.getCluster().member().address(), entry, index);
    }

    // Replicate the command to followers.
Reply all
Reply to author
Forward
0 new messages