Karl_T

SessionHandlerDBRedis

15 posts in this topic

Greetings. I am here to share my first module. I make this module because I cannot find one to suit my need. I like SessionHandlerDB but I do not want to use mysql database to store session for performance. So, Redis seems to be the best choice. I have tried to use netcarver's SessionHandlerRedis but it lacks something I need, those are the active session checking and the easy module configuration while I do borrow some code from it (thanks to netcarver). So I take this chance to merge them together to form a new module. I am new to use github and I don't know if it is appropriate to publish another similar project, or fork from them. 

You may grab this from Github: SessionHandlerDBRedis

I hope this could give somebody a help.

 

Caution before use: this module lacks support for session lock. It will be implemented for the next update.

 

Updated to v0.3

changelog: 

v0.3 - added ability to get forwarded IP instead of normal remote IP. 

6 people like this

Share this post


Link to post
Share on other sites

Thanks for posting Karl.

I think it would be best to fork the project and commit your changes. This way there will be only one Redis session handler database but with two developers. @netcarver is a really nice guy, so I think you guys can work this out :)

Share this post


Link to post
Share on other sites

@arjen Thanks for your suggestion. Hopefully my publish does not cause much issue here. Sorry if I have violated something. I wondered if it is appropriate to fork a project with 90% code changed or instead fork to SessionHandlerDB with more similarity. I will try to fork SessionHandlerRedis later. Hope that netcarver is still interested in this module. ^_^

Share this post


Link to post
Share on other sites

No issues here :)

But since the amount of modules is (luckily) pretty small in ProcessWire I guess it would be wise to join forces instead of creating several modules with overlap. If 90% of the code is changed, I'm not really sure if a fork is appropriate, but it might be. I guess we have to wait until @netcarver joins the discussion.

2 people like this

Share this post


Link to post
Share on other sites

My module was very experimental. Very happy for it to have a successor ^-^

2 people like this

Share this post


Link to post
Share on other sites
8 hours ago, netcarver said:

My module was very experimental. Very happy for it to have a successor ^-^

Thanks netcarver, I will try to make a pr on it. ^_^

I do think using Redis as the session handler has many advantages such as reduce work load for mysql(if you are using it to store sessions) and performance boot(fastest way at the moment?). I experienced a faster page load after using it, no thorough experiment anyway lol. So, I am surprised that no much dev is interested in this(no reply in the SessionHandlerRedis post last two years!?). I wonder if I missed some drawbacks or this tech is already outdated.:undecided:

1 person likes this

Share this post


Link to post
Share on other sites

Redis is often not available in shared hosting environments and we have lots of users, where this kind of tech / performance gain doesn't make a real difference. It's certainly a really nice to have module, but it always depends on the use-case.

Share this post


Link to post
Share on other sites
7 minutes ago, LostKobrakai said:

Redis is often not available in shared hosting environments and we have lots of users, where this kind of tech / performance gain doesn't make a real difference. It's certainly a really nice to have module, but it always depends on the use-case.

Thanks for your points. It indeed makes less difference for low traffic site where shared hosting is the common choice. I always use cheap VPS plan in DigitalOcean or Linode to gain the largest control for less money so I forgot about shared hosting for long.:P.

2 people like this

Share this post


Link to post
Share on other sites

@Karl_T It's great of what you have done. I can feel your excitement about using Redis. 

Haven't had the chance to dig deeper into your code but of what I saw, you are not using session lock. Forgive me if I am wrong.

I was using phpredis (the php extension) as a global session handler replacement in php.ini , but it lacks support for session lock. I was having trouble because of this and I wrote my own solution attached here. I just prepend it.

When using session with files - the files system have lock on write. When using SessionDB - the database has a row or table lock depending on the table engine. Memcache have lock implemented and it's suitable for replacement in php.ini. Of what I saw in the phpredis code, there is no lock and have to be implemented externally. 

  • My issue because of this here.
  • This guy here explained more about the session lock and session fixation.
  • Here is the related issue/feature request at GitHub/phpredis. 
  • Magento's dev opinion here .

Also many recommend igbinary as a php serializer of the session data before to be stored in Redis. Of course, it is not installed by default on a shared hosting. Just as a reminder, there were many ways to decrease the memory usage. Some prefer using "strings" instead of "hashes" as a datatype if not using millions of sessions and shortened keys for memory optimization. 

Also, just saw a cron job deleting the expired keys. Redis have native key removal for the expired keys and there is no reason for garbage collector or a cron job to delete the old keys. Sorry if I am wrong about your code. I am keen to test it in the morning. 

Hope this helps. Peace!

session_handler_redis.php

test_serializers.php

5 people like this

Share this post


Link to post
Share on other sites

@seddass Thanks for your great lesson. I have really learnt a lot! I lack the knowledge and sense to find out the potential threats. And, I should have made it clear about the existence of any open issues affecting the usage before using a library. I will dig deeper and try to resolve the issue. Your attached code would be a great help for this.:lol:

