Autor | Zpráva | ||
---|---|---|---|
zrnecx Profil |
Dobrej den,
dělám hru na telefony v Cordove, a jako server pouzivam PHP.... jsou nektere kroky ktere je potreba udelat jen jednou (Matchmaking, Priprava hry) a pri cekani na hru se odesila opakovane pozadavek jestli je hra pripravena.... nevim jak zacit, proste kdyz je request tak sem to vymyslel tak ze v nejake slozce "temp" si vytvarim indikacni soubory... funguje to tak ze prvni pozadavek vytvori soubor, probehne priprava a pak se soubor smaze. kazdy dalsi uzivatel ktery posle pozadavek na zjisteni stavu zjisti ze soubor existuje a jen vrati vysledek true/false jestli je hra pripravena.. Pro priklad vam sem dam kod: private static function CanProcessMatchmaking($id) { @mkdir("temp",0777,true); return !file_exists("temp/".$id.".block"); } private static function SignStart($id) { if(self::CanProcessMatchmaking($id)) { file_put_contents("temp/".$id.".block",$id); return true; } else { return false; } } private static function SignEnd($id) { unlink("temp/".$id.".block"); } a kod kterym provadim akce je: private static function StuffToDo() { if(self::SignStart("matchmake")) { //Match Prepare Here... self::SignEnd("matchmake"); } } Je tohle "dobry" zpusob jak to udelat? vim ze je pruser kdyz nabehne vyjimka a nesmaze to soubor, ale to poresim tim ze proste zadna vyjimka nemuze nastat (vse osefim) me by jen zajmalo jestli je to spolehlivy zpusob jak udelat ze process probehne jen jednou za dobu kdy bude napr 10,1000,1000000 requestů na ten konkretni php soubor... predem dekuji za odpovedi :) |
||
Joker Profil |
#2 · Zasláno: 10. 9. 2018, 10:26:11
zrnecx:
Nebylo by lepší použít databázi? |
||
zrnecx Profil |
#3 · Zasláno: 10. 9. 2018, 12:49:13
Joker:
tom si nejsem jisty prave.. ale asi ji pouziju no... me se nechtela kvuli tomu delat tabulka abych to jen na ryhchlo zprovoznil.. v tom pripade ta sama otazka, nemuze pri vetsim mnozstvi uzivatelu ten jedne proces probehnout 2x? jde mi o to aby kdyz to najde 2 hrace co budo hrat proti sobe a najendou process co bezi zaraz najde jednoho z nich ale hodi to tretimu, tak by se to rozbilo, timhle sem tomu chtel zabranit. nejlepsi by byl cron ale u wedosu muzu spustit max 1 za 5 minut coz je dlouha cekaci doba si myslim... |
||
Joker Profil |
#4 · Zasláno: 10. 9. 2018, 13:20:38
Tak teď nevím přesně jaký problém řešíte.
Ale jestli jde o problém paralelismu, tj.: Dvě spuštěná hledání najdou paralelně téhož volného hráče a přidělí ho do dvou různých her, tak to je řešitelné např. pomocí zámků, kdy samotnou operaci přidělení může současně dělat vždycky jen jedna instance a ostatní musejí čekat, až ta první skončí a uvolní zámek. Přesněji nevím jak poradit dokud nemám bližší popis problému. |
||
zrnecx Profil |
#5 · Zasláno: 10. 9. 2018, 13:46:30
Vsak o tom je prvni prispevek, ten zamek mel byt soubor ve slozce temp a nebo jak si rikal v nejake tabulce v databazi bude 1 nebo 0 podle toho jestli uz nejaky probiha nebo neprobiha
cely proces je uz mam normalne funkcni, otazka tedy zni nasledovne: Příklad 1, tak jak to má fungovat.. //ZÁMEK = 0 Request 1: checknout jestli je zámek 0 [true] Request 1: nastavit zámek na 1 [] //ZÁMEK = 1 Request 1: delat operaci kterou potrebuju jen jednou zaraz [] Request 2: checknout jestli je zámek 0 [false] Request 2: nemam co delat.. konec skriptu... Request 1: operace dokoncena, zámek na nulu //ZÁMEK = 0 Příklad 2, to co mam strach ze se stane //ZÁMEK = 0 Request 1: checknout jestli je zámek 0 [true] Request 2: checknout jestli je zámek 0 [true] Request 1: nastavit zámek na 1 [] //ZÁMEK = 1 Request 2: nastavit zámek na 1 [] //ZÁMEK = 1 Request 1: delat operaci kterou potrebuju jen jednou zaraz [] Request 2: TAKTÉŽ delat operaci kterou potrebuju jen jednou zaraz [] Request 1: operace dokoncena, zámek na nulu //ZÁMEK = 0 ;(nyni by se mohl pripojit treti uzivatel ktery uvidi ze je zamek 0 i kdyz ani druhy nedobehl (pritom nemel vubec bezet)) Request 2: operace dokoncena, zámek na nulu //ZÁMEK = 0 chápeme se? nevim jak vic polopaticky vysvetlit svuj dotaz :) |
||
Kajman Profil |
#6 · Zasláno: 10. 9. 2018, 14:12:39
V databázi (innodb) to vyřeší použití transakce.
|
||
zrnecx Profil |
Na wedosu:
Verze MySQL: 5.5.5-10.1.19-MariaDB i tady? Jinak rad bych se toho dozvedel vice.. pouzivam nette/database (momentalne v2.4.6, ale muzu pres composer normalne updatnout) Jde to přes to nejak normalne? |
||
T-fon Profil |
#8 · Zasláno: 10. 9. 2018, 14:42:28
Nette má transakce jednoduše vyřešené.
|
||
zrnecx Profil |
#9 · Zasláno: 10. 9. 2018, 14:53:25
Takže když udělám
$database->beginTransaction(); $info = $database->fetch("SELECT locked...."); if($info!==false&&$info["locked"]==0) $database->query("UPDATE locked na 1"); $database->commit(); a mezitím když nekdo zavola druhej pokus, tak se druhá instance sekne na begin transaction dokud v první nedám commit? nebo to chápu úplně špatně? |
||
Kajman Profil |
#10 · Zasláno: 10. 9. 2018, 15:53:45
Mysql v innodb tuším zamyká záznamy na úrovni řádků, takže jiná transakce dělající select a update na jiném řádku tabulky by neměla být s touto v kolizi.
Hlavně tu tabulku vytvořte typu innodb a nevytvářejte ji jako myisam, abyste transakce nad ní mohl korektně používat. |
||
Joker Profil |
#11 · Zasláno: 10. 9. 2018, 16:00:49
zrnecx:
Pokud používáte databázi, není důvod si dělat zámky manuálně. Čili postup v databázi by byl: 1. LOCK TABLES 2. UPDATE 3. UNLOCK TABLES Možná mezi 1. a 2. ještě bude zjištění, koho vlastně aktualizovat, ale podle mě by to šlo udělat jedním dotazem. Něco na způsob: UPDATE players SET idGame=id aktuální hry WHERE hráč ještě nemá přidělenou hru LIMIT 1 Pokud se spustí víc instancí, tak všechny ostatní budou čekat na LOCK TABLES dokud se zámek neuvolní. |
||
Kajman Profil |
#12 · Zasláno: 10. 9. 2018, 16:18:46
Lock tables je postup pro starší myisam tabulky.
|
||
zrnecx Profil |
#13 · Zasláno: 11. 9. 2018, 08:20:26
já tomu teda nerozumím... (mozna je to tim ze piju tu dedovu slivovicu) jak by teda vypadal kod, ktery pouziva nette database......
zadani vypada tak, ze mam JSON api... aplikace se kni pripoji pomoci tokenu ktry dostane pri prihlaseni tabulka vypada takhle: Tabulka: match_making id int(11) Auto Increment //AI team mediumtext //JSON členove teamu game_type int(11) // typ hry matched tinyint(4) //bool 1/0 (uz byl prirazen ke hre? SQL: "WHERE matched = 0") match_room int(11) // IDcko hry do ktere byl pridan, pokud je matched 1 druha tabulka s hrama: Tabulka: match_room id int(11) Auto Increment //IDcko hry viz "match_room" v match_making game_type int(11) //typ hry jako v predchozi tabulce players_team1 mediumtext //seznm rhacu tymu 1 players_team2 mediumtext //seznam hracu tymu 2 json_game_stack longtext //trida hry ulozena pomoci funkce "serialize()" (jo chtel sme json ale to neulozi celou tridu) finished tinyint(4) //1/0 true false ready tinyint(4) //1/0 true false v klientovi se pripojuje na api kazdych nekolik stovek ms kazdy klient co hleda mathmaking, a kazdy z nich ktery objevi ze nikdo nedela matchmaking ho bude delat... pseudokod toho co chci: NetteDatabase: Check jestli je lock 0 NetteDatabase: Nastaveni locku na 1 a okamzite zablokovani moznosti upravy tabulky jinym procesem NetteDatabase: zkusit jestli neni tabulka zamknuta (transakce?) a nastavit lock na 1 Ostatni kod: najit pár a uložit ho do match_room a v match_making nastavit matched na 1 (to mam nakodovane, tenhle muzete vlozit jen jako komentar "do" NetteDatabase: Hodit lock na 0 a umoznit jinnym procesum hledat match Pardon ze se ptam jak retard, ale fakt nevim jak ty transakce fungují, kdyby jste mi sem napsali nejaky ten kod toho zamykani byl bych nadmíru štasten.. dekuji pánové za rady :) :* mam vas rad :) |
||
Kcko Profil |
#14 · Zasláno: 11. 9. 2018, 16:52:47
zrnecx:
Jak se pracuje s Nette database najdeš na Nette.org, to bys mohl vědět, když Nette používáš viz doc.nette.org/cs/2.4/database-core (dole). Nastuduj si to trošku , napiš nějaký kód a pak se ptej dál (a to spíš na Nette fóru), tahle diskuse není Nette diskuse. |
||
zrnecx Profil |
#15 · Zasláno: 12. 9. 2018, 09:37:24
Tak nette nepouzivam, jenom tu databazi a tracy, jinak to nema s nette nic spolecneho... dik za odpovedi :)
|
||
T-fon Profil |
Pokud používáš Nette Database, tak to můžeš řešit těma transakcema, na který jsem ti už posílal odkaz. Asi to teda neni nejideálnější řešení, ale funguje to a je to jednoduchý na použití.
|
||
Kcko Profil |
zrnecx:
Mno a? Já taky na svém projektu, který není postaven na Nette používám moduly z Nette (Tracy, Nette database, Forms, Latte). S Nette database se pracuje pořád stejně. Nemáš zač, když se budeš trošku snažit, tak to napíšeš. Tady máš příkazy jak pracovat s transakcí. Zahájíš / Potvrdíš nebo Zrušíš. |
||
Joker Profil |
zrnecx:
Dotaz k návrhu té databáze: Skutečně obsahuje sloupec matched v tabulce match_making nějakou novou informaci? Není to tak, že v matched je 1 právě tehdy když v match_room je ID hry a 0 právě tehdy když match_room je NULL (popř. 0)? Podle mě by to snad ani speciální zámek nevyžadovalo. Když by se hra přidělovala dotazem na způsob: UPDATE match_making SET match_room = ID hry WHERE match_room IS NULL [AND případné další podmínky] [ORDER BY nějaká priorita přidělování] LIMIT 1 …tak by si databáze měla sama ohlídat, že to nechytí dvakrát stejný řádek. |
||
zrnecx Profil |
#19 · Zasláno: 13. 9. 2018, 13:38:59
tak vono je to tam kvuli historii kdo byl skym matchnuty abych mohl debugovat, ale tohle vypada hezky
|
||
Joker Profil |
#20 · Zasláno: 13. 9. 2018, 14:55:29
zrnecx:
Jenže to může uchovat historii stejně jen o krok zpátky (tj. když bude v matched 0, může v match_room být ID předchozí hry). Jestli chcete historii, udělal bych pro každou hru nový záznam. Aktuálně to předpokládám funguje tak, že přidělení hry nastaví matched=1 a ID hry, následně po hře se přenastaví matched=0 (a zůstane staré ID hry) a další přidělení přepíše ID hry a nastaví zase matched=1. Pro zachování historie by šlo dát každému záznamu ještě stav, po skončení hry by se záznam nastavil jako už neaktivní a před další hrou by se založil nový záznam. |
||
zrnecx Profil |
#21 · Zasláno: 13. 9. 2018, 16:11:21
Joker:
„Jenže to může uchovat historii stejně jen o krok zpátky“ nene, uchova ji celou protože „Aktuálně to předpokládám...“ ... špatně. Takhle vypada tabulka (nikdo zrovna hru nehledá) Takhle vypadá tabulka her: Prostě historii to uloží... neměl sem ted 2 dny cas na tom delat... jestli chcete, tak dam vedet jak dopadla ta moje zkouska s transakcema... taky sem jeste narazil na nette/safe-stream.. to by melo jit pouzit kdyz dam na zacatku fopen a po dokonceni fclose... |
||
Časová prodleva: 6 let
|
0