Bagaimana mmorpg menyimpan data?

22

Saya ingin menggunakan database sql di server.exe saya.

katakanlah 1000 pengguna online. Dan pemain akan mengubah data mereka saat mereka bermain. Dan server harus menyimpan pembaruan ini.

Tapi bagaimana caranya ?

saya pikir ada dua cara:

1) server akan menyimpan ram pada saat dijalankan dan kadang-kadang atau jam server akan menulis data (pembaruan) ke database sql dari ram. Tetapi jika listrik padam atau entah bagaimana server dimatikan, pembaruan tidak akan menghemat. tentu saja saya tidak ingin kehilangan pembaruan.

2) server akan menyimpan pembaruan dalam database pada saat run time. tetapi apa yang akan terjadi pada kecepatan? Saya memikirkan sebuah metode. saya akan menunjukkan kepada Anda di bawah ini dengan gambar. Bisakah saya mendapatkan kecepatan yang cukup untuk 1000 pemain online dengan metode ini? masukkan deskripsi gambar di sini

Emre Kaya
sumber
11
Sudahkah Anda melakukan tolok ukur? Apa yang membuat Anda berpikir operasi basis data akan menjadi masalah bagi gim Anda?
congusbongus
3
Jika kondisi permainan Anda benar-benar berhubungan? Anda yakin ingin database SQL?
Stop Harming Monica
6
Baca juga cara menangani kata sandi menggunakan hash. Atau setidaknya beri tahu pengguna bahwa kata sandi mereka disimpan sebagai teks biasa, sehingga mereka sadar untuk tidak menggunakan kata sandi aman lain.
TomTsagk
24
Sebagai catatan tambahan, jika Anda ingin membangun MMO komersial dan Anda mengajukan pertanyaan seperti ini, Anda mungkin harus memulai dengan sesuatu yang lebih kecil. MMO sangat sulit dilakukan, apalagi melakukannya dengan benar, dan mereka tidak terlalu bagus dari sudut pandang bisnis. Jika ini hanya masalah pribadi dan Anda ingin menghitung jumlah pemain yang tinggi, mulailah dengan sesuatu seperti 64 pemain, kemudian naiklah. Ini akan jauh lebih mudah daripada mencoba merancang arsitektur "sempurna" dari awal tanpa pengalaman. Lihat ini .
Dana Gugatan Monica
1
Anda dapat menulis API umum yang agnostik penyimpanan. Kemudian tulis sebuah adaptor yang menyimpan data dalam RAM untuk penyimpanan yang tertunda. Atau Anda dapat menulis adaptor yang menyimpan data dalam file sementara sebelum membersihkannya di SQL DB. Dengan begitu Anda bisa menghidupkan dan mematikan caching untuk mencari tahu mana yang terbaik. Anda tidak perlu menulis terlalu banyak kode tambahan, Jika arsitektur Anda dibangun dengan benar.
0xC0DEGURU

Jawaban:

37

Sebagian besar MMO (atau proyek yang menggunakan arsitektur serupa) Saya telah bekerja pada atau tahu menggunakan metode pertama: server game bekerja terutama dengan RAM pada mesin yang menjalankan proses server, dan hanya secara berkala membuat serial data game yang relevan ke database SQL untuk arsip (jika digunakan sama sekali).

Masalah yang Anda catat tentang kegagalan daya adalah valid, tetapi lebih kecil kemungkinannya dibandingkan masalah seperti gangguan dalam proses (keandalan uptime umumnya merupakan salah satu hal yang Anda bayar untuk pusat data). Tetapi tetap saja. Anda memitigasi masalah-masalah tersebut melalui hal-hal seperti menyetel interval penyimpanan (jadi kegagalan hanya menghabiskan biaya paling banyak beberapa menit untuk kemajuan), mendistribusikan antrian penyimpanan di beberapa mesin, secara agresif membatasi jumlah data yang perlu disimpan, dan menerapkan penyimpanan yang dapat dimulai kembali antrian.

Secara umum, menggunakan SQL server itu sendiri sebagai memori utama akan lambat lambat (dan rumit). Saya tidak melihat cukup detail dalam proposal Anda di sana untuk dapat mengatakan dengan pasti apakah itu hanya akan bekerja untuk sekitar 1000 pemain - mungkin akan baik-baik saja. Tapi saya tidak percaya Anda bisa membuatnya bisa diukur secara agresif.

