Apakah ada cara untuk membuat dunia yang dinamis seperti MMORPG dapat diskalakan secara horizontal?

11

Bayangkan dunia terbuka dengan 500+ pemain dengan data berubah secepat 20 pembaruan / pemain / detik. Terakhir kali saya bekerja di MMORPG yang serupa, menggunakan SQL, jadi obvioulsy tidak bisa meminta DB sepanjang waktu. Sebagai gantinya, itu memuat semua pemain dari DB ke memori sebagai objek C ++ dan menggunakannya. Artinya, diskalakan secara vertikal. Apakah mungkin untuk membuat server yang skalabel secara horizontal? Apakah ada database yang dirancang untuk mendukung jumlah pembaruan itu secara bersamaan?

Viktor Maia
sumber
Mengapa Anda ingin memperbarui pemain di basis data 20 kali / detik?
Balon
@Balon di situlah aku bingung. Jika saya tidak memperbaruinya dalam database, hanya dalam memori, maka saya akan memiliki status yang berbeda di antara mesin yang berbeda. Tapi saya kira pembaruan DB memiliki beberapa overhead besar sehingga tidak benar-benar akan berfungsi untuk jumlah pembaruan itu?
MaiaVictor
2
Jika Anda benar-benar berpikir bahwa mesin yang berbeda (atau bahkan proses) memerlukan pembaruan 20Hz pada ratusan objek maka sepenuhnya memotong database dan menggunakan sistem pesan secara langsung. Tetapi apa yang Anda benar-benar pikirkan benar-benar Anda inginkan bukanlah yang Anda inginkan. Yang Anda inginkan adalah memiliki ruang lingkup yang waras tentang siapa yang perlu tahu apa dan kemudian memiliki cara untuk mengangkut benda-benda di antara ruang lingkup dengan rapi. Anda harus menjawab pertanyaan mengapa Anda membutuhkan pembaruan 20Hz antara mesin yang berbeda untuk jawaban yang bagus, seseorang mungkin memikirkan cara baru untuk melihat masalahnya.
Patrick Hughes
@ PatrickHughes Saya tidak tahu apa yang saya butuhkan, saya hanya menjelaskan cara kerjanya. Karakter bergerak 2 ~ 3 ubin / detik. Perburuan pemain mungkin dikelilingi oleh beberapa monster, jadi setidaknya 10 ubin / pemain / detik. Lalu ada barang-barang yang membusuk di lantai, di ransel pemain. Ada serangan yang bergerak ke arah pemain, ada serangan yang bergerak ke arah monster. Ada pembusukan kesehatan, mana yang digunakan, timer menerapkan kerusakan racun pada pemain. Jadi, segalanya berubah sangat cepat. Ini adalah desain game. Bagaimana desain tersebut dapat diskalakan secara vertikal?
MaiaVictor
1
Saya melihat ini di HackerNews beberapa waktu lalu: paralleluniverse.co Mereka sedang mengerjakan database yang melakukan semua segmentasi spasial / distribusi barang untuk Anda. Saya kira di bawah tenda, mereka melakukan semua hal dalam jawaban di bawah ini.
kapal tunda

Jawaban:

17

Test case dari 500 pemain yang berkomunikasi, itu adalah 250K aliran informasi terbang sekitar pada 20Hz. Bandwidth internal untuk itu adalah, dengan asumsi 100 byte setiap pesan, sekitar 500MB / detik. Kedengarannya ambisius. Terutama antar proses.

Jika Anda memisahkan pemain menjadi 100, itu menurunkan menjadi 20 MB / detik, dan seterusnya. Itulah sebabnya MMO memiliki zona, dan di zona itu gelembung kecil pengaruhnya, dan seterusnya ke bawah hingga bandwidth menjadi masuk akal.

Masalah aslinya dapat dinyatakan bahwa jika Anda memiliki 10 orang yang semuanya berbagi informasi waktu nyata, tetapi Anda ingin 500 orang berbagi , itu merupakan pertumbuhan yang eksponensial dari tautan komunikasi dan bagaimana kita dapat mengatasinya . Saya khawatir tidak ada peluru ajaib yang pernah saya dengar yang secara ajaib dapat membuat kemajuan geometris hilang.

