[PHP] Requests naar Redis, of opslaan in var?

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
Deze code is een voorbeeld om de situatie te schetsen, niet iets wat in praktijk gebruikt zou worden.

Ik vraag me af of het aan performance iets uitmaakt hoe vaak je de request doet naar Redis, of het toch echt in een globale variable op moet slaan.


Stel er is een class:
code:
1
2
3
4
5
class tweaker {
   static function henk() {
      return $redis->get('henk');
   }
}


En daarna iets om het op te vragen:
code:
1
2
3
for ($i = 1; $i <= 100; $i++) {
   tweakers::henk();
}



In dit geval gebeurt het dat tweakers::henk(); 10x opgevraagd wordt.
Ik vraag me af of dit kwaad zou kunnen om te doen qua performance.
Of is het beter om iets als dit te doen (en dat maakt het niet bepaald mooier).

code:
1
2
3
4
5
6
class tweaker {
static function henk() {

if (!isset($GLOBALS['henk'])) $GLOBALS['henk'] = $redis->get('henk');
return $GLOBALS['henk'] ;
}

Alle reacties


Acties:
  • 0 Henk 'm!

  • Room42
  • Registratie: September 2001
  • Niet online
Meten == weten. Dit kun je toch gewoon benchmarken?

[ Voor 54% gewijzigd door Room42 op 17-12-2019 13:35 ]

"Technological advancements don't feel fun anymore because of the motivations behind so many of them." Bron


Acties:
  • 0 Henk 'm!

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
Room42 schreef op dinsdag 17 december 2019 @ 13:35:
Meten == weten. Dit kun je toch gewoon benchmarken?
Zeker, maar dan voeg ik graag extra benchmarks toe op basis van suggesties.
Ik kan me niet voorstellen dat werken met
code:
1
$GLOBALS['henk']
een goede mogelijkheid zou zijn.

Acties:
  • 0 Henk 'm!

  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 12:59

The Eagle

I wear my sunglasses at night

Redis gebruiken betekent een extra component, dus theoretisch heb je sowieso een stukje extra legacy tov native in de code en dus in memory houden.
Having said that: als je wilt parallelliseren ontkom je er niet aan statefull te werken. En het is juist redis wat heel handig is om snel meerdere states bij te houden. Dat wordt wat lastig met globale variabelen. En bovendien schaalt dat voor geen meter horizontaal.

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)


Acties:
  • 0 Henk 'm!

  • HollowGamer
  • Registratie: Februari 2009
  • Niet online
Ik snap je voorbeeld niet. Je kunt die toch voor je loop opvangen in een variabel? Dan hoef je hem maar een keer op te vragen.

Of wil je juist parameters meegeven?

Acties:
  • 0 Henk 'm!

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
The Eagle schreef op dinsdag 17 december 2019 @ 13:40:
Redis gebruiken betekent een extra component, dus theoretisch heb je sowieso een stukje extra legacy tov native in de code en dus in memory houden.
Having said that: als je wilt parallelliseren ontkom je er niet aan statefull te werken. En het is juist redis wat heel handig is om snel meerdere states bij te houden. Dat wordt wat lastig met globale variabelen. En bovendien schaalt dat voor geen meter horizontaal.
Wat bedoel je met legacy? (of bedoel je latency?).

De informatie in Redis wijzigt zeer summier, het is vooral een storage locatie om mysql te ontlasten bij veel dezelfde queries.
De informatie wordt echter wel met hoge regelmaat opgevraagd in dezelfde sessie (een paar 1000x wellicht), dit komt zelden voor echter (4x per dag ofzo).
HollowGamer schreef op dinsdag 17 december 2019 @ 13:53:
Ik snap je voorbeeld niet. Je kunt die toch voor je loop opvangen in een variabel? Dan hoef je hem maar een keer op te vragen.

Of wil je juist parameters meegeven?
Dat is het punt, waar sla je die variable op. In een global var of houd je het in Redis.

Acties:
  • +1 Henk 'm!

  • Stoppel
  • Registratie: Januari 2006
  • Laatst online: 01-10 18:23

Stoppel

een diedudabist

Daarnaast moet je je misschien afvragen of je uberhaupt wel variabelen in de global namespace zou willen opslaan.

edit:
Waarom zou je die var in _GLOBAL willen opslaan? Is je vraag niet eerder of je its "in memory" vs "redis" zou willen opslaan?

Je kan een variabele namelijk ook gewoon in een class zetten en publiek toegankelijk maken, het nut van _GLOBAL is mij niet echt duidelijk in je vraagstuk.

Als je met meerdere workers werkt met containers maar de state moet wel over de verschillende containers beschikbaar zijn dan ontkom je niet aan iets als Redis (bijv caching) maar inMemory zal altijd sneller zijn dan een externe service imho