Selanjutnya, itu tidak menyelesaikan masalah. Kegagalan daya selama proses penyimpanan masih akan kehilangan atau merusak data kecuali jika Anda melakukan pekerjaan untuk menerapkan jenis antrian yang dapat dimulai kembali yang sama (yang bahkan kemudian, yang hanya sangat mengurangi kemungkinan hilangnya data bencana, itu tidak mencegahnya) .

Saya sarankan Anda pergi dengan pendekatan pertama.


sumber
10
Mengenai "tuning interval save", MMO terakhir yang saya kerjakan memiliki interval save berdasarkan jumlah pemain aktif. Kami tahu itu bisa menangani menyimpan data pemain X per detik tanpa hambatan yang nyata, jadi kami hanya menyimpannya sedikit di bawah pemain X per detik secara bergiliran. Biasanya berakhir sebagai save untuk setiap pemain setiap dua menit atau lebih pada hari-hari sibuk, dan mungkin dua kali menit selama masa-masa lambat.
Meanbits
4
"Restartable save queue" terdengar seperti jurnal, seperti yang diterapkan oleh banyak sistem file dan mesin basis data?
grawity
6
Masalah-masalah ini tidak unik untuk MMO, atau bahkan video game, sama sekali . Hampir setiap ORM yang ada menyediakan semacam mekanisme caching / batching. Tidak perlu menggulung solusi Anda sendiri.
BlueRaja - Danny Pflughoeft
3
Jika Anda akhirnya pergi dengan menyimpan ke disk pada interval tertentu, saya akan merekomendasikan merancang sistem di mana hal-hal dapat segera disimpan, karena ketika orang mendapatkan drop / die / etc langka. Dengan begitu, jika ada server crash atau semacamnya, orang yang melakukan sesuatu yang besar tidak akan terlalu kesal.
Jon
5
@ Jon, dan kemudian Anda mengalami masalah dengan orang yang dapat menduplikasi objek. Idealnya, Anda menyimpan seluruh kondisi game secara berkala sebagai satu transaksi. Setelah Anda mulai menabung sedikit demi sedikit, Anda berakhir dengan situasi di mana kerusakan dapat menyebabkan data tidak konsisten; pemain yang dapat memicu crash pada permintaan, atau bahkan memprediksi kapan crash mungkin terjadi, dapat memanfaatkan ini untuk keuntungan mereka.
Tandai
15

1000 pemain mungkin atau mungkin tidak menjadi masalah. Itu tergantung pada seberapa sering Anda perlu memperbarui database. Namun ada solusi sederhana: letakkan database di server sendiri.


Saya telah mengintip bagaimana sistem basis data bekerja dalam sebuah permainan yang oleh orang-orang akan memanggil MMO-Lite - yang mana saya tidak akan ungkapkan - namun saya dapat mengatakannya secara konsisten memiliki lebih dari 1000 pemain, ini abstrak:

  • Mereka menggunakan database "No-SQL" berbasis dokumen untuk informasi karakter pribadi (inventaris, peralatan, serupa).
  • Mereka menggunakan database relasional yang lebih tradisional untuk informasi karakter publik yang jarang diperbarui (nama, prestasi, dll ...) dan statistik.

Menggunakan database berbasis dokumen ternyata menjadi ide yang baik untuk kinerja dalam hal ini. Itu baik untuk mengakses data, meskipun buruk untuk melakukan penggabungan dan agregasi ... tetapi mereka tidak akan melakukannya dengan data yang ada di sana.

Di sisi lain, ketika mereka perlu melakukan sesuatu seperti mengubah objek dengan objek lain untuk semua orang, kebutuhan untuk menjalankan skrip latar belakang yang berjalan karakter demi karakter dan memperbaruinya satu per satu, dibutuhkan waktu yang nyata.


Data karakter ada di klien dan di server, dan sistem dirancang agar tetap sinkron, melakukan operasi yang sama di kedua sisi.

Sekarang, ketika seorang pemain melakukan transaksi dengan sistem - katakan bertukar item dengan yang lain melalui NPC atau serupa - ini memiliki tahapan berikut:

  • Klien memeriksa apakah operasi itu valid
  • Klien mengirim operasi ke server (operasi async)
  • Klien memperbarui modelnya dalam RAM
  • Server memeriksa apakah operasi itu valid
  • Server memperbarui modelnya dalam RAM
  • Server memperbarui basis data (operasi async)
  • Server memberi tahu klien bahwa perubahan terjadi

