Setelah Anda melakukan upgrade instans kluster sharded ApsaraDB for MongoDB ke MongoDB 6.0 (versi minor 7.0.1 atau lebih baru) atau versi utama yang lebih baru, menjalankan sh.status() mungkin menunjukkan bahwa jumlah chunk tidak merata di seluruh shard—terkadang hanya satu chunk per shard. Topik ini menjelaskan mengapa hal ini terjadi dan cara menilai dengan benar apakah data tetap seimbang.
Gejala
Beberapa pengguna melaporkan bahwa setelah melakukan upgrade instans kluster sharded ApsaraDB for MongoDB ke MongoDB 6.0 (versi minor 7.0.1 atau lebih baru), sh.status() menunjukkan bahwa jumlah chunk di seluruh shard tidak lagi kira-kira sama, berbeda dengan kondisi sebelum upgrade. Pengamatan umum meliputi:
-
MongoDB 6.0 (minor 7.0.1 dan seterusnya): Jumlah chunk sangat bervariasi antar shard.
-
MongoDB 7.0 dan seterusnya: Setiap shard mungkin hanya menyimpan satu chunk.
Anda mungkin bertanya-tanya:
-
Apakah data tidak lagi terdistribusi secara merata?
-
Apakah balancer rusak?
-
Apakah proses upgrade gagal?
Ini adalah perilaku yang diharapkan setelah upgrade. Data Anda tetap terdistribusi secara merata, dan tidak diperlukan tindakan apa pun. Balancer baru tidak lagi menggunakan jumlah chunk sebagai kriteria penyeimbangan, melainkan menggunakan ukuran data aktual.
Mengapa hal ini terjadi
Perilaku sebelum MongoDB 6.0 minor 7.0.1
Sebelum ApsaraDB for MongoDB 6.0 minor 7.0.1, kluster sharded menyeimbangkan data sebagai berikut:
-
Ukuran chunk default adalah 64 MB.
-
Ketika sebuah chunk melebihi 64 MB, chunk tersebut akan secara otomatis dipisah (AutoSplit) menjadi chunk yang lebih kecil.
-
Balancer secara berkala memeriksa jumlah chunk pada setiap shard dan memigrasikan chunk (
moveChunk) begitu perbedaan melebihi ambang batas migrasi. -
Akhirnya, setiap shard menyimpan banyak chunk dengan jumlah yang kira-kira sama.
Dalam model ini, sh.status() menampilkan beberapa chunk per shard, sehingga memberikan kesan intuitif bahwa data terdistribusi secara merata.
Perubahan dalam MongoDB 6.0 mulai dari minor 7.0.1 (community 6.0.3)
Mulai dari ApsaraDB for MongoDB 6.0 minor 7.0.1, yang sesuai dengan MongoDB community 6.0.3, balancer memperkenalkan perubahan berikut:
-
AutoSplit dihapus: Chunk tidak lagi dipisah secara otomatis saat penuh. Pemisahan hanya terjadi jika diperlukan sebelum migrasi.
-
Kriteria penyeimbangan baru: Dari jumlah chunk menjadi ukuran data aktual.
-
Ambang batas migrasi disesuaikan: Migrasi dipicu ketika ukuran koleksi yang sama berbeda lebih dari tiga kali ukuran chunk di seluruh shard. (Ukuran chunk default mulai dari ApsaraDB for MongoDB 6.0 adalah 128 MB, artinya ambang batasnya adalah 384 MB.)
-
Perubahan terminologi: Konsep chunk kurang ditekankan, digantikan oleh "range".
moveChunkdigantikan olehmoveRange. -
Anda tidak perlu lagi menjalankan
sh.enableSharding()sebelum melakukan sharding pada koleksi.
Efek: Karena AutoSplit dihapus dan jumlah chunk tidak lagi menjadi kriteria penyeimbangan, jumlah chunk di seluruh shard mungkin menjadi tidak merata, yang merupakan hal normal. Untuk informasi lebih lanjut, lihat sh.enableAutoSplit().
Baru di MongoDB 7.0: AutoMerger
MongoDB 7.0 memperkenalkan fitur AutoMerger:
-
Balancer secara otomatis menggabungkan chunk yang bersebelahan dan dapat digabung pada shard yang sama.
-
AutoMerger berjalan di latar belakang sebagai bagian dari operasi penyeimbangan dan diaktifkan secara default.
-
Fitur ini berjalan setiap
autoMergerIntervalSecsdetik. -
Jika jendela penyeimbangan dikonfigurasi, AutoMerger hanya berjalan dalam jendela tersebut.
Efek: Di MongoDB 7.0 dan seterusnya, AutoMerger pada akhirnya dapat mengonsolidasi chunk pada setiap shard menjadi satu chunk tunggal. Hal ini juga normal. Untuk informasi lebih lanjut, lihat AutoMerger.
Mengapa perubahan ini dilakukan
Balancer berbasis jumlah chunk pada versi lama memiliki beberapa kelemahan:
|
Masalah |
Deskripsi |
|
Jumbo chunks |
Ketika kunci shard memiliki kardinalitas rendah, semua dokumen dalam sebuah chunk memiliki nilai kunci yang sama, sehingga chunk tersebut tidak dapat dipisah. Shard mungkin memiliki jumlah chunk yang sama tetapi penggunaan disk yang sangat berbeda. |
|
Write skew |
Jika kunci shard range mengandung komponen yang meningkat secara monoton, tulisan baru terkonsentrasi pada satu shard saja. |
|
Konsumsi resource |
Operasi AutoSplit dan moveChunk yang sering mengonsumsi sumber daya CPU signifikan dan berdampak pada performa workload. |
Menggunakan ukuran data aktual sebagai kriteria penyeimbangan memberikan gambaran distribusi data yang lebih akurat dan mengurangi pemisahan serta migrasi chunk yang tidak perlu.
Pemetaan versi
|
Versi ApsaraDB for MongoDB |
Versi Community |
Perilaku balancer |
|
MongoDB 4.4 |
MongoDB 4.4 |
Lama: AutoSplit + penyeimbangan berbasis jumlah chunk |
|
MongoDB 5.0 |
MongoDB 5.0 |
Lama: AutoSplit + penyeimbangan berbasis jumlah chunk |
|
MongoDB 6.0 (minor 7.0.0) |
MongoDB 6.0.0 |
Lama: AutoSplit + penyeimbangan berbasis jumlah chunk |
|
MongoDB 6.0 (minor 7.0.1 dan seterusnya) |
MongoDB 6.0.3 |
AutoSplit dihapus + penyeimbangan berbasis ukuran (jumlah chunk mungkin tidak merata) |
|
MongoDB 7.0 dan seterusnya |
MongoDB 7.0+ |
AutoSplit dihapus + penyeimbangan berbasis ukuran + AutoMerger mengonsolidasi chunk |
Perbandingan lintas versi
|
Item |
MongoDB 6.0 (sebelum minor 7.0.1) |
MongoDB 6.0 (minor 7.0.1 dan seterusnya) |
MongoDB 7.0 dan seterusnya |
|
AutoSplit |
Diaktifkan. Chunk dipisah secara otomatis saat penuh. |
Dinonaktifkan |
Dimatikan |
|
AutoMerger |
Tidak tersedia |
Tidak tersedia |
Diaktifkan. Chunk digabung secara otomatis. |
|
Kriteria penyeimbangan |
Jumlah chunk |
Ukuran data aktual |
Ukuran data aktual |
|
Jumlah chunk per shard |
Banyak, kira-kira sama |
Tidak merata, mungkin berbeda antar shard |
Mungkin konvergen menjadi satu |
|
Ambang batas migrasi |
Perbedaan jumlah chunk ≥ 1 (MongoDB 4.2 dan seterusnya) |
Ukuran data berbeda lebih dari tiga kali ukuran chunk |
Ukuran data berbeda lebih dari tiga kali ukuran chunk |
|
|
Diperlukan sebelum sharding |
Opsional di MongoDB 6.0 dan seterusnya |
Opsional |
|
Cara menilai keseimbangan |
|
|
|
Data uji
Hasil berikut diukur setelah tool YCSB memasukkan 50 juta record ke instans kluster sharded ApsaraDB for MongoDB yang menjalankan MongoDB 4.4, MongoDB 6.0, dan MongoDB 8.0.
MongoDB 4.4 (perilaku lama)
Jalankan sh.status(). Fokus pada bidang chunkMetadata dalam output. Setiap shard memiliki 435 chunk, dan jumlahnya sama. Ini adalah hasil dari mekanisme AutoSplit lama:
mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfda6dec76b373f5eda81') }
---
shards
[
{
_id: 'd-uf6xxxx1',
host: 'mgset-1xxxxx0/192.168.XX.2:3005,192.168.XX.11:3002',
state: 1
},
{
_id: 'd-uf6xxxx2',
host: 'mgset-1xxxxx1/192.168.XX.4:3002,192.168.XX.5:3002',
state: 1
}
]
---
active mongoses
[ { '4.4.30': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
'Currently enabled': 'yes',
'Failed balancer rounds in last 5 attempts': 0,
'Currently running': 'no',
'Migration Results for the last 24 hours': { '947': 'Success' }
}
---
databases
[
{
database: {
_id: 'ycsb',
primary: 'd-uf6xxxx2',
partitioned: true
},
collections: {
'ycsb.test1': {
shardKey: { _id: 'hashed' },
unique: false,
balancing: true,
chunkMetadata: [
{ shard: 'd-uf6xxxx1', nChunks: 435 },
{ shard: 'd-uf6xxxx2', nChunks: 435 }
],
chunks: [
'too many chunks to print, use verbose if you want to force print'
],
tags: []
}
}
}
]
Jalankan db.test1.getShardDistribution(). Fokus pada bidang data (ukuran data) dan chunks (jumlah chunk) untuk setiap shard:
mongos> use ycsb
switched to db ycsb
mongos> db.test1.getShardDistribution()
Shard d-uf6xxxx1 at mgset-1xxxxx0/192.168.XX.2:3005,192.168.XX.11:3002
{
data: '27.2GiB',
docs: 25014674,
chunks: 435,
'estimated data per chunk': '64.04MiB',
'estimated docs per chunk': 57504
}
---
Shard d-uf6xxxx2 at mgset-1xxxxx1/192.168.XX.4:3002,192.168.XX.5:3002
{
data: '36.23GiB',
docs: 33313293,
chunks: 435,
'estimated data per chunk': '85.29MiB',
'estimated docs per chunk': 76582
}
---
Totals
{
data: '63.44GiB',
docs: 58327967,
chunks: 870,
'Shard d-uf6xxxx1': [
'42.88 % data',
'42.88 % docs in cluster',
'1KiB avg obj size on shard'
],
'Shard d-uf6xxxx2': [
'57.11 % data',
'57.11 % docs in cluster',
'1KiB avg obj size on shard'
]
}
MongoDB 6.0 (minor 7.0.1 dan seterusnya)
Jalankan sh.status(). Fokus pada bidang chunkMetadata. Jumlah chunk terlihat sangat tidak merata di seluruh shard (216 vs. 1):
mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdc420578638757c1d06') }
---
shards
[
{
_id: 'd-uf6xxxx3',
host: 'mgset-1xxxxx2/192.168.XX.7:3002,192.168.XX.8:3002',
state: 1,
topologyTime: Timestamp({ t: 1778122310, i: 2 })
},
{
_id: 'd-uf6xxxx4',
host: 'mgset-1xxxxx3/192.168.XX.9:3002,192.168.XX.10:3002',
state: 1,
topologyTime: Timestamp({ t: 1778122310, i: 9 })
}
]
---
active mongoses
[ { '6.0.27': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
'Currently running': 'no',
'Currently enabled': 'yes',
'Failed balancer rounds in last 5 attempts': 0,
'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
{
database: {
_id: 'ycsb',
primary: 'd-uf6xxxx4',
partitioned: false,
version: {
uuid: UUID('4ee45231-9585-4dba-8f34-f624860e1a79'),
timestamp: Timestamp({ t: 1778122930, i: 1 }),
lastMod: 1
}
},
collections: {
'ycsb.test2': {
shardKey: { _id: 'hashed' },
unique: false,
balancing: true,
allowMigrations: true,
chunkMetadata: [
{ shard: 'd-uf6xxxx3', nChunks: 216 },
{ shard: 'd-uf6xxxx4', nChunks: 1 }
],
chunks: [
'too many chunks to print, use verbose if you want to force print'
],
tags: []
}
}
}
]
Jalankan db.test2.getShardDistribution(). Fokus pada persentase data untuk setiap shard. Meskipun terdapat perbedaan besar dalam jumlah chunk (216 vs. 1), data tetap terdistribusi secara merata (50,31% vs. 49,68%):
mongos> use ycsb
switched to db ycsb
mongos> db.test2.getShardDistribution()
Shard d-uf6xxxx4 at mgset-1xxxxx3/192.168.XX.9:3002,192.168.XX.10:3002
{
data: '27.36GiB',
docs: 32285618,
chunks: 1,
'estimated data per chunk': '27.36GiB',
'estimated docs per chunk': 32285618
}
---
Shard d-uf6xxxx3 at mgset-1xxxxx2/192.168.XX.7:3002,192.168.XX.8:3002
{
data: '27.01GiB',
docs: 24841944,
chunks: 216,
'estimated data per chunk': '128.09MiB',
'estimated docs per chunk': 115009
}
---
Totals
{
data: '54.38GiB',
docs: 57127562,
chunks: 217,
'Shard d-uf6xxxx4': [
'50.31 % data',
'56.51 % docs in cluster',
'1KiB avg obj size on shard'
],
'Shard d-uf6xxxx3': [
'49.68 % data',
'43.48 % docs in cluster',
'1KiB avg obj size on shard'
]
}
MongoDB 8.0 (dengan AutoMerger)
Segera setelah migrasi selesai, jalankan sh.status(). Fokus pada bidang chunkMetadata. Setiap shard masih memiliki beberapa chunk (55 vs. 1):
mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdbdd7b0e3d9551dd833') }
---
shards
[
{
_id: 'd-uf6xxxx5',
host: 'mgset-1xxxxx4/192.168.XX.1:3000,192.168.XX.3:3002',
state: 1,
topologyTime: Timestamp({ t: 1778122320, i: 8 }),
replSetConfigVersion: Long('-1')
},
{
_id: 'd-uf6xxxx6',
host: 'mgset-1xxxxx5/192.168.XX.5:3003,192.168.XX.6:3003',
state: 1,
topologyTime: Timestamp({ t: 1778122319, i: 10 }),
replSetConfigVersion: Long('-1')
}
]
---
active mongoses
[ { '8.0.18': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
'Currently enabled': 'yes',
'Failed balancer rounds in last 5 attempts': 0,
'Currently running': 'no',
'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
{
database: {
_id: 'ycsb',
primary: 'd-uf6xxxx6',
version: {
uuid: UUID('98799357-048e-45bc-a472-387165e0fe74'),
timestamp: Timestamp({ t: 1778122931, i: 2 }),
lastMod: 1
}
},
collections: {
'ycsb.test2': {
shardKey: { _id: 'hashed' },
unique: false,
balancing: true,
allowMigrations: true,
chunkMetadata: [
{ shard: 'd-uf6xxxx5', nChunks: 55 },
{ shard: 'd-uf6xxxx6', nChunks: 1 }
],
chunks: [
'too many chunks to print, use verbose if you want to force print'
],
tags: []
}
}
}
]
Setelah AutoMerger selesai, jalankan sh.status() lagi. Fokus pada bidang chunkMetadata. Setiap shard kini hanya memiliki satu chunk:
mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdbdd7b0e3d9551dd833') }
---
shards
[
{
_id: 'd-uf6xxxx5',
host: 'mgset-1xxxxx4/192.168.XX.1:3000,192.168.XX.3:3002',
state: 1,
topologyTime: Timestamp({ t: 1778122320, i: 8 }),
replSetConfigVersion: Long('-1')
},
{
_id: 'd-uf6xxxx6',
host: 'mgset-1xxxxx5/192.168.XX.5:3003,192.168.XX.6:3003',
state: 1,
topologyTime: Timestamp({ t: 1778122319, i: 10 }),
replSetConfigVersion: Long('-1')
}
]
---
active mongoses
[ { '8.0.18': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
'Currently enabled': 'yes',
'Failed balancer rounds in last 5 attempts': 0,
'Currently running': 'no',
'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
{
database: {
_id: 'ycsb',
primary: 'd-uf6xxxx6',
version: {
uuid: UUID('98799357-048e-45bc-a472-387165e0fe74'),
timestamp: Timestamp({ t: 1778122931, i: 2 }),
lastMod: 1
}
},
collections: {
'ycsb.test2': {
shardKey: { _id: 'hashed' },
unique: false,
balancing: true,
allowMigrations: true,
chunkMetadata: [
{ shard: 'd-uf6xxxx5', nChunks: 1 },
{ shard: 'd-uf6xxxx6', nChunks: 1 }
],
chunks: [
{ min: { _id: MinKey() }, max: { _id: Long('-58615400192952365') }, 'on shard': 'd-uf6xxxx5', 'last modified': Timestamp({ t: 217, i: 2 }) },
{ min: { _id: Long('-58615400192952365') }, max: { _id: MaxKey() }, 'on shard': 'd-uf6xxxx6', 'last modified': Timestamp({ t: 217, i: 1 }) }
],
tags: []
}
}
}
]
Jalankan db.test2.getShardDistribution(). Fokus pada persentase data. Meskipun setiap shard hanya memiliki satu chunk, data tetap terdistribusi secara merata (49,67% vs. 50,32%):
mongos> use ycsb
switched to db ycsb
mongos> db.test2.getShardDistribution()
Shard d-uf6xxxx5 at mgset-1xxxxx4/192.168.XX.1:3000,192.168.XX.3:3002
{
data: '27.01GiB',
docs: 24841944,
chunks: 1,
'estimated data per chunk': '27.01GiB',
'estimated docs per chunk': 24841944
}
---
Shard d-uf6xxxx6 at mgset-1xxxxx5/192.168.XX.5:3003,192.168.XX.6:3003
{
data: '27.37GiB',
docs: 35898246,
chunks: 1,
'estimated data per chunk': '27.37GiB',
'estimated docs per chunk': 35898246
}
---
Totals
{
data: '54.39GiB',
docs: 60740190,
chunks: 2,
'Shard d-uf6xxxx5': [
'49.67 % data',
'40.89 % docs in cluster',
'1KiB avg obj size on shard'
],
'Shard d-uf6xxxx6': [
'50.32 % data',
'59.1 % docs in cluster',
'1KiB avg obj size on shard'
]
}
Kesimpulan: Data uji pada ketiga versi menunjukkan bahwa terlepas dari perubahan jumlah chunk (870 → 217 → 2), data tetap terdistribusi secara merata di seluruh shard. Perbedaan jumlah chunk semata-mata disebabkan oleh perubahan manajemen internal dan tidak memengaruhi distribusi data aktual atau workload Anda.
Cara menilai keseimbangan data dengan benar
Setelah Anda melakukan upgrade ke MongoDB 6.0 (minor 7.0.1) atau lebih baru, gunakan metode berikut untuk mengevaluasi keseimbangan:
Disarankan: getShardDistribution()
Sambungkan ke mongos dan jalankan:
use <your_database>
db.<your_collection>.getShardDistribution()
Perintah ini menampilkan ukuran data, jumlah dokumen, dan persentase koleksi pada setiap shard, memberikan gambaran akurat tentang distribusi.
Helper: db.stats()
use <your_database>
db.stats()
Mengembalikan penggunaan penyimpanan keseluruhan database di seluruh shard.
Tidak lagi disarankan: jumlah chunk pada sh.status()
sh.status() masih berfungsi, tetapi jumlah chunk tidak lagi mencerminkan keseimbangan data. Jumlah chunk yang tidak merata atau satu chunk per shard adalah hal normal dan tidak menunjukkan adanya masalah pada distribusi data.
FAQ
T: Apakah saya akan kehilangan data jika jumlah chunk menjadi tidak merata atau turun menjadi satu setelah upgrade?
J: Tidak. Chunk hanyalah unit logis internal yang digunakan MongoDB untuk mengelola data. Perubahan jumlah chunk tidak memengaruhi data aktual, yang tetap utuh pada setiap shard.
T: Apakah saya perlu menjalankan perintah split secara manual untuk memisah chunk?
J: Tidak. Balancer baru memisah data sesuai kebutuhan sebelum migrasi. Tidak diperlukan intervensi manual.
T: Apakah balancer masih berfungsi setelah upgrade?
J: Ya. Balancer terus beroperasi tetapi menggunakan ukuran data sebagai kriterianya, bukan jumlah chunk. Ketika perbedaan ukuran data antar shard melebihi ambang batas, balancer akan memigrasikan data secara otomatis.
T: Apa perbedaan perilaku chunk antara MongoDB 6.0 dan MongoDB 7.0 setelah upgrade?
J: MongoDB 6.0 (minor 7.0.1 dan seterusnya) menghapus AutoSplit dan menggunakan penyeimbangan berbasis ukuran, sehingga jumlah chunk di seluruh shard mungkin tidak merata. MongoDB 7.0 menambahkan AutoMerger di atasnya, yang mengonsolidasi chunk. Setiap shard pada akhirnya mungkin hanya menyimpan satu chunk. Dalam kedua kasus, data tetap terdistribusi secara merata.
T: Apakah wajar jika terdapat banyak chunk selama migrasi?
J: Ya. Balancer melakukan pemisahan yang diperlukan selama migrasi, sehingga beberapa chunk mungkin muncul sementara. Di MongoDB 7.0 dan seterusnya, AutoMerger akan mengonsolidasinya setelah migrasi selesai. Di MongoDB 6.0, chunk tersebut mungkin tetap ada, tetapi keseimbangan data tidak terpengaruh.
T: Apakah perubahan ini memengaruhi beban kerja saya?
J: Tidak. Perubahan ini transparan bagi aplikasi. Bahkan, perilaku baru ini mengurangi pemisahan dan migrasi yang tidak perlu, yang sering kali meningkatkan performa.