Mmorpg veriyi nasıl saklar?


22

Benim server.exe sql veritabanı kullanmak istiyorum.

1000 kullanıcı çevrimiçi diyelim. Oyuncular oynadıklarında verilerini değiştireceklerdir. Ve sunucunun bu güncellemeleri kaydetmesi gerekir.

Ama nasıl ?

orada iki yol düşünüyorum:

1) sunucu çalışma zamanında ramda tasarruf sağlar ve bazen veya saatlik bir sunucu ram'dan sql veritabanına veri (güncelleme) yazar. Ancak elektrik kesilirse veya bir şekilde sunucu kapanırsa, güncellemeler tasarruf sağlamaz. Tabii ki güncellemeleri kaybetmek istemiyorum.

2) sunucu güncellemeleri çalışma zamanında veritabanına kaydeder. ama hız ne olacak? Bir yöntem düşündüm. Size resim ile aşağıda göstereceğim. Bu yöntemle 1000 çevrimiçi oyuncu için yeterince hız alabilir miyim? görüntü tanımını buraya girin


11
Herhangi bir kıyaslama yaptın mı? Veritabanı işlemlerinin oyununuz için bir sorun olacağını düşündüren nedir?
congusbongus

3
Oyun durumunuz aslında ilişkiselse? SQL veritabanı istediğinden emin misin?
Monica

6
Ayrıca lütfen şifreleri nasıl kullanacağınızı karma kullanarak okuyun. Veya en azından kullanıcıya şifrelerinin düz metin olarak kaydedildiğini bildirerek başka bir güvenli şifre kullanmamalarının farkındalar.
TomTsagk

24
Yan not olarak, ticari bir MMO inşa etmek istiyorsanız ve bunun gibi sorular soruyorsanız, muhtemelen daha küçük bir şeyle başlamalısınız. MMO'ları yapmak kesinlikle inanılmaz zor, bunları doğru yapmaktan bile çekinmiyorlar ve iş açısından çok iyi değiller. Bu sadece kişisel bir şeyse ve yüksek oyuncu sayımı yapmak istiyorsanız, 64 oyuncu gibi bir şeyle başlayın, sonra da yükselin. "Mükemmel" mimariyi en baştan deneyimsiz sıfırdan tasarlamaya çalışmaktan çok daha kolay olacak. Bkz bu .
Fon Monica'nın Davası

1
Depolama için agnostik olan genel bir API yazabilirsiniz. Ardından, gecikmeli depolama için verileri RAM'e önbelleğe alan bir adaptör yazın. Veya, verileri geçici dosyada önbelleğe alan bağdaştırıcıyı SQL DB'de yıkamak için yazabilirsiniz. Bu şekilde hangisinin en iyi olduğunu bulmak için önbelleğe alma özelliğini açıp kapatabilirsiniz. Çok fazla fazladan fazladan ekstra kod yazmanıza gerek yoktur, eğer mimarlığınız doğru yapılmışsa.
0xC0DEGURU

Yanıtlar:


37

Çoğu MMO (veya benzer mimariyi kullanan projeler) ilk yöntemi kullandım ya da kullandım: oyun sunucuları, esas olarak sunucu işlemlerini çalıştıran makinelerde RAM ile çalışır ve yalnızca ilgili oyun verilerini SQL veritabanına belirli aralıklarla seri hale getirir Arşivleme için (eğer biri kullanılıyorsa).

Elektrik kesintisi ile ilgili olarak not ettiğiniz sorunlar geçerlidir, ancak süreçteki çökmeler gibi sorunlardan daha az olasıdır (çalışma süresi güvenilirliği genellikle veri merkezine ödeme yapacağınız şeylerden biridir). Ama hala. Tasarruf aralığını ayarlamak (bu nedenle bir başarısızlık sadece birkaç dakikalık bir ilerleme maliyetidir), tasarruf sıralarını birden fazla makineye dağıtmak, kaydedilmesi gereken veri miktarını agresif bir şekilde taramak ve yeniden başlatılabilir tasarruf uygulamak gibi şeyler yoluyla bu sorunları azaltırsınız kuyruklar.

Genel olarak konuşursak, SQL sunucunun kendisini ana bellek olarak kullanmak tatsız derecede yavaş (ve hantal) olacaktır. Buradaki teklifinizde yalnızca 1000 oyuncu için işe yarayıp yaramayacağından emin olmak için yeterince ayrıntı görmüyorum - muhtemelen iyi olurdu. Ama agresif ölçeklendirilebilir yapabileceğine inanmıyorum.