Catatan :

  • Pembaruan basis data, meskipun async, dilakukan segera. Jika karena alasan apa pun server game turun, tidak banyak yang hilang.
  • Degradasi kinerja bukan masalah besar karena menempatkan database di server mereka sendiri.

Perdagangan antar pemain ditangani dengan cara yang sama, dengan aturan tambahan untuk mencegah pemain menipu pemain lain, dan keterlacakan tambahan jika terjadi transaksi yang harus dibatalkan. Saya mendengar ada log khusus dari semua transaksi yang disimpan selama beberapa waktu (untuk menyelesaikan masalah ketika seseorang mengeluh), saya tidak tahu lebih banyak tentang cara kerja bagian itu.


Terkadang ada yang tidak beres, ini memiliki dua kemungkinan hasil:

  • Jika kesalahan terjadi segera, server akan memberi tahu klien, yang akan mengembalikan operasi (pemain melihat operasi dibatalkan).
  • UI mengatakan pemain memiliki item, tetapi server tidak setuju. Jika pengguna mencoba menggunakannya, itu akan meminta server dan gagal, membuat objek palsu tidak dapat digunakan. Objek palsu hilang ketika inventaris dimuat ulang, yang digunakan sebagai kesempatan untuk menyinkronkan model.

Dalam kedua kasus, klien menyadari kesalahan, dan akan mencatatnya bersama dengan semua yang dilakukan pemain. Sisi klien sedang terjadi setiap saat. Kemudian, saat logout, jika ada kesalahan, klien mengirim log ke server.


Game ini tidak menggunakan waktu pemeliharaan harian atau mingguan tradisional yang dimiliki sebagian besar MMORPG. Pemeliharaan terjadwal sering digunakan untuk mengatur ulang penghitung, penghitung waktu, menjalankan prosedur basis data. Mereka juga merupakan kesempatan untuk menukar versi server dengan pembaruan.

Theraot
sumber
Terima kasih, tetapi bagaimana dengan pergerakan pemain misalnya, jika seorang pemain bergerak dari posisinya saat ini: x:10,y:10,z:10Kepada x:11,y:11,z:11, haruskah ini segera disimpan dalam database? bagaimana jika pemain terus berlari, ini berarti kami menyimpan posisinya saat ini setiap 1 detik atau kurang, dan jika ada ribuan pemain, itu jutaan pertanyaan ke DB setiap detik. Apakah ini cara kerjanya?
dwix
2
Posisi pemain harus disimpan sangat jarang dalam database. Anda hanya ingin itu pada kesempatan khusus seperti membuka menu, memulai api unggun, istirahat dll. Tergantung pada gim itu bahkan tidak akan disimpan secara terperinci. Beberapa permainan membuat Anda selalu muncul di kota terdekat dll, sehingga akan menghemat kerumitan menyimpan posisi juga. Tapi itu melayang ke berbasis opini.
Nico
1
@dwix dalam kasus permainan yang saya bicarakan, posisi pemain bahkan tidak disimpan. Jika Anda keluar dan masuk, atau jika server turun, pemain akan ditempatkan kembali pada posisi yang diketahui aman (sunting: ini adalah contoh pribadi, "rumah" jika Anda mau, tetapi itu sama untuk semua orang). Namun, beberapa permainan tetap mempertahankan posisi pemain yang tepat, bahkan saat terputus secara tidak disengaja. Untuk melakukannya, pendekatan yang umum adalah menyimpan informasi itu lebih jarang. Apapun, Anda tidak menunggu server apa pada database.
Theraot
1
@dwix ketika berbicara tentang posisi avatar, Anda tidak terlalu peduli dengan nilai historis, bukan? Nah, jika databasenya adalah bottle neck, maka throttle datanya. Alih-alih menyimpan setiap centang server, simpan lebih jarang. Ini berarti bahwa basis data tidak akan memiliki nilai paling mutakhir, tetapi itu tidak akan berdampak besar pada kinerja. Sementara itu server akan tetap menyimpan nilai pembaruan dalam RAM, dan itulah yang bekerja dengannya. Tambahan: jujur ​​saya akan menyarankan agar tidak menyimpan posisi, tetapi beberapa permainan melakukannya.
Theraot
1
@dwix, lihat komentar meanbits
Theraot
7

