←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

Pare pytań odnośnie mysql

  • +
  • -
Sniper Elite's Photo Sniper Elite 21.03.2014

Witam.

Chcę przenieść swój "stary cod" z zapisu nvault na mysql. Jako że pierwszy raz będę to robił mam kilka pytań:

 

- jak najlepiej zabierać się za zapis (aby jak najszybciej wczytywał dane po zmianie mapy)?

- czy ilość zmiennych do pobrania z bazy ma wpływ na szybkość jej wczytania?


Edited by Sniper Elite, 21.03.2014 20:55.
Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 22.03.2014

Najlepiej się za to zabrać w client_authorized, ale... 32 zapytania do pobrania danych dla wszystkich graczy tuż po zmianie mapy na pełnym 32 slotowym serwerze prawie na 100% skończy się crashem. Na mniejszych serwerach będzie niewiele lepiej, już od 15 graczy mogą się zacząć spore problemy. Dlatego dobrym pomysłem jest cache zapytań. Robisz tak: gdy nadchodzi zmiana mapy, zapisujesz gdzieś nieulotnie (np w pliku) listę graczy, którzy są na serwerze przed zmianą. Prawie wszyscy będą na serwerze po zmianie. Tuż po zmianie (plugin_configure) wykonujesz jedno zapytanie, w którym pobierasz dane dla wszystkich tych graczy i zapisujesz je w tablicach w taki sposób, aby po połączeniu odpowiednich graczy spowrotem po zmianie mapy, można było te dane do nich dopasować i załadować je im zamiast wykonywać dla każdego oddzielne zapytanie. Jak się znajdzie ktoś, kto przy zmianie mapy dojdzie to dla niego pobierasz dane w standardowy sposób. Jeśli ktoś po zmianie mapy nie powróci, nic się nie stanie.

Następna rzecz: zapis danych, tutaj również nie można przesadzić z ilością zapytań, a przy zmianie mapy znów mamy ich mnóstwo. Dlatego zamiast zapisywać dane w client_disconnect, stwórz string który wypełnisz początkiem zapytania (INSERT INTO .... VALUES), w client_disconnect dodaj do tego stringa dane o konkretnym graczu, a w plugin_end dodaj końcówkę zapytania (ON DUPLICATE KEY UPDATE...) i je wykonaj. Obciążenie serwera spada w tym momencie znacznie.

Grunt to podzielić sobie zadanie na 3 etapy i wykonywać je w tej kolejności:
  • Projekt bazy danych - należy go wykonać w taki sposób, aby można było przy zapisie użyć jednego zapytania INSERT INTO ... ON DUPLICATE KEY UPDATE zamiast dwóch oddzielnych INSERT oraz UPDATE i do tego SELECT żeby sprawdzić którego należy użyć
  • Zapis do bazy danych - dobrze jest go wykonać przed odczytem. Uwagi napisałem już wyżej.
  • Odczyt z bazy danych - to idzie na końcu, tutaj musimy umiejętnie użyć cache'owania, bo ludzie mają dziwne pomysły i wystarczy kilka osób które będą na zmianę wchodzić na serwer i z niego wychodzić, żeby ten serwer wywalić (przy amxbans wystarczy jedna taka osoba i serwer się po chwili wykłada)
To, ile zmiennych pobierasz nie ma znaczenia (no jakieś ma, ale cholernie nieistotne). Znaczenie ma, jak już wyżej napisałem, ilość zapytań wykonywanych w danym czasie oraz to, jak "daleko" serwer ma do bazy danych (czyli jak długo będzie trwać wykonanie zapytania).
Quote

  • +
  • -
Sniper Elite's Photo Sniper Elite 23.03.2014

Ciekawie opisane, dzięki :)

A zapis np. w najnowszym diablo 5.9l lub CodMod v3 lud Diablo Core Darka jak się sprawdza przy 32 graczach?

Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 23.03.2014

Sądzę, że nie bardzo... Jeśli masz dobre połączenie z serwerem MySQL i szybko on odpowiada to może się sprawdzić, ale jeśli połączenie jest słabe (np SQL jest we Francji, a HLDS w Polsce) to będzie kiepsko...

Quote

  • +
  • -
Sniper Elite's Photo Sniper Elite 23.03.2014

Hosting to unixstorm, więc wszystko ładnie śmiga. Jedyny minus to to że zwykły hosting, vps zakupie dopiero w wakacje.

Spróbuję zrobić na razie coś  na podobe coda darka. Mam na serwerze rozgrzewkę, więc powinno się w trakcie jej załadować. Bo tym sposobem który opisałeś będzie ciężko, jeszcze tak programować nie umiem.

Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 23.03.2014