Jangan gunakan basis data untuk berkomunikasi, itu gunanya pesan. Gunakan database untuk memberlakukan transaksi dan menyimpan info yang Anda tidak ingin kehilangan pemain. Kebanyakan MMO yang saya kenal hanya memperbarui basis data dengan info pemain dinamis setiap 1-10 menit, atau pada titik berguna seperti transisi zona atau memasuki zona "aman" dalam desain.

Anda mungkin harus mendesain ulang permainan kebutuhan untuk setiap pemain, tidak peduli seberapa jauh, untuk memiliki update realtime isi ransel setiap pemain lain.

Juga mengubah pola pembaruan dari 20Hz ke kecepatan berdasarkan jarak, seseorang 1 mil jauhnya tidak perlu tahu bahwa Anda bergerak 1 kaki tepat 230,6 detik, kemudian kaki lain pada 231,4 detik, mereka dapat menangani Anda bergerak 15 kaki setiap 10 detik.

Patrick Hughes
sumber
Jawaban yang mengagumkan dan informatif, terima kasih. Tetapi saya dapat menambahkan bahwa sementara dunia berubah dengan sangat cepat, seorang pemain hanya dapat melihat pemain lain tepat di sebelahnya. Saya tidak melihatnya sebagai geometris - 500 pemain mengirim info ke server; server secara berkala mengirimkan info kepada 500 pemain itu. Itu linear, seperti yang saya lihat. Tetapi poin utamanya adalah pada paragraf ke-4: jika saya hanya menggunakan database untuk penyimpanan, maka saya memuat data ke memori. Jika saya memuat data ke memori di mesin, saya membuat versi dunia yang tidak sinkron. Itu yang tidak saya dapatkan.
MaiaVictor
Untuk 1 klien: 1 pesan keluar + 1 pesan di = 2. Untuk 2 klien: 2 pesan keluar, 2 pesan masuk = 4. Untuk 3 klien: 3 pesan keluar, 3 pesan di = 9. Dan begitulah seterusnya. Seperti ini: kirim pesan status, server mengirimkan hasil kepada saya dan 2 klien lainnya (1 masuk, 3 keluar) dan 3 klien semua melakukan itu (1 dalam 9 keluar). Meskipun terlihat linier hanya untuk satu klien dari 3, Anda bisa mengalikannya dengan semua klien untuk total throughput sistem. Adapun desync, bahkan proses pada kotak fisik yang sama tidak sinkron sampai pesan status dibuat dan dikirim, itu hanya masalah di mana pipa kosong, RAM lokal atau bersih.
Patrick Hughes
5

Gunakan pemfilteran area yang menarik. Jika dunia dipecah menjadi 3 server, dan area pada server 1 tidak berada di dekat area server 3, tidak ada alasan bagi mereka untuk berbagi informasi tentang entitas sama sekali.

Demikian juga, pada satu server, hanya mengirim informasi yang relevan kepada klien. Jika pemain A berada di ujung peta yang sepenuhnya berlawanan dari pemain B, tidak ada alasan untuk mengirim pembaruan tentang B ke A, atau sebaliknya.

Ketika Anda memiliki beberapa server di dunia berkelanjutan, Anda akan memiliki entitas di dekat tepi pada server 2 yang dekat dengan entitas di server 1. Anda dapat mengirim pembaruan dari server "otoritatif" untuk entitas ke server lain (bila perlu) , dan juga meneruskan pesan apa pun ke server yang berwenang sebagaimana mestinya.

Ya, dalam hal ini, satu server akan sedikit kedaluwarsa untuk entitas tertentu. Jangan mencoba menyelesaikannya. Atasi saja. Asumsikan bahwa entitas mungkin sedikit ketinggalan zaman. Lakukan logika apa pun yang memerlukan informasi terkini hanya di server yang memiliki entitas secara otoritatif. Ketika suatu entitas memengaruhi entitas lain, kirim pesan dan anggaplah dibutuhkan beberapa kutu logika game sebelum diproses dan tampilan Anda diperbarui.