Kedua pendekatan tersebut digunakan dengan MMORPG. Menyimpan semuanya dalam memori dan secara berkala memeriksa dan mengarahkannya ke disk tampaknya menjadi pilihan yang paling populer, setidaknya untuk gim yang lebih lama. Ini memiliki keuntungan menjadi cukup sederhana untuk diimplementasikan dan scaling cukup baik, tetapi membuatnya dapat diandalkan sepenuhnya terserah pengembang. Database SQL menyediakan properti ACID yang membuat keandalan lebih mudah, tetapi secara keseluruhan lebih rumit untuk diimplementasikan dengan baik dan dapat memiliki masalah dengan penskalaan.

EVE Online adalah contoh MMO di mana semuanya disimpan dalam database SQL. Saya pikir itu memuncak pada sekitar 60.000 pengguna simultan, dan harus mendedikasikan beberapa perangkat keras yang mahal untuk server database selama bertahun-tahun agar tetap mengikuti beban. Namun EVE menyimpan lebih banyak data per pengguna daripada kebanyakan MMORPG dan memiliki transaksi yang lebih sering dan bervariasi. Properti ACID di database memungkinkan seluruh database yang masif dan rumit untuk selalu disimpan dalam kondisi yang konsisten.

Misalnya, pertimbangkan kasing ketika seseorang memberikan item kepada pemain lain. Basis data EVE menjamin bahwa bahkan jika terjadi kerusakan atau kegagalan daya, item tersebut berakhir hanya dalam inventaris satu pemain. Yaitu, transaksi basis data yang menghapus item dari inventaris satu pemain dan menambahkannya ke pemain lain adalah atom. Transaksi selesai atau tidak terjadi sama sekali. Anda tidak dapat berakhir dalam keadaan apakah item tersebut ada dalam inventaris pemain atau keduanya.

MMORPG yang menyimpan data pemain dalam memori dan secara berkala pos-pos pemeriksaannya harus menerapkan atomicity ini sendiri. Salah satu cara untuk melakukan ini adalah pos pemeriksaan data setiap pemain pada saat yang sama, memastikan bahwa pos pemeriksaan baru berkomitmen penuh ke disk sebelum dianggap sebagai pos pemeriksaan terbaru. Gim ini juga harus memastikan bahwa data pemain tidak dapat berubah saat sedang diperiksa. Dengan sejumlah besar pemain aktif, tantangan menjadi melakukan semua ini tanpa menyebabkan penundaan yang cukup lama sehingga para pemain akan perhatikan.

Jangan meremehkan betapa pentingnya konsistensi. Saat Anda mengembangkan game, game ini akan sering crash. Anda tidak ingin melacak mengapa item menghilang dan / atau menggandakan, bukan ketika masalahnya adalah bug yang tidak terkait menyebabkan game mogok pada waktu yang buruk. Terlebih lagi ketika game Anda ditayangkan, itu akan crash jauh lebih dari yang Anda harapkan. Server Anda yang beroperasi dengan sempurna dalam pengujian, tiba-tiba akan memunculkan banyak bug di bawah muatan penuh dan pemain melakukan hal-hal yang tidak Anda harapkan.

Perhatikan bahwa sebagian besar MMORPG menggunakan database SQL untuk informasi terkait akun bahkan jika mereka tidak untuk data game sebenarnya. Yang lebih penting daripada mempertahankan status permainan dalam kondisi konsisten adalah menjaga status tagihan konsisten. Kasus terburuk untuk database game yang korup adalah Anda harus memulihkan database dari cadangan harian. Kasus terburuk untuk database akun yang korup adalah Anda bangkrut karena semua tolak bayar.

Untuk proyek Anda, Anda mungkin bisa menuju ke sana. Memiliki 1000 pengguna simultan mungkin tidak akan memaksakan batasan apa yang dapat ditangani oleh server SQL pada PC komoditas saat ini, tetapi banyak yang akan bergantung pada sifat transaksi. Jika Anda terbiasa dengan SQL dan desain basis data relasional, ini dapat bekerja untuk Anda. Anda akan ingin meminimalkan transaksi sebanyak mungkin, untuk sesuatu seperti hitpoint pemain saat ini Anda mungkin hanya ingin menyimpannya secara berkala ke database karena statistik seperti ini tidak perlu konsisten. (Dalam game PvP mereka mungkin ...) Jangan menyimpan hal-hal seperti monster HP dalam database sama sekali, di sebagian besar game hanya data yang terkait dengan pemain yang persisten.