To naprawdę nie jest ciężka rzecz, wystarczy małymi kroczkami się do tego zabrać. Cały 1 i 2 punkt opisałem w poradniku na forum Plugin + baza danych tylko 3 punkt, czyli odczyt Ci zostaje. Tu możesz sobie na początek plugin uruchamiać bez bufurowania danych, zawsze to będzie przyrost wydajności na samym zapisie danych i mniej crashy przy zmianie mapy (mniej nie oznacza wcale, bo jeszcze odczyt zostaje).

Kiedyś może pokuszę się o uniwersalny moduł zapisu danych do SQL i pliku, w którym miejsce zapisu będzie się wybierało bez udziału pluginu i będzie się on już zajmował optymalnym rozplanowywaniem wykonywania zapytań w przypadku użycia SQL. Ale to na pewno będzie dalej niż bliżej, bo priorytetem dla mnie jest kilka innych rzeczy.
Quote

  • +
  • -
Sniper Elite's Photo Sniper Elite 23.03.2014

Czyli proponujesz zrobić tak:

- zapisywać dane ze statystykami expem i poziomem do pliku tekstowego i powiedzmy co 60 sek. sprawdzać czy gracz dalej gra na serwerze, jeżeli nie to zaktualizować jego wpis w bazie a ten z pliku tekstowego wyczyścić.

- to samo z odczytem. Po zmianie mapy większość graczy będzie z poprzedniej mapy, więc odczytanie danych też nie powinno być problemem. Jeżeli go tam nie ma odczytać dane z tabeli, ew. utworzyć nowy wpis.

- nie używać client_disconnect oraz plugin_end bo wtedy zapytanie wywoływane jest wszystkim graczom (zmiana mapy) a to laguje.

 

Jest funkcja która zwraca ilość wpisów w takim pliku tekstowym?


Edited by Sniper Elite, 23.03.2014 22:41.
Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 23.03.2014

Zapisywać dane możesz w zmiennej, tworzysz zmienną globalną o takiej długości, aby pomieściła zapytanie zapisujące 32 graczy na raz, wypełniasz ją początkiem zapytania insert, gdy gracz wyjdzie z serwera (client_disconnect) dopisujesz do zmiennej dane gracza do zapisania. Co jakiś czas (np 60 sekund), gdy dopiszesz już 32 graczy i w plugin_end dopisujesz do zapytania jego koniec, wykonujesz je, czyścisz zmienną i wpisujesz znów początek. Z tym wyjątkiem, że w plugin_end nie używasz ThreadQuery, ale metody "blokującej" (przy plugin_end tego "blokowania" nie widać, a ThreadQuery może powodować błędy)

Przed zmianą mapy zapisujesz dane użytkownika w jakimś pliku, po zmianie po 60 sekundach czyścisz plik. Wygodnie jest sobie utworzyć folder w data i w osobnych plikach trzymać dla każdego gracza dane, pliki nazywając ID gracza (nick, steamid czy ip w zależności od tego po czym sprawdzasz) + czas utworzenia pliku (wtedy wiesz kiedy go usunąć) i odpowiednio sprawdzać, czy plik istnieje gdy gracz wchodzi na serwer.
Quote

  • +
  • -
Sniper Elite's Photo Sniper Elite 25.03.2014

Nie było mnie troszkę.

Przeszukałem forum, ale nie znalazłem nic o dokładnym opisie mysql w amxx. Chodzi mi głównie to takie zwroty jak "INSERT INTO" lub "ON DUPLICATE KEY".

Jest gdzieś to wyjaśnione?

Quote

Seba's Photo Seba 26.03.2014

 

 

Najlepiej się za to zabrać w client_authorized, ale... 32 zapytania do pobrania danych dla wszystkich graczy tuż po zmianie mapy na pełnym 32 slotowym serwerze prawie na 100% skończy się crashem. 

Tiru riru paczka zwiru, a amxbans dziala na tysiacach serwerow wlasnie w ten sposob. ;)

Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 26.03.2014

Tiru riru paczka zwiru, a amxbans dziala na tysiacach serwerow wlasnie w ten sposob. ;)


I wiele serwerów z amxbans właśnie dlatego przy zmianie mapy crashuje. Wystarczy, żeby połączenie z bazą danych było wątpliwej jakości.
Quote

Seba's Photo Seba 27.03.2014

 

Tiru riru paczka zwiru, a amxbans dziala na tysiacach serwerow wlasnie w ten sposob. ;)


I wiele serwerów z amxbans właśnie dlatego przy zmianie mapy crashuje. Wystarczy, żeby połączenie z bazą danych było wątpliwej jakości.

 