11 hours ago, seddass said:

Some prefer using "strings" instead of "hashes" as a datatype if not using millions of sessions and shortened keys for memory optimization. 

I was using string as datatype originally. Hash is used because it is the only way I found that can let me to do calculation like finding recent active session using timestamp by ZADD.

11 hours ago, seddass said:

Also, just saw a cron job deleting the expired keys. Redis have native key removal for the expired keys and there is no reason for garbage collector or a cron job to delete the old keys.

Thanks for poitning this out. I overlooked this one.

 

3 people like this

Share this post


Link to post
Share on other sites

@Karl_T Glad to save your time. If we join forces we can create a great Redis Sess Handler for PW. Hope @netcarver will help too. 

Quote

Hash is used because it is the only way I found that can let me to do calculation like finding recent active session using timestamp by ZADD.

If it's just occasionally, I would try with strings using TTL (or PTTL) to get their expire time and to sort all the keys in php array. BTW never played with TTL till now. It has to be tested with a lot of sessions. 

The next feature will be to provide connection support for local socket and to multiple Redis servers with priority and auth.

My experience with Redis started when I find out session_id() took 12 seconds because of many sess files. 

2 people like this

Share this post


Link to post
Share on other sites

@seddass, @Karl_T

I'm a little out of the loop regarding Redis, at the moment, but I like the idea of collaborating on this. As I have the original repo on github, how about I add you both as collaborators, and we can make this a more community oriented effort?

7 people like this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   1 member

  • Similar Content

    • By Slav
      Hey Guys! Im new to PW and am working on a website built on PW. Im trying to understand how sessions work in PW. Specifically what exactly is happening when session expires. The thing is that my client wants to be redirected to homepage whenever session expires, so basically he doesnt want to be redirected to admin login page when he's in the admin environment of PW(he doesnt want his clients to see the admin login page for whatever reason). Is it possible to hook to the session expiration and redirect to a specific url? And what is the correct way to do it in PW?
      I would appreciate the help!
      Cheers!
    • By Dennis Spohr
      Hi all,
      I have problems to keep my session on different subdomains (including www).
      I've set the following config:
      $config->sessionCookieDomain = '.mydomain.net'; $config->sessionCookieSecure = false; But it doesn't work, I always loose the session when I switch between www.mydomain.net and example.mydomain.net.
      Could it be because both of them have a different SSL-Certificate? (https)
      Thanks for any help!
      Dennis
    • By martind
      hi,
      i have a login form on my page which is handled within a template called by ajax. Login works fine, but only if the site doesn't get reloaded - which isn't the intention but may occur. So is there a way to manually reset the session data from within my form-handler template after successfully calling $session->login($username, $password), to have it working after a page reload?
      thanks, martin
    • By Harmen
      Hi all,
       
      Currently I am working on a filter for all the products in a category. So I've set up a class and built a (PW) form in it. When the user clicks on continue the form should return a processform function which sets the variable of the form in a session. Later in the file I want to read out that session and use that variable to select which products should show up and which should be hidden. So now with code examples to make it a bit more clear for you:
       
      In my file I start with a class:
      class classname { public function ShowForm() { $form = $this->Form1(); if ($this->input->post->submit) { if ($this->processForm1($form)) $this->session->redirect("./"); } return $form->render(); } Then a form inside the class:
      protected function Form1() { $form = wire('modules')->get("InputfieldForm"); $form->description = "Fill in the fields to find the mouse which fits your wishes"; $form->label = "Mouse Selector"; $form->action = "./"; $form->method = 'post'; $f = wire('modules')->get("InputfieldRadios"); $f->name = "Hand"; $f->label = "label"; $f->addOption(1, "1"); $f->addOption(2, "2"); $form->add($f); $this->addSubmit($form, 'Continue'); return $form; } This function is called when the user submits:
      protected function ProcessForm1($form) { $form->processInput($this->input->post); $this->session->hand = (int)$form->get("Hand")->value; } As you see I store the variable of the submitted form in a session. After closing the class I continue with building the page and then I want to read out that variable:
      $value = $this->session->hand; $content .= "Value of 'Hand': " . $value; But when I execute this on my website I cannot see the value of the form. Have I done something wrong or how can I fix this?
      Thanks in advance,
      ~Harmen
    • By Doc
      Hello,
      When do you choose to use $input->whitelist($key, $value) rather than $session->myvar (with myvar = 3 for example) ?
      The documentation uses the example of the MarkupPagerNav module :
      "An example is the MarkupPagerNav plugin module, which provides an easy way for you to have pagination. Lets say that you used it to paginate search engine results. [...]" (from https://processwire.com/api/variables/input/)
      But If I don't have pagination, but some variables to store for each member of my website, do I have any interest to store them with whitelist rather than within sessions ? 
      Thanks