[ Voor 70% gewijzigd door Stoppel op 17-12-2019 16:30 ]

Beauty is in the eye of the beholder


Acties:
  • +1 Henk 'm!

  • kaesve
  • Registratie: Maart 2009
  • Laatst online: 16-05 03:04
Bender schreef op dinsdag 17 december 2019 @ 14:19:

[...]


Dat is het punt, waar sla je die variable op. In een global var of houd je het in Redis.
Waarm zijn dat je enige twee opties? Je kan prima dit schrijven:

code:
1
2
3
4
$henk = tweakers::henk();
for ($i = 1; $i <= 100; $i++) {
   $henk; // Ik neem aan dat je hier nog iets wil doen
}


Geen globale variabelen, maar ook niet 100x uit Redis opvragen.

Acties:
  • 0 Henk 'm!

  • deCube
  • Registratie: Mei 2006
  • Laatst online: 24-09 10:33
HollowGamer schreef op dinsdag 17 december 2019 @ 13:53:
Ik snap je voorbeeld niet. Je kunt die toch voor je loop opvangen in een variabel? Dan hoef je hem maar een keer op te vragen.

Of wil je juist parameters meegeven?
Zoiets zou ik met de huidige context ook doen:
PHP:
1
2
3
4
5
6
7
8
9
class tweaker {
   private static $henk;
   static function henk() {
      if (null === self::$henk) {
         self::$henk = $redis->get('henk');
      }
      return self::$henk;
   }
}

Work hard & be brave.


Acties:
  • 0 Henk 'm!

  • HollowGamer
  • Registratie: Februari 2009
  • Niet online
deCube schreef op dinsdag 17 december 2019 @ 16:33:
[...]


Zoiets zou ik met de huidige context ook doen:
PHP:
1
2
3
4
5
6
7
8
9
class tweaker {
   private static $henk;
   static function henk() {
      if (null === self::$henk) {
         self::$henk = $redis->get('henk');
      }
      return self::$henk;
   }
}
Ik snap hem nog niet. Tevens ben ik niet zo fan van getters en setters in één call. Beter zet je die in bijvoorbeeld setHenk(..) en getHenk().

[ Voor 3% gewijzigd door HollowGamer op 18-12-2019 12:38 ]


Acties:
  • 0 Henk 'm!

  • Josk79
  • Registratie: September 2013
  • Laatst online: 12:23
In bovenstaand voorbeeld is geen setter. Dit is een vrij gangbare manier van eenmalige initialisatie.

Acties:
  • 0 Henk 'm!

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
kaesve schreef op dinsdag 17 december 2019 @ 16:32:
[...]


Waarm zijn dat je enige twee opties? Je kan prima dit schrijven:

code:
1
2
3
4
$henk = tweakers::henk();
for ($i = 1; $i <= 100; $i++) {
   $henk; // Ik neem aan dat je hier nog iets wil doen
}


Geen globale variabelen, maar ook niet 100x uit Redis opvragen.
Dat snap ik.
Maar het punt is dat het vaak opgevraagd wordt, nu is het een loop, maar kunnen ook 100 methods zijn.
Het gaat dus niet om een for, maar om het vaak veelvuldig opvragen van informatie uit redis.

Acties:
  • +1 Henk 'm!

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 23-09 14:00
Bender schreef op dinsdag 17 december 2019 @ 18:59:
[...]


Dat snap ik.
Maar het punt is dat het vaak opgevraagd wordt, nu is het een loop, maar kunnen ook 100 methods zijn.
Het gaat dus niet om een for, maar om het vaak veelvuldig opvragen van informatie uit redis.
En wat is daarbij het probleem? Informatie ophalen uit redis is normaliter super snel. Het in een global of static variabele stoppen helpt daarbij niet, want dat geld niet bij de volgende page request (hetzij zelfde user, hetzij een andere). De oplossing van @kaesve is het beste: cachen wanneer je het meerdere keren achter elkaar nodig hebt, en dus ook dezelfde waarde wilt.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Bender schreef op dinsdag 17 december 2019 @ 18:59:
[...]


Dat snap ik.
Maar het punt is dat het vaak opgevraagd wordt, nu is het een loop, maar kunnen ook 100 methods zijn.
Het gaat dus niet om een for, maar om het vaak veelvuldig opvragen van informatie uit redis.
Het is nogal afhankelijk van je use case. Het is nogal logisch dat het langzamer is om het elke keer uit redis te halen dan puur uit het geheugen van je eigen proces.

