Saat mengembangkan sistem server, untuk beradaptasi dengan permintaan data yang besar dan bersamaan, kita sering perlu menyimpan data secara tidak sinkron, terutama ketika bekerja dalam sistem terdistribusi. Pada saat ini, kami tidak dapat menunggu database penyisipan untuk mengembalikan ID otomatis untuk diambil. Sebagai gantinya, kita perlu menghasilkan ID unik global sebelum memasukkan database, menggunakan ID unik global. Di server game, ID unik global dapat digunakan untuk kombinasi server di masa depan dan tidak akan ada konflik utama. Di masa depan, jika terjadi pertumbuhan bisnis, basis data dan tabel split dapat diimplementasikan. Misalnya, item pengguna harus ditempatkan di pecahan yang sama, dan pecahan ini dapat ditentukan berdasarkan nilai kisaran ID pengguna, seperti ID pengguna dengan ID pengguna yang lebih besar dari 1000 dan kurang dari 100.000 dalam pecahan. Saat ini, berikut ini biasanya digunakan:
1. UUID Java sendiri.
Uuid.randomuuid (). Tostring () dapat dihasilkan secara lokal melalui program layanan, dan generasi ID tidak tergantung pada implementasi database.
Keuntungan:
Menghasilkan id secara lokal dan tidak memerlukan panggilan jarak jauh.
Dunia adalah satu -satunya yang tidak mengulangi.
Kemampuan ekspansi horizontal sangat bagus.
Kerugian:
ID memiliki 128 bit, yang memakan ruang besar dan perlu disimpan sebagai tipe string, dan efisiensi pengindeksan sangat rendah.
ID yang dihasilkan tidak mengandung cap waktu, dan tren tidak dapat dijamin akan meningkat. Sulit untuk mengandalkan saat membagi database basis data.
2. Metode Incr Berbasis Redis
Redis sendiri dioperasikan satu threaded, dan ACCT memastikan operasi bertambah atom. Ini juga mendukung pengaturan ukuran langkah tambahan.
Keuntungan:
Mudah digunakan dan mudah digunakan. Anda hanya perlu memanggil API Redis.
Beberapa server dapat berbagi layanan Redis untuk mengurangi waktu pengembangan data bersama.
Redis dapat digunakan dalam kelompok untuk menyelesaikan masalah satu titik kegagalan.
Kerugian:
Jika sistemnya terlalu besar, beberapa layanan permintaan untuk Redis pada saat yang sama akan menyebabkan kemacetan kinerja.
3. Solusi dari Flicker
Solusi ini didasarkan pada ID Peningkatan Otomatis Database, yang menggunakan database terpisah khusus untuk menghasilkan ID. Anda dapat menemukan detailnya secara online. Saya pribadi berpikir itu cukup merepotkan untuk digunakan dan tidak disarankan untuk menggunakannya.
4. Twitter Snowflake
Snowflake adalah algoritma generasi ID terdistribusi yang merupakan open source di Twitter. Gagasan intinya adalah untuk menghasilkan ID tipe panjang, menggunakan 41bit sebagai jumlah milidetik, 10bit sebagai nomor mesin, dan 12bit sebagai nomor seri dalam milidetik. Algoritma ini secara teoritis dapat menghasilkan ID hingga 1.000*(2^12) per detik per mesin, yaitu sekitar 400W, yang sepenuhnya dapat memenuhi kebutuhan bisnis.
Menurut ide algoritma Snowflake, kami dapat menghasilkan ID unik global kami sendiri berdasarkan skenario bisnis kami. Karena panjang jenis panjang dalam java adalah 64bit, ID yang kami rancang perlu dikontrol pada 64bit.
Keuntungan: kinerja tinggi, latensi rendah; aplikasi independen; tertib demi waktu.
Kekurangan: Pengembangan dan penyebaran independen diperlukan.
Misalnya, ID yang kami rancang berisi informasi berikut:
| 41 bit: cap waktu | 3 bit: Area | 10 bit: Nomor mesin | 10 bit: Nomor Seri |
Kode Java yang menghasilkan ID unik:
/*** Generator ID Kustom* aturan pembuatan ID: ID hingga 64 bit ** | 41 Bit: Timestamp (MS) | 3 bit: Area (ruang komputer) | 10 bit: Nomor mesin | 10 Bit: Nomor Seri |*/Kelas Publik GameUUid {// Waktu Referensi Private Long Twepoch = 1288834974657L; // Kamis, 04 Nov 2010 01:42:54 GMT // DAFFASI BENAR Region Private Private Final Long RegionIdbits = 3L; // Digit Identifikasi Mesin Private Private Final Long WorkeridBits = 10L; // Nomor Serial Digit Private Final Long Sequencebits = 10L; // Nilai Maksimum Wilayah Bendera Id ID Private Static Private Static Final Long Sequencebits = 10L;//Nilai Maksimum Wilayah Bendera Wilayah ID ID ID Private Static Final Private Static Long Static = -1 Maximum value of machine ID private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// Maximum value of serial number ID private final static long sequenceMask = -1L ^ (-1L << sequenceBits);// The machine ID is shifted 10 bits to the left private final static long workerIdShift = sequenceBits;// The service ID is shifted left by 20 bits private final static long regionIdshift = SequenceBits + workerIdbits; // Waktu bergeser dengan 23 bit privat final statis statis waktu panjang longtshift = sequencebits + workeridbits + regionIdbits; private static long lastTimestamp = -1l; Urutan panjang pribadi = 0l; pekerja panjang final swasta; regional long final swasta; Public GameUUid (Long WorkerID, Long RegionID) {// Jika di luar jangkauan, pengecualian dilemparkan jika (WorkerId> MaxWorkerID || WorkerID <0) {Throw IllegalArgumentException baru ("ID Pekerja tidak bisa lebih besar dari %d atau lebih dari 0");} if (regionid> maxregionid || lebih besar dari %d atau kurang dari 0 ");} this.workerid = workerid; this.regionid = regionId;} public GameUuid (long workerid) {// jika di luar jangkauan dilemparkan jika (workerid> maxworkerid || workerid <0) {lempar new ilegalargumentException ("worker id tidak lebih besar dari %d atau lebih dari 0");} this.workerid = workerid = ini. this.nextId (false, 0);}/*** Kode aktual yang dihasilkan oleh @param ispadding* @param busid* @return*/private disinkronkan long nextid (boolean ispadding, long busid) {long timestamp = timeGen (); long paddingnum = regionId; if (if (ispadding) {paddingnum (paddingnum = long paddingnum = regionId; if (iSpadding) {Paddingnum = paddingnum = BUDDINGNUM = region; if (ispadding) {paddingnum = paddingnum = BUDDINGNUM = region; {lempar pengecualian baru ("Jam bergerak mundur. Menolak untuk menghasilkan ID untuk" + (lastTimestamp - timestamp) + "jutaan detik");} catch (pengecualian e) {e.printstacktrace ();}} // jika waktu generasi terakhir adalah sama dengan waktu saat ini, if ifeSamp (); {// Urutan meningkat dengan sendirinya, karena urutannya hanya 10bit, dikombinasikan dengan sequencemask dan menghapus urutan bit tinggi = (urutan + 1) & sequencemask; // menilai apakah itu meluap, yaitu, melebihi 1024 di setiap milidetik. Ketika 1024, dikombinasikan dengan sequencemask, dan urutan sama dengan 0if (sequence == 0) {// spin tunggu sampai milidetik timestamp berikutnya = tailnextmillis (lasttimestamp);}} else {// jika urutannya berbeda dari generasi terakhir, reset ulang urutan, mana yang dimulai. // Untuk memastikan keacakan yang lebih besar dari mantissa, atur nomor acak dalam urutan bit terakhir = SecureRandom baru (). NextInt (10);} LastTimestamp = timestamp; return ((timestamp - twepoch) << timestampleftshift) | (Paddingnum << RegionalIdshift) | (WorkerId << WorkeridShift) | Urutan;} // mencegah waktu pembangkitan lebih kecil dari waktu sebelumnya (karena masalah seperti ntp callback), dan mempertahankan tren tambahan. Tailnextmillis long long (final lastTimestamp) {timestamp long -this.time (while ()} longsampamp lastTampamp) {timestamp = this.timeGen (); while (timestamp <= lastTampamp) {timestamp long -long (); wala timeGen () {return system.currentTimeMillis ();}}Beberapa hal yang perlu diperhatikan saat menggunakan metode khusus:
Untuk mempertahankan tren pertumbuhan, perlu untuk menghindari waktu beberapa server lebih awal dan beberapa server terlambat, sehingga waktu semua server perlu dikendalikan, dan waktu ketika server waktu NTP menelepon kembali ke server dihindari; Saat melintasi milidetik, nomor seri selalu mencapai 0, yang akan membuat lebih banyak ID dengan nomor seri 0, menghasilkan ID yang tidak merata setelah modulo, sehingga nomor seri bukan milik 0 setiap kali, tetapi angka acak dari 0 hingga 9.
Kita dapat memilih metode yang disebutkan di atas sesuai dengan kebutuhan kita. Dalam pengembangan server game, Anda dapat memilih sesuai dengan jenis permainan Anda sendiri, seperti game seluler, dan Anda dapat menggunakan metode Redis sederhana, yang sederhana dan tidak mudah untuk membuat kesalahan. Karena jumlah ID baru yang dibuat oleh server tunggal dalam permainan semacam ini tidak terlalu besar, ia sepenuhnya dapat memenuhi kebutuhan. Untuk server permainan dunia besar, mereka terutama didistribusikan, sehingga Anda dapat menggunakan kepingan salju. Kode Snowflake di atas hanyalah sebuah contoh dan perlu disesuaikan sesuai dengan kebutuhan Anda, jadi ada volume pengembangan tambahan, dan Anda harus memperhatikan tindakan pencegahan di atas.
Di atas adalah ringkasan metode menggunakan kode Java untuk mengimplementasikan server game untuk menghasilkan ID unik global berdasarkan kode Java. Saya harap ini akan membantu semua orang. Jika Anda memiliki pertanyaan, silakan tinggalkan saya pesan dan editor akan membalas semua orang tepat waktu. Terima kasih banyak atas dukungan Anda ke situs web Wulin.com!