Ayrıca, sorunu çözmez. Aynı tür yeniden başlatılabilir tasarruf kuyruğunu uygulamak için çalışma yapmadığınız sürece, tasarruf işlemi sırasında meydana gelen bir elektrik kesintisi yine de verileri kaybedecek ya da bozacaktır (ki o zaman bile, felaketle ilgili veri kaybı olasılığını ciddi şekilde azaltan, onu engellemez) .

İlk yaklaşıma gitmeni öneririm.


10
"Tasarruf aralığının ayarlanması" ile ilgili olarak, üzerinde çalıştığım en son MMO aktif oyuncu sayısına göre bir tasarruf aralığına sahipti. Dikkat çeken bir darboğaz gözetmeksizin X oyuncuların saniyede bir verilerini kurtarmanın üstesinden gelebileceğini biliyorduk, bu yüzden sadece dönen bir saniyede X oyuncuların altında biraz tasarruf sağladık. Genellikle, yoğun günlerde her iki dakikada bir, belki de yavaş zamanlarda dakikada iki kez olmak üzere, her oyuncu için bir tasarruf olarak sonuçlandı.
Meanbits

4
"Yeniden başlatılabilir kaydetme kuyruğu", birçok dosya sistemi ve veritabanı altyapısı tarafından uygulanan bir günlük gibi görünüyor mu?
Grawity

6
Bu sorunlar MMOs, hatta video oyunları, özgü değildir hiç . Neredeyse var olan her ORM, bir tür önbellekleme / harmanlama mekanizması sağlar. Kendi çözümünüzü atmanıza gerek yok.
BlueRaja - Danny Pflughoeft

3
Belirli bir aralıkta bir diske kaydetme işlemini bitirirseniz, insanların nadiren düşmesi / ölmesi / ölmesi gibi durumlarda işlerin hemen kaydedilebileceği bir sistem tasarlamanızı tavsiye ederim. Bu şekilde, eğer bir sunucu çökmesi ya da bir şey olursa, büyük bir şey başarmış insanlar çok üzülmeyecektir.
Jon

5
@Jon, ve sonra insanların nesneleri çoğaltabilmeleri sorunuyla karşılaşıyorsunuz. İdeal olarak, tüm oyun durumunu periyodik olarak tek bir işlem olarak kaydedersiniz. Parçalı olarak kaydetmeye başladığınızda, bir çarpışmanın tutarsız verilere neden olabileceği durumlara katlanırsınız; İsteğe bağlı bir çökmeye neden olan veya bir çarpmanın ne zaman olacağını tahmin edebilen oyuncular avantajlarından yararlanabilirler.
Mark

15

1000 oyuncu sorun olabilir veya olmayabilir. Veritabanını ne sıklıkta güncellemeniz gerektiğine bağlıdır. Ancak basit bir çözüm var: veritabanını kendi sunucusuna koy.


Veri tabanı sisteminin insanların bir MMO-Lite olarak adlandırdığı bir oyunu nasıl çalıştığını - hangisini ifşa edemeyeceğimi - ancak sürekli olarak 1000'den fazla oyuncunun olduğunu söyleyebilirim.

  • Özel karakter bilgileri (envanter, ekipman, benzeri) için "No-SQL" veritabanı tabanlı bir belge kullanıyorlar.
  • Nadiren güncellenen genel karakter bilgileri (isim, başarılar, vb.) Ve istatistikler için daha geleneksel bir ilişkisel veritabanı kullanırlar.

Belge tabanlı bir veritabanı kullanılması, bu durumda performans için iyi bir fikir olarak ortaya çıkıyor. Birleşmeler ve toplamalar yapmak için kötü olsa da verilere erişmek için iyidir ... ... ama orada bulunan verilerle yapmazlar.

Öte yandan, bir nesneyi herkes için başka bir nesneyle değiştirmek gibi bir şey yapmaları gerektiğinde, karakter karakter karakter alan ve bunları birer birer güncelleyen bir arka plan komut dosyası çalıştırma ihtiyacı fark edilir zaman alır.


Karakterin verileri hem istemcide hem de sunucuda bulunur ve sistem, her iki tarafta da aynı işlemleri yaparak onları senkronize tutmak için tasarlanmıştır.

Şimdi, bir oyuncu sistemle bir işlem yaptığında - NPC veya benzeri bir ürünle başka bir ürün değişimi söyle - bu aşamalar:

  • Müşteriler işlemin geçerli olup olmadığını kontrol eder
  • İstemci işlemi sunucuya gönderir (zaman uyumsuz işlem)
  • İstemci RAM'deki modelini günceller.
  • İşlemin geçerli olup olmadığını sunucu kontrol eder
  • Sunucu, modelini RAM’de günceller
  • Sunucu veritabanını günceller (zaman uyumsuz işlem)
  • Sunucu müşteriye değişikliğin gerçekleştiğini söyler

