Jelajahi Sumber

Fix selection of host by token (#1405)

We've seen increased per-query latency after upgrading to latest gocql.
This commit fixes the latency issue for us.

This partially reverts 7b17705d75148afe48e336a49743178a201cdda3. There
were multiple unrelated changes in that commit. The relevant part of
that commit's description is:

    Fix finding the correct token in the token ring for host selection.

Unfortunately that description does not contain the details of the issue
it was aimed to fix.

The change in 7b17705d75148afe48e336a49743178a201cdda3 also made the two
binary search implementations (tokenRingReplicas.replicasFor and
tokenRing.GetHostForToken) inconsistent, reverting the change fixed this
discrepancy as well.

The token values returned in system.peers and system.local tables are
ends of ranges that the nodes are responsible for[1], so we never need
to rollunder.

When searching for a node responsible for token X (computed from
partition key), we need to find hostTokens with end token Y with the
lowest value such that Y >= X. In case X is larger than the largest
end token value in tokenRingReplicas, we wrap the ring and the node with
the lowest token is responsible (i.e. the hostTokens at index 0).

[1] https://docs.datastax.com/en/dse/6.7/dse-arch/datastax_enterprise/dbArch/archAboutDataDistribute.html
Martin Sucha 5 tahun lalu
induk
melakukan
9b1842907e
2 mengubah file dengan 2 tambahan dan 12 penghapusan
  1. 2 2
      policies_test.go
  2. 0 10
      topology.go

+ 2 - 2
policies_test.go

@@ -106,8 +106,8 @@ func TestHostPolicy_TokenAware_SimpleStrategy(t *testing.T) {
 	// now the token ring is configured
 	query.RoutingKey([]byte("20"))
 	iter = policy.Pick(query)
-	iterCheck(t, iter, "0")
 	iterCheck(t, iter, "1")
+	iterCheck(t, iter, "2")
 }
 
 // Tests of the host pool host selection policy implementation
@@ -608,7 +608,7 @@ func TestHostPolicy_TokenAware_NetworkStrategy(t *testing.T) {
 	}, policyInternal.getMetadataReadOnly().replicas)
 
 	// now the token ring is configured
-	query.RoutingKey([]byte("23"))
+	query.RoutingKey([]byte("18"))
 	iter = policy.Pick(query)
 	// first should be hosts with matching token from the local DC
 	iterCheck(t, iter, "4")

+ 0 - 10
topology.go

@@ -33,19 +33,9 @@ func (h tokenRingReplicas) replicasFor(t token) *hostTokens {
 		return !h[i].token.Less(t)
 	})
 
-	// TODO: simplify this
-	if p < len(h) && h[p].token == t {
-		return &h[p]
-	}
-
-	p--
-
 	if p >= len(h) {
 		// rollover
 		p = 0
-	} else if p < 0 {
-		// rollunder
-		p = len(h) - 1
 	}
 
 	return &h[p]