De vraag is vooral of de waarde ondertussen veranderd kan zijn door een ander proces en of je die wijziging wil observeren, of dat je binnen de context juist wil dat alle bewerkingen op dezelfde waarde gedaan worden.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • +1 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Bender schreef op dinsdag 17 december 2019 @ 13:30:
Ik vraag me af of het aan performance iets uitmaakt hoe vaak je de request doet naar Redis, of het toch echt in een globale variable op moet slaan.
Opslaan in een variabele is bijna altijd beter (maar niet in $GLOBALS maar gewoon een normale). Als we tienduizenden requests per server afhandelen, dan is het toch belangrijk om dit soort onnodige calls te vermijden, ook al duren ze minder dan een milliseconde. Want 50.000 of 500.000 calls per seconde naar redis maakt wel echt een verschil.

Echter, met php gaat dat sowieso niet het geval zijn dat je zoveel requests afhandelt, dus waarschijnlijk ga je het niet zo snel merken. Performance van 10 redis calls is niet echt een argument als je al in scripttaal als php bezig bent, dat kost normaal minder dan 0.01 seconde en merk je dus niet. Dan is het belangrijker wat Woy zegt: je wil waarschijnlijk niet dat je op een pagina verschillende waardes gebruikt, dus daarom wil je dit in een variabele opslaan.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 12:59

The Eagle

I wear my sunglasses at night

Bender schreef op dinsdag 17 december 2019 @ 14:19:
[...]


Wat bedoel je met legacy? (of bedoel je latency?).

De informatie in Redis wijzigt zeer summier, het is vooral een storage locatie om mysql te ontlasten bij veel dezelfde queries.
De informatie wordt echter wel met hoge regelmaat opgevraagd in dezelfde sessie (een paar 1000x wellicht), dit komt zelden voor echter (4x per dag ofzo).


[...]


Dat is het punt, waar sla je die variable op. In een global var of houd je het in Redis.
Ik bedoelde idd latency :)
En Redis is gewoon een key-value store. Als jij veel de zelfde queries op de zelfde informatie hebt in een DB, dan zou ik DB wise meer cachen of mijn programmatuur eens nalopen. Desnoods een view op die data, die blijven in het geheugen staan. Maar dikke kans dat een PHP programmeur daar totaal niet over nadenkt, die ziet gewoon een DB backend. En als die te traag is spin je zo redis op. Ja, zo kan het idd ook.

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)


Acties:
  • 0 Henk 'm!

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
pedorus schreef op dinsdag 17 december 2019 @ 22:17:
[...]
Opslaan in een variabele is bijna altijd beter (maar niet in $GLOBALS maar gewoon een normale).
Dat vond ik ook het meest logisch, maar de variable bestaat alleen in een class en is niet global. En daar ontstaat eigenlijk het probleem (wellicht had ik daar duidelijker in moeten zijn).
(een class die in een andere class weer opgeroepen wordt)

Handig om te weten wellicht, het zal niet door bezoekers gebruikt worden van een website maar is een achtergrond taak (zonder webserver) die een product feed opbouwen. Het gaat dus niet alleen om optimale performance maar ook stukje onderhoudbaarheid.
The Eagle schreef op dinsdag 17 december 2019 @ 22:37:
[...]

Ik bedoelde idd latency :)
En Redis is gewoon een key-value store. Als jij veel de zelfde queries op de zelfde informatie hebt in een DB, dan zou ik DB wise meer cachen of mijn programmatuur eens nalopen. Desnoods een view op die data, die blijven in het geheugen staan. Maar dikke kans dat een PHP programmeur daar totaal niet over nadenkt, die ziet gewoon een DB backend. En als die te traag is spin je zo redis op. Ja, zo kan het idd ook.
Redis wordt gebruikt voor de Cache juist, of begrijp ik je punt niet goed.
De kans dat tussentijds de informatie wijzigt is klein, mocht het gebeuren is het acceptabel als er verschil in zou zitten.

Acties:
  • +1 Henk 'm!

  • deCube
  • Registratie: Mei 2006
  • Laatst online: 24-09 10:33
Bender schreef op woensdag 18 december 2019 @ 10:25:
[...]


Dat vond ik ook het meest logisch, maar de variable bestaat alleen in een class en is niet global. En daar ontstaat eigenlijk het probleem (wellicht had ik daar duidelijker in moeten zijn).
(een class die in een andere class weer opgeroepen wordt)
Heb je geen dependency injection container o.i.d.?
[...]


Redis wordt gebruikt voor de Cache juist, of begrijp ik je punt niet goed.
De kans dat tussentijds de informatie wijzigt is klein, mocht het gebeuren is het acceptabel als er verschil in zou zitten.
Redis is een key-value storage, vaak toegepast in cache maar ook bv. om sessies en andere informatie in een stateless omgeving (bv. als een applicatie op meerdere webservers draait) op te slaan.

Work hard & be brave.


Acties:
  • 0 Henk 'm!

  • HollowGamer
  • Registratie: Februari 2009
  • Niet online
Bender schreef op woensdag 18 december 2019 @ 10:25:
[...]


