Skip to content

Commit

Permalink
use new way to generate the split key
Browse files Browse the repository at this point in the history
  • Loading branch information
nolouch committed Oct 11, 2018
1 parent 61d6777 commit 38e55a0
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 64 deletions.
4 changes: 1 addition & 3 deletions table/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ func decodeCmpUintToInt(u uint64) int64 {
// DecodeBytes decodes bytes which is encoded by EncodeBytes before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytes(b []byte) ([]byte, []byte, error) {
if len(b) == 0 {
return b, nil, nil
}

data := make([]byte, 0, len(b))
for {
if len(b) < encGroupSize+1 {
Expand Down
4 changes: 2 additions & 2 deletions tools/pd-simulator/simulator/cases/import_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ func newImportData() *Case {
if leaderTotal == 0 || peerTotal == 0 {
return false
}
leaderLog := "leader distribute (table2)"
peerLog := "peer distribute (table2)"
leaderLog := fmt.Sprintf("table2 total %d leaders -", leaderTotal)
peerLog := fmt.Sprintf("table2 total %d peers-", peerTotal)
for storeID := 1; storeID <= 10; storeID++ {
if leaderCount, ok := leaderDstb[uint64(storeID)]; ok {
leaderLog = fmt.Sprintf("%s [store %d]:%.2f%%", leaderLog, storeID, float64(leaderCount)/float64(leaderTotal)*100)
Expand Down
96 changes: 45 additions & 51 deletions tools/pd-simulator/simulator/raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,20 +298,25 @@ func generateKeys(size int) []string {
return v
}

func generateTableKey(tableID, rowID int64) []byte {
key := table.GenerateRowKey(tableID, rowID)
// To try not to split the same keys as much as possible
for i := 0; i <= keyLen; i++ {
key = append(key, byte(rand.Intn(0xFF)))
}

return table.EncodeBytes(key)
}

func generateTableKeys(tableCount, size int) []string {
v := make([]string, 0, size)
groupNumber := size / tableCount
id := 0
tableID := 0
var key []byte
for size > 0 {
id++
tableID := id
tableID++
for rowID := 0; rowID < groupNumber && size > 0; rowID++ {
key := table.GenerateRowKey(int64(tableID), int64(rowID))
if rowID == 0 {
key = table.GenerateTableKey(int64(tableID))
continue
}
key = table.EncodeBytes(key)
key = generateTableKey(int64(tableID), int64(rowID))
v = append(v, string(key))
size--
}
Expand Down Expand Up @@ -343,6 +348,11 @@ func generateSplitKey(start, end []byte) []byte {
}

func mustDecodeMvccKey(key []byte) []byte {
// FIXME: seems nil key not encode to order compare key
if len(key) == 0 {
return nil
}

left, res, err := table.DecodeBytes(key)
if len(left) > 0 {
simutil.Logger.Fatalf("Decode key left some bytes: %v", key)
Expand All @@ -355,21 +365,21 @@ func mustDecodeMvccKey(key []byte) []byte {

// generateTiDBEncodedSplitKey calculates the split key with start and end key,
// the keys are encoded according to the TiDB encoding rules.
// The algorithm is the computationally the logical median.
func generateTiDBEncodedSplitKey(start, end []byte) []byte {
if bytes.Equal(start, end) {
simutil.Logger.Fatal("start key and end key should not be same")
if len(start) == 0 && len(end) == 0 {
// suppose use table key with table ID 0 and row ID 0.
return generateTableKey(0, 0)
}

start = mustDecodeMvccKey(start)
end = mustDecodeMvccKey(end)
if len(start) == 0 && len(end) == 0 {
// suppose use table key with table ID: 0
key := table.GenerateTableKey(int64(0))
return table.EncodeBytes(key)
}
// make the start and end in same length.

// make the start key and end key in same length.
if len(end) == 0 {
end = make([]byte, len(start))
end = make([]byte, 0, len(start))
for i := range end {
end[i] = 0xFF
}
} else if len(start) < len(end) {
pad := make([]byte, len(end)-len(start))
start = append(start, pad...)
Expand All @@ -378,39 +388,23 @@ func generateTiDBEncodedSplitKey(start, end []byte) []byte {
end = append(end, pad...)
}

borrow := false
equalWithStart := true
var (
d uint16
e uint16
)
res := make([]byte, len(start))
for i := 0; i < len(start); i++ {
s := start[i]
e = uint16(end[i])
if borrow {
e += 0x100
}
// if can't divide 2, assume that the lowposition borrows one from the high position, and then can divide 2.
borrow = (uint16(s)+e)%2 != 0
d = (uint16(s) + e) / 2
if d != uint16(s) {
equalWithStart = false
switch bytes.Compare(start, end) {
case 0:
return table.EncodeBytes(start)
case 1:
simutil.Logger.Fatalf("invalid start key: %v end key: %v", start, end)
case -1:
}
for i := len(end) - 1; i >= 0; i-- {
if i == 0 {
simutil.Logger.Fatalf("invalid end key: %v to split", end)
}
if d >= 0x100 {
d -= 0x100
for j := i - 1; j >= 0; j-- {
res[j]++
if res[j] != 0 {
break
}
}
if end[i] == 0 {
end[i] = 0xFF
} else {
end[i]--
break
}
res[i] = byte(d)
}
if equalWithStart {
res = append(res, 0)
}

return table.EncodeBytes(res)
return table.EncodeBytes(end)
}
43 changes: 35 additions & 8 deletions tools/pd-simulator/simulator/raft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"testing"

. "github.com/pingcap/check"
"github.com/pingcap/pd/table"
)

func Test(t *testing.T) {
Expand All @@ -35,15 +36,41 @@ func (t *testTableKeySuite) TestGenerateTableKeys(c *C) {

for i := 1; i < len(keys); i++ {
c.Assert(keys[i-1], Less, keys[i])
splitKey := string(generateTiDBEncodedSplitKey([]byte(keys[i-1]), []byte(keys[i])))
c.Assert(keys[i-1], Less, splitKey)
c.Assert(splitKey, Less, keys[i])
s := []byte(keys[i-1])
e := []byte(keys[i])
for j := 0; j < 1000; j++ {
split := generateTiDBEncodedSplitKey(s, e)
c.Assert(s, Less, split)
c.Assert(split, Less, e)
e = split
}
}

}

func (t *testTableKeySuite) TestGenerateSplitKey(c *C) {
s := []byte(table.EncodeBytes([]byte("a")))
e := []byte(table.EncodeBytes([]byte("ab")))
for i := 0; i <= 100; i++ {
cc := generateTiDBEncodedSplitKey(s, e)
c.Assert(s, LessEqual, cc)
c.Assert(cc, LessEqual, e)
e = cc
}

// empty key
startKey := []byte("")
endKey := []byte{116, 128, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 248}
splitKey := generateTiDBEncodedSplitKey(startKey, endKey)
c.Assert(startKey, Less, splitKey)
c.Assert(splitKey, Less, endKey)
s = []byte("")
e = []byte{116, 128, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 248}
splitKey := generateTiDBEncodedSplitKey(s, e)
c.Assert(s, Less, splitKey)
c.Assert(splitKey, Less, e)

// split equal key
s = table.EncodeBytes([]byte{116, 128, 0, 0, 0, 0, 0, 0, 1})
e = table.EncodeBytes([]byte{116, 128, 0, 0, 0, 0, 0, 0, 1, 0})
c.Assert(s, Less, e)
splitKey = generateTiDBEncodedSplitKey(s, e)
c.Assert(s, Less, splitKey)
c.Assert(splitKey, LessEqual, e)

}

0 comments on commit 38e55a0

Please sign in to comment.