Desain ini juga memudahkan untuk memasang satu server. Tidak ada entitas yang harus langsung memodifikasi entitas lain, hanya mengirim pesan, dan cache proxy per-server / per-thread lokal harus dianggap sedikit kedaluwarsa.

Misalnya, jika entitas A menyerang entitas B, jangan periksa umur B dan kemudian mengirim pesan kematian jika menyentuh 0. Cukup kirim pesan "rusak", biarkan server otoritatif untuk B menanganinya, dan kemudian menangani Pesan "entitas-died" dikirim oleh server B nanti jika entitas A peduli tentang itu.

Hal yang sama berlaku untuk aplikasi non-game yang besar dan dapat diskalakan. Basis data pusat bukanlah teknologi berbagi instan yang ajaib. Dua server harus berkomunikasi dengan pesan, secara asinkron, dalam batch, untuk mempertahankan throughput yang tinggi. Karenanya popularitas teknologi seperti AMPQ dan sejenisnya. Basis data untuk penyimpanan dan mendukung sinkronisasi karena diperlukan sehingga dapat digunakan untuk komunikasi, bukan karena itu sendiri dimaksudkan untuk sinkronisasi atau komunikasi.

Sean Middleditch
sumber
Terima kasih, ini mengakhiri sebagian besar keraguan saya yang tersisa. Anda juga memberi saya ide untuk memisahkan server oleh pemain, bukan area - ini akan terlihat lebih halus. Setiap server menangani x pemain. Saya sangat menyukai ini! Apakah ini digunakan? Dan juga, ada satu hal lagi. Seperti yang saya tanyakan di atas, saya baru saja belajar tentang basis data NoSQL baru, Couchbase. Seharusnya sama seperti CouchDB, kecuali dengan kecepatan tulis / baca yang sangat cepat: hingga 200 ribu pembaruan per detik! Mungkin ini bisa benar-benar berfungsi sebagai "model dunia bersama waktu-nyata", atau belum?
MaiaVictor
Saya tidak tahu apakah teknik itu digunakan di alam liar selain server "kasar" biasa. Hanya melakukannya oleh pemain dan area geografis berarti setiap server mungkin perlu menyadari sejumlah besar entitas di berbagai bidang, meningkatkan beban server dan sangat meningkatkan komunikasi antar server. Melakukannya berdasarkan area berarti server Anda mungkin kelebihan beban di area yang penuh sesak (meskipun Anda dapat secara dinamis memecah dan bergabung dengan area dalam kasus itu), tetapi berarti bahwa setiap server memiliki kumpulan entitas non-pemain yang relevan dan geometri yang lebih kecil untuk melacak .
Sean Middleditch
@Dokkat: Dimungkinkan untuk memiliki semacam "area lunak" di mana Anda memiliki setiap server yang terutama menangani pemain di bagian tertentu dari dunia game, tetapi minta mereka secara transparan menyerahkan pemain ke server lain jika mereka menyimpang terlalu jauh dari wilayah server asli mereka. Anda hanya perlu memastikan bahwa penyerahannya cukup lancar sehingga pemain tidak benar-benar menyadarinya. Anda bahkan dapat mencoba menggunakan beberapa teknik adaptif yang bagus untuk menjaga kelompok pemain yang berinteraksi di server yang sama, bahkan jika mereka hanya berada pada batas wilayah.
Ilmari Karonen
3

Anda mungkin akan tertarik dengan artikel ini di Gamasutra , di mana pengembang Eve Online membahas bagaimana mungkin untuk berhasil menjalankan permainan dengan 400.000 pemain aktif ... dalam satu basis data SQL.

Liosan
sumber
2

Jangan menganggap database sebagai semacam model dunia bersama waktu nyata yang menyimpan segala sesuatu tentang segala hal setiap saat - seperti yang Anda perhatikan, itu tidak mungkin berhasil.

Alih-alih, perlakukan database lebih seperti file penyimpanan yang diperbarui secara otomatis: Anda memperbarui database hanya sesekali, seperti ketika pemain masuk atau keluar atau berpindah dari satu zona ke zona lain, atau setiap kali terjadi sesuatu yang penting yang tidak Anda inginkan. hilang jika terjadi crash server.