Dat vond ik ook het meest logisch, maar de variable bestaat alleen in een class en is niet global. En daar ontstaat eigenlijk het probleem (wellicht had ik daar duidelijker in moeten zijn).
(een class die in een andere class weer opgeroepen wordt)

Handig om te weten wellicht, het zal niet door bezoekers gebruikt worden van een website maar is een achtergrond taak (zonder webserver) die een product feed opbouwen. Het gaat dus niet alleen om optimale performance maar ook stukje onderhoudbaarheid.


[...]


Redis wordt gebruikt voor de Cache juist, of begrijp ik je punt niet goed.
De kans dat tussentijds de informatie wijzigt is klein, mocht het gebeuren is het acceptabel als er verschil in zou zitten.
Ik snap nog steeds het probleem/de vraag niet. :?

Wat heeft Redis precies met onderhoud te maken? Verder mag een achtergrond taak in mijn ogen iets minder aan caching doen, het gebeurt zoals gezegd op de achtergrond en meestal wil je 'verse' data of enkel uit de cache halen als die toch niet veranderd.

En wat bedoel je met een class die een andere class aanroept? Dat is toch vrij normaal allemaal.

Gebruik je overigens een framework?

[ Voor 4% gewijzigd door HollowGamer op 18-12-2019 12:44 ]


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Bender schreef op woensdag 18 december 2019 @ 10:25:
[...]
Handig om te weten wellicht, het zal niet door bezoekers gebruikt worden van een website maar is een achtergrond taak (zonder webserver) die een product feed opbouwen. Het gaat dus niet alleen om optimale performance maar ook stukje onderhoudbaarheid.
Dan zou ik zelf (net naargelang de achtergrond taak aangeroepen wordt en de data vers moet zijn) een 3-traps raket opbouwen :
- Een variabele binnen je taak (dus niet een globale variabele) die je 1x vult bij het beginnen van de taak vanuit redis
- Een redis - caching voor je sql-caching
- Als redis null is dan sql pakken.

Dan is hij dus 1x per dag echt traag, als hij vanuit sql moet komen. Daarna is hij nog per run 1x "traag" omdat redis gewoon network latency etc heeft. Daarna is alles as fast as possible doordat je een lokale variabele hebt die je gewoon 100.000x kunt uitlezen.
[...]
Redis wordt gebruikt voor de Cache juist, of begrijp ik je punt niet goed.
Redis is leuk en snel, maar als jij 1.000.000 calls doet naar redis die elke keer antwoord binnen 0,01 ms dan praat je alsnog over 10 seconden wachttijd, het is sneller dan 1.000.000 db-calls maar niet zo snel als 1.000.000 in memory calls.

Redis is simpelweg niet een gratis cache, al kan het wel zo lijken als je slechts 1.000 calls doet, het beste advies blijft gewoon meten=weten want het hangt van te veel dingen af om een algemeen advies te geven.
Bij 1 miljoen calls oid zou ik altijd gaan voor local var, maar bij 1.000 kan ik voor de onderhoudbaarheid weer kiezen om alles vanuit redis te lezen. Het is theoretisch trager, maar praktisch is het simpelweg 1 laag minder.

  • Xalephsis
  • Registratie: Augustus 2009
  • Laatst online: 28-05 15:40
Stel je niet ook eigenlijk de verkeerde vraag? Je vraagt of iets sneller is vanuit variabele of vanuit Redis, waar het antwoord altijd variabele zal zijn. Maar wat je eigenlijk wil weten is wat is een efficiënte manier om je data tijdelijk in bij te houden, in welk geval Redis een prima oplossing is.

Je kunt dat prima afvangen door daar je eigen repository voor te schrijven, die handelt de implementatie af en geeft je altijd de data terug. Of het nou in cache staat of niet, dan voert ie gewoon de SQL uit, slaat het op in de cache store en geeft alsnog je data terug.

  • Bender
  • Registratie: Augustus 2000
  • Laatst online: 02-10 11:51
Wellicht is het de verkeerde vraag die ik stelde, tijdens de reactie gaf het ook nieuwe inzichten en ideeën op basis van andermans suggesties.

Predis werd gebruikt, maar uiteraard ge-extend.

Nu is het bij bepaalde requests zo dat ik weet welke veel voor gaan komen, dat maakt het makkelijk. Hierin heb ik een mogelijkheid toegevoegd om per key mee te geven of deze in de sessie gecached mogen worden en dat lijkt goed te werken.


Wellicht een bonus;
Vorige week aanpassing doorgevoerd dat bij (bekende) grote values de value gecomprimeerd opgeslagen wordt, deze moet uiteraard wel uitgepakt worden maar de impact van CPU lijkt zeer beperkt maar het gebruikte geheugen werd gehalveerd.
Pagina: 1