Ale jak juz komus radzisz to rob to rzetelnie, 100% to oznacza za kazdym razem :)

Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 27.03.2014

Tiru riru paczka zwiru, a amxbans dziala na tysiacach serwerow wlasnie w ten sposob. ;)


I wiele serwerów z amxbans właśnie dlatego przy zmianie mapy crashuje. Wystarczy, żeby połączenie z bazą danych było wątpliwej jakości.

Ale jak juz komus radzisz to rob to rzetelnie, 100% to oznacza za kazdym razem :)

Dlatego napisałem "prawie na 100%". Jestem nastawiony na pisanie pluginów, które mają działać w każdej sytuacji, a nie tylko na moim dobrze skonfigurowanym serwerze który ma dobre połączenie z bazą danych (a i w takiej sytuacji na 32 slotowym serwerze crashe się zdarzają). Bo nawet jak piszę plugin dla siebie, to moje warunki też mogą się zmienić i nie będę miał bazy danych w dobrej lokalizacji względem serwera.
Quote

  • +
  • -
sebul's Photo sebul 27.03.2014

Jakby nie patrzeć "prawie 100%", to też "trochę" za dużo. Oczywiście masz rację pisząc, że nie jest to dobrze zrobione, ale też nie przesadzajmy, że to nie działa. Co prawda może sam nie miałem nigdy 32 slotowego serwera, ale widziałem jak działają takie serwery z amxbansem (nawet starszym niż gm amxbans).

Quote

  • +
  • -
Sniper Elite's Photo Sniper Elite 27.03.2014

Panowie odbiegamy od tematu :)

 

Powiedzmy że będę chciał zapisywać poziom gracza do pliku (w config/lvl.ini). Taki mały przykład:

 

"Sniper Elite" "13" "14440" "statystyka1" "statystyka2"...

"sebul" "15" "18888" "statystyka1" "statystyka2"...

"Seba" "11" "10000" "statystyka1" "statystyka2"...

 

Da się później z tego pliku odwołać do określonego nicku? Sprawdzić czy dany nick w nim widnieje?

 

Chciałem zrobić tak, że po wbiciu na serwer i odczytaniu lvl z bazy będzie on zapisywany w takim pliku i aktualizowany gdy dostaniemy expa.

Następnie taskiem będę sprawdzać czy gracz na serwerze jeszcze jest, jeżeli nie zapisze dane do bazy a wpis usunę.

 

Jeżeli takie operacje są możliwe poproszę o jakiś poradnik z dokładnym opisem jak takie zapisywanie do pliku działa (zapis wartości, sprawdzanie czy w dokumencie istnieje dana wartość (nick), usuwanie wpisów z tego pliku oraz może ilość graczy zapisanych w tym pliku).

 

Jeżeli nie to pomysł GwynBleidD też jest spoko:
 

 

Zapisywać dane możesz w zmiennej, tworzysz zmienną globalną o takiej długości, aby pomieściła zapytanie zapisujące 32 graczy na raz, wypełniasz ją początkiem zapytania insert, gdy gracz wyjdzie z serwera (client_disconnect) dopisujesz do zmiennej dane gracza do zapisania. Co jakiś czas (np 60 sekund), gdy dopiszesz już 32 graczy i w plugin_end dopisujesz do zapytania jego koniec, wykonujesz je, czyścisz zmienną i wpisujesz znów początek. Z tym wyjątkiem, że w plugin_end nie używasz ThreadQuery, ale metody "blokującej" (przy plugin_end tego "blokowania" nie widać, a ThreadQuery może powodować błędy)

Przed zmianą mapy zapisujesz dane użytkownika w jakimś pliku, po zmianie po 60 sekundach czyścisz plik. Wygodnie jest sobie utworzyć folder w data i w osobnych plikach trzymać dla każdego gracza dane, pliki nazywając ID gracza (nick, steamid czy ip w zależności od tego po czym sprawdzasz) + czas utworzenia pliku (wtedy wiesz kiedy go usunąć) i odpowiednio sprawdzać, czy plik istnieje gdy gracz wchodzi na serwer.

 

 

tylko ciut skomplikowany. Nie mam pomysłu jak ta duża zmienna globalna miałaby wyglądać.


Edited by Sniper Elite, 27.03.2014 12:25.
Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 27.03.2014

Trie albo coś w tym rodzaju miałem na myśli zamiast tej zmiennej. Chociaż i tak nie będzie to łatwe do zrobienia w AMXX. Twoje rozwiązanie również do najłatwiejszych nie należy.
Quote