notlar :

  • Veri tabanı güncellemeleri, zaman uyumsuz olmasına rağmen hemen yapılır. Hangi nedenle olursa olsun oyun sunucusu düşerse, çok fazla kayıp olmaz.
  • Veritabanlarını kendi sunucularına yerleştirme sayesinde performansın düşmesi çok önemli değildir.

Oyuncular arasındaki işlemler, diğer oyuncuların dolandırıcılığını önlemek için ekstra kurallar ve bir işlemin yapılması gerektiğinde ekstra izlenebilirlik ile benzer şekilde ele alınır. Bir süre tutulan tüm işlemlerin özel günlükleri olduğunu duydum (birinin şikayet etmesi durumunda sorunları çözmek için), bu bölümün nasıl çalıştığını daha fazla bilmiyorum.


Bazen bir şeyler ters gider, bunun iki olası sonucu vardır:

  • Hata hemen meydana gelirse, sunucu istemciye, işlemi geri döndüreceğini söyler (oyuncu işlemi geri aldığını görür).
  • Kullanıcı Arabirimi, oynatıcının bir öğesi olduğunu ancak sunucunun aynı fikirde olmadığını söylüyor. Kullanıcı onu kullanmaya çalışırsa, sunucuya sorar ve başarısız olur ve sahte nesneyi kullanılamaz duruma getirir. Yanlış nesne, envanter yeniden yüklendiğinde kaybolur ve bu da modeli senkronize etmek için bir fırsat olarak kullanılır.

Her iki durumda, müşteri hatanın farkındadır ve oynatıcının yaptığı tüm işlemlerle birlikte günlüğe kaydeder. Müşteri tarafında oturum açmak her zaman oluyor. Ardından, oturumu kapattığınızda, bir hata varsa, istemci günlükleri sunucuya gönderir.


Bu oyun, çoğu MMORPG'nin sahip olduğu geleneksel günlük veya haftalık bakım zamanını kullanmaz. Bu zamanlanmış bakım genellikle sayaçları, zamanlayıcıları sıfırlamak, veritabanı işlemlerini çalıştırmak için kullanılır. Ayrıca, güncelleme için sunucu sürümlerini takas etme fırsatı da sunarlar.


Teşekkürler, peki ya oyuncu hareketleri, örneğin, bir oyuncu şu anki konumundan hareket ederse: x:10,y:10,z:10Bu x:11,y:11,z:11, derhal veritabanına kaydedilmeli mi? ya eğer oyuncu çalışmaya devam ederse, bu şu anki pozisyonunu her 1 saniyede bir ya da daha az bir süre içinde koruduğumuz anlamına gelir ve binlerce oyuncu varsa, bu her saniye DB'ye milyonlarca sorgu gönderir. Bu nasıl çalışıyor?
dwix

2
Oynatıcının konumu veritabanında nadiren kaydedilmelidir. Sadece menüyü açmak, kamp ateşi başlatmak, dinlenmek vb. Gibi özel durumlarda istersiniz. Oyuna bağlı olarak o kadar detaylı bile olmaz. Bazı oyunlar sizi her zaman en yakın kasabaya vb. Yerleştirir, böylece pozisyonu kaydetme zahmetinden kurtarırsınız. Ancak bu düşünceye dayalı olarak sürüklenir.
Nico,

1
Bahsettiğim oyun durumunda @ dwix, oyuncunun pozisyonu bile kaydedilmedi. Oturumu kapatıp oturum açarsanız veya sunucu kapanırsa, oynatıcı bilinen güvenli bir konuma geri yerleştirilir (düzenleme: özel bir örnek, eğer istersen "ev" olur, ancak herkes için aynıdır). Bununla birlikte, bazı oyunlar yanlışlıkla bağlantının kesilmesi durumunda bile oynatıcının tam konumunu korur. Bunu yapmak için, genel yaklaşım bu bilgiyi daha az sıklıkta depolamaktır. Yine de, sunucunun veritabanında ne beklediğini bilmiyorsunuz.
Theraot