Di sisi lain, jika Anda bukan penyihir SQL, Anda mungkin menemukan menyimpan semua data di memori jauh lebih mudah untuk bekerja dengan andal. Database SQL membuat konsistensi dan keandalan lebih mudah, tetapi tidak otomatis. Basis data yang dirancang dengan buruk dapat berkinerja buruk dan menyebabkan inkonsistensi. Transaksi tidak akan menjadi atom kecuali Anda membuatnya demikian. Jika Anda tidak menggunakan pernyataan parameterisasi secara religius, Anda akan membuka diri terhadap serangan injeksi SQL.

Ross Ridge
sumber
0

Berbagai permainan menyimpan berbagai hal dengan cara berbeda. Seringkali, perusahaan game membuat beberapa cara untuk melakukan ini, dan sebagian besar game mereka menggunakan cara yang sama. Tentu saja, berbagai studio sering menggunakan cara yang berbeda. SQL tentu digunakan untuk gim, misalnya CCP (EVE) memiliki (atau setidaknya memiliki) jaringan server SQL, saya tidak yakin bagaimana mereka melakukannya sekarang. Lainnya, cukup gunakan banyak file.

Mungkin mulai dengan menciptakan "mekanisme perantara data" agnostik, untuk menangani berbagai transaksi data permainan? Karena Anda hanya menguji apa pun, buat mekanisme yang memungkinkan Anda untuk tidak perlu terlalu peduli tentang penyimpanan, dari sudut pandang permainan itu sendiri. Artinya, berkonsentrasilah pada bagaimana, dari aplikasi host, Anda akan menangani ini.

Secara pribadi saya pikir itu akan menjadi aset yang hebat jika Anda bisa mengganti toko yang sebenarnya, tanpa harus menulis ulang permainan dan broker itu sendiri. Alihkan saja ke modul lain dengan antarmuka yang sama untuk diajak bicara oleh broker.

Menyimpan data itu sendiri kemungkinan tidak akan menjadi masalah. Pengiriman data yang efisien, ke / dari toko itu, antara tuan rumah dan semua klien, bisa lebih rumit. Apakah saya mengirimkan seluruh kumpulan data pemain, atau jika saya memecahnya menjadi beberapa bagian, granularitas apa yang saya pilih untuk dipartisi, dll. Yang mana yang lebih intensif sumber daya dalam situasi apa, dll.

Satu format untuk pengiriman data, bisa berupa XML. Dengan begitu Anda bisa lebih mudah menjadi dinamis dalam hal bagaimana Anda bisa memotongnya. Satu karakter vs banyak karakter, atau satu item vs koleksi item, dll. Anda kemudian dapat "menyimpan" XML sebagai XML (dalam SQL), dan / atau meminta SQL mendistribusikannya dengan cara yang lebih transaksional dari XML, ke bagaimana Anda ingin data sebenarnya disimpan.

Cara lain adalah biner, yang lebih efisien dalam hal pengiriman, tetapi dapat menimbulkan lebih banyak biaya dalam situasi lain.

Dengan 1.000 klien, Anda dapat memulainya, dan dengan mudah menyimpan 10 MB per klien dan hanya menggunakan 10 GB RAM efektif + menambahkan beberapa RAM administratif sistem untuk mengelola data itu, katakan satu atau dua GB lagi. Anda bisa menyimpannya di RAM pada host yang sudah dalam struktur data siap digunakan. Dan memuat / menyimpan secara dinamis, tergantung pada siapa yang online, dalam berbagai frekuensi tergantung pada aktivitas, dll.

Anda bahkan dapat menyimpan informasi masing-masing klien dalam file terpisah, dan sebagainya.

rampok
sumber
0

Simpan pemain * online * di ram, dan dorong mereka ke database (SQLite? MySQL?) Ketika mereka logout. jika Anda khawatir tentang IO yang berhenti selama logout, berikan setiap logout itu utas sendiri, jangan lakukan itu di utas utama / permainan (sebenarnya saya menyimpan utas pemain khusus untuk setiap pemain online, itu membuat kode jaringan jadi lebih mudah daripada melakukan pendekatan jaringan async io)

hanshenrik
sumber