Status dunia waktu nyata yang sebenarnya harus dipegang oleh server permainan, dalam memori, seperti dalam contoh asli Anda. Sekarang, trik untuk penskalaan horizontal adalah tidak semua server perlu mengetahui segalanya setiap saat . Misalnya, jika pemain A bermain di zona A di server A, server B berjalan zona B biasanya tidak perlu tahu apa yang pemain A memiliki dalam ransel mereka - dan, jika tidak perlu tahu bahwa untuk beberapa alasan (misalnya, karena pemain B di zona B melemparkan semacam mantra mata-mata jarak jauh pada A) ia hanya dapat meminta informasi dari server lain .

Ini mengharuskan Anda untuk menetapkan tanggung jawab yang jelas ke server, sehingga ketika server B ingin tahu tentang ransel pemain A, ia akan tahu server mana yang memiliki informasi resmi tentang itu. Anda juga mungkin ingin menyertakan semacam mekanisme pembaruan berlangganan, sehingga misalnya server B dapat memberi tahu server A " Saya memiliki seseorang yang memata-matai pemain A, terus perbarui semua yang mereka lakukan sampai saya katakan sebaliknya. " Anda mungkin akan juga ingin memasukkan semacam sistem siaran global untuk acara global penting yang mungkin perlu diketahui pemain di mana pun mereka berada; tentu saja, kejadian seperti itu juga harus direkam dalam database, tetapi jika mereka disiarkan secara aktif ke semua server berarti bahwa server tidak harus terus polling database untuk pembaruan.

Ilmari Karonen
sumber
Jawaban yang luar biasa! Inilah tepatnya yang saya minta, terima kasih. Jadi mungkin kuncinya adalah untuk membagi server di area, menjaga logika di memori. Mungkin saya tambahkan: Saya baru saja belajar tentang database NoSQL baru, Couchbase. Seharusnya sama seperti CouchDB, kecuali dengan kecepatan tulis / baca yang sangat cepat: hingga 200 ribu pembaruan per detik! Mungkin ini bisa benar-benar berfungsi sebagai "model dunia bersama waktu-nyata", atau belum?
MaiaVictor
@Dokkat tidak, tidak akan. Couchbase bukanlah sihir.
Philipp
2

Respons lain telah melakukan pekerjaan yang baik untuk menunjukkan bagaimana menggunakan database, dan tidak menggunakan database untuk komunikasi. Satu aspek lain yang mungkin Anda perhatikan adalah mengategorikan pembaruan Anda berdasarkan bagaimana informasi tersebut perlu dikomunikasikan ke entitas lain. Daripada lingkup komunikasi ke server, Anda bisa mendistribusikan pesan Anda dan menggunakan mekanisme pubsub untuk mengkomunikasikan pembaruan antar entitas. Misalnya, Anda mungkin memperlakukan lokasi secara berbeda berdasarkan siapa yang dekat dengan Anda:

  • Lokasi yang tepat dan real-time mungkin berguna dalam radius R
  • Pembaruan lokasi yang kurang tepat dan kurang sering mungkin berguna dalam radius 2 * R
  • Tidak ada informasi lokasi yang diperlukan di luar radius 2 * R

Anda dapat mengkomunikasikan informasi lokasi untuk suatu entitas dengan memindai secara berkala entitas dalam radius 2 * R (atau beberapa kelipatan yang didasarkan pada tingkat pembaruan dan kecepatan maksimum suatu entitas), dan berlangganan entitas ke feed lokasi yang tepat atau tidak tepat dari entitas lain.

Anda dapat memiliki strategi berbeda untuk berbagai jenis informasi, kelompokkan hal-hal umum ke dalam antrian pesan yang sama, atau memiliki antrian yang berbeda untuk pesan yang perlu pergi ke entitas yang berbeda (atau hanya mengirim mereka ke entitas yang paling luas dan memiliki pesan yang dibuang jika mereka tidak berguna).

David N.
sumber