1
@dwix avatarın konumu hakkında konuşurken, gerçekten tarihsel değerleri umursamıyorsun, değil mi? Eğer veritabanı bir şişe boynuysa, verileri kısın. Her sunucuyu tıklamak yerine, daha az sıklıkta saklayın. Veritabanının en güncel değere sahip olmayacağı, ancak performansı çok fazla etkilemeyeceği anlamına gelir. Bu arada, sunucu güncelleme değerini RAM'de tutacaktır ve bununla çalışıyor. Zeyilname: dürüst olmak gerekirse pozisyonları saklamaya karşı tavsiyelerde bulunabilirim, ancak bazı oyunlar bunu yapar.
Theraot


7

Her iki yaklaşım da MMORPG'lerle birlikte kullanılır. Her şeyi bellekte tutmak ve düzenli aralıklarla diski işaretlemeyi kontrol etmek, en azından eski oyunlar için en popüler seçenek gibi görünüyor. Oldukça iyi bir şekilde uygulanması ve ölçeklenmesi oldukça basit olma avantajına sahiptir, ancak bunu güvenilir kılmak, geliştiriciye tamamen kalmış durumda. SQL veritabanları güvenilirliği kolaylaştıran, ancak genel olarak uygulanması daha karmaşık olan ve ölçeklendirme ile ilgili problemler yaşayabilen ACID özellikleri sunar .

EVE Online, her şeyin bir SQL veritabanında depolandığı bir MMO örneğidir. Sanırım 60.000 civarında eşzamanlı kullanıcıya hitap ediyor ve yüke ayak uydurabilmek için yıllar boyunca veritabanı sunucularına bazı pahalı donanımlar ayırmak zorunda kaldı. Bununla birlikte, EVE kullanıcı başına çoğu MMORPG'den çok daha fazla veri depolar ve çok daha sık ve çeşitli işlemlere sahiptir. Veritabanının ACID özellikleri, tüm büyük ve karmaşık veri tabanlarının her zaman tutarlı bir durumda tutulmasını sağlar.

Örneğin, birisi başka bir oyuncuya bir öğe verdiğinde durumu düşünün. EVE veri tabanı, bir çarpışma veya elektrik kesintisi durumunda bile, öğenin yalnızca bir oyuncunun envanterinde sona erdiğini garanti eder. Yani, öğeyi bir oyuncunun envanterinden kaldıran ve diğer oyuncunun içine ekleyen veritabanı işlemi atomiktir. İşlem ya tamamen tamamlandı ya da hiç olmadı. Bir oyuncunun envanterinde veya her ikisinde de öğe bulunmuyorsa bir durumda olamazsınız.

Oynatıcı verilerini bellekte tutan ve periyodik olarak kontrol noktalarını tutan bir MMORPG, bu atomiteyi kendisi uygulamak zorundadır. Bunu yapmanın bir yolu, her oyuncunun verilerini aynı anda kontrol etmek ve yeni kontrol noktasının en son kontrol noktası olarak kabul edilmeden önce diske tamamen bağlı kalmasını sağlamaktır. Oyun aynı zamanda, kontrol edilen süre boyunca oyuncu verilerinin değişmemesini sağlamalıdır. Çok sayıda aktif oyuncu ile, meydan okuma bütün bunları, oyuncuların farkedeceği kadar uzun bir gecikmeye neden olmadan gerçekleştirir.

Tutarlılığın ne kadar önemli olduğunu hafife almayın. Oyununuzu geliştirirken çokça çarpacak. Sorun alakasız bir hata oyunun kötü bir zamanda çökmesine neden olduğunda değil, öğelerin neden ortadan kalktığını ve / veya çoğaldığını anlamak istemezsiniz. Dahası, oyununuz yayınlandığında, beklediğinizden çok daha fazla çarpacaktır. Mükemmel bir şekilde test altında çalışan sunucunuz aniden tam yük altında çok fazla hataya neden olacak ve oyuncuların beklemeyeceği şeyleri yapabilecek.

Çoğu MMORPG'nin, gerçek oyun verileri için olmasalar bile hesapla ilgili bilgiler için SQL veritabanları kullandığını unutmayın. Oyun durumunu tutarlı bir durumda tutmaktan daha önemli olan, fatura durumunu tutarlı tutmaktır. Oyun veritabanını bozmak için en kötü durum, veritabanını günlük bir yedekten geri yüklemek zorunda olmanızdır. Hesap veritabanının bozulmaması için en kötü durum, tüm geri ödemeler nedeniyle iflas etmenizdir.

Projeniz için muhtemelen iki yoldan da gidebilirsiniz. 1000 eşzamanlı kullanıcıya sahip olmak muhtemelen bir SQL sunucusunun bugünlerde bir emtia bilgisayarında neler yapabileceğinin sınırlarını zorlamayacak, ancak çoğu işlemin niteliğine bağlı olacaktır. SQL ve ilişkisel veritabanı tasarımına aşina iseniz, bu sizin için işe yarayabilir. İşlemleri mümkün olduğu kadar en aza indirmek isteyeceksiniz, oyuncuların güncel hit puanları gibi bir şey için bunları düzenli aralıklarla veritabanına kaydetmek isteyebilirsiniz, çünkü bunun gibi istatistiklerin tutarlı olması gerekmez. (PvP oyunda olsa bile ...) Canavar HP gibi şeyleri veritabanında saklamayın, çoğu oyunda sadece oyuncu ile ilgili veriler kalıcıdır.

Öte yandan, bir SQL sihirbazı değilseniz, güvenilir bir şekilde çalışmak için tüm verileri bellekte tutmayı çok daha basit bulabilirsiniz. SQL veritabanları tutarlılığı ve güvenilirliği kolaylaştırır, ancak otomatik değildir. Kötü tasarlanmış bir veritabanı yetersiz performans gösterebilir ve tutarsızlıklara yol açabilir. Yapmadıkça işlemler atomik olmayacak. Parametreli ifadeleri dini olarak kullanmazsanız, kendinizi SQL enjeksiyon saldırılarına açarsınız.


0

Çeşitli oyunlar, şeyleri farklı şekillerde saklar. Genellikle, oyun şirketleri bunu yapmanın bir yolunu yaratır ve oyunlarının çoğu aynı şekilde kullanır. Tabii ki, farklı stüdyolar genellikle farklı yollar kullanır. SQL kesinlikle oyunlar için kullanılıyor, örneğin CCP (EVE) bir SQL sunucu ağına sahipti (veya en azından vardı), şimdi nasıl yaptıklarından emin değilim. Diğerleri, sadece çok sayıda dosya kullanın.

Belki çeşitli oyun veri işlemlerini ele almak için agnostik bir "veri aracı mekanizması" oluşturarak başlayabiliriz? Sadece zaten test yaptığınız için, oyunun bakış açısından depolama hakkında çok fazla ilgilenmenize gerek kalmayacak bir mekanizma oluşturun. Yani, ana bilgisayar uygulamasından, bununla nasıl başa çıkacağınıza odaklanın.

Şahsen, oyunu ve komisyoncunun kendisini yeniden yazmak zorunda kalmadan, gerçek mağazayı değiştirebilmenin büyük bir avantaj olacağını düşünüyorum. Aracının konuşması için aynı arabirime sahip başka bir modüle geçmeniz yeterli.

Verileri kendi içinde saklamak muhtemelen kendi başına bir sorun olmayacak. Verileri, bu depoya / depodan, ana bilgisayar ve tüm istemciler arasında verimli bir şekilde göndermek daha zor olabilir. Tüm oyuncu veri setini gönderiyor muyum, yoksa parçalara ayırırsam, hangi ayrıntı derecesine göre ayırmayı seçiyorum, vb.

Verilerin gönderileceği formatlardan biri XML olabilir. Bu şekilde nasıl parçalayabildiğiniz konusunda daha kolay dinamik olabilirsiniz. Bir karakter birden fazla karaktere, bir öğe vs bir öğe koleksiyonuna vs vs Verilerin gerçekte saklanmasını istediğiniz şekilde.

Başka bir yol da nakliye açısından daha verimli olan, ancak diğer durumlarda daha fazla maliyete neden olabilen ikilidir.

1.000 istemciyle, her istemci için 10 MB ile başlayabilir ve kolayca depolayabilir ve yalnızca 10 GB etkin RAM kullanabilirsiniz + bu verileri yönetmek için bazı sistem yönetimsel RAM ekleyin, başka bir GB veya iki tane söyleyin. Bunu, ana bilgisayardaki RAM'de, veri yapısında kullanıma hazır halde tutabilirsiniz. Ayrıca çevrimiçi olarak, etkinliğe, vb. Bağlı olarak çeşitli frekanslarda dinamik olarak yükleyin / kaydedin.

Her müşterinin bilgilerini ayrı bir dosyada saklayabilirsiniz, vb.


0

* Çevrimiçi * oyuncuları ram içinde tutun ve oturumu kapattıklarında bir veritabanına (SQLite? MySQL?) Bastırın. oturum kapatma sırasında IO'nun durması konusunda endişeleniyorsanız, her oturumu kendi başlığına verin, ana / oyun başlığında yapmayın (aslında her çevrimiçi oyuncu için özel bir oyuncu dizisi tutuyorum, ağ kodunu çok daha kolay hale getirdim zaman uyumsuz ağ io yaklaşımı yapmaktan daha)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.