Now I do this: every time I load the page, I update the key " {$user->id}.online " in the {$user->id}.online for 5 minutes. If there is no key, the user is offline.

This method is good when you need to check a particular user by knowing his id . But how to get all users online? We have to load all users (for the time being, there are not many of them) and check " {$user->id}.online " for {$user->id}.online . It's horrible. Is there a better way?

  • If you use Memcached, you can get a list of keys. php.net/manual/ru/memcached.getallkeys.php - ilyaplot
  • Do you think this is the norm? - GroZa
  • and why throw a separate key in the cache, and not to store the ID array? - teran
  • @teran how to check online then? From this array id will be deleted? - GroZa
  • @GroZa need to think about the removal. I made a counter on .net using SignalR , look towards similar php solutions . there asynchronous requests to the server are sent from the client during connection / disconnect. As a result, it was possible to receive when a new person arrived, or the client moved to another page, or he ended the session. The data went in both directions. That is, when you change the number of people, all customers received a notification. - teran

3 answers 3

A variant with a record that contains a list of intended online users:

 $m = new Memcached(); $m->addServer('localhost', 11211); $now = time(); $life = 5 * 60; $m->set("{$user->id}.online", true, $life); if (($online_users = $m->get('online_users')) === false) { $online_users = array($user->id => $now); // нужно ли записывать время в значение элемента под вопросом // возможно хватит true или 1 } else { $online_users[$user->id] = $now; foreach ($online_users as $id => $time) { // ключи {$id}.online остаются для проверки if (false === $m->get("{$id}.online")) { unset($online_users[$id]); } else { // тут что-то делаем с юзером, который онлайн // $id содержит его номер // $time содержит время последней отметки оналайн } } } $m->set('online_users', $online_users, $life); // в переменной $online_users массив id (номера в ключах массива) юзеров онлайн 

PS Testing was not conducted. Benefits / losses were not calculated.

  • I thought about this option. But if 100 people go to the site at the same time, it turns out you need to write an array 100 times to online_users - to apply for the same key, then there will be some kind of blocking for writing to Memcached / Redis? I do not know whether this is normal or not. But the option is good) - GroZa

You can try to calculate using sessions.

For sessions, file storage is defined by default, where each session is individually stored on disk. This means that in order to find out how many users are online (I assume, "online = a set of existing $_SESSION['$nickname'] sessions), you will need to open all session files stored on the disk and check how many unique nicknam'ов exist inside sessions.

It should be borne in mind that:

  • Sessions are not destroyed immediately upon closing the browser. This means that the server must come up with some kind of time-based algorithm to decide who is online and who is not.
  • Sessions are isolated from each other so that $_SESSION["test1"] cannot be shared by several other sessions.
  • I think this option is worse than mine now. - GroZa
  • And it may also be that the session files are not deleted at all :) And until the server starts to issue an error about the lack of disk space, no one knows about it. - Visman

The label in the database with two fields

 CREATE TABLE users{ user_id INT, last_login TIMESTAMP, PRIMARY KEY(user_id) } 

When a user logs in

 INSERT INTO users (user_id, last_login) values ($id, NOW()) ON DUPLICATE KEY UPDATE last_login=NOW(); 

Accordingly, the number of "active"

 SELECT COUNT(*) FROM users WHERE NOW() - last_login<$desired_timeout 
  • It is slow to add an entry to the database for each page load. - GroZa
  • @GroZa To say this, you must at least check it out first. What are your expected loads? If we are talking about the order of 10 people per second, then it makes sense to look at the delay in communicating with the database, if it is less (and judging by the timeout of 5 minutes, this is so), then I beg you. - rjhdby
  • I do not need to try to understand that using the cache in memory is much faster than making SQL queries. I want to make a universal decision, but not "up to 10 people per second use the database, but after 50 it will be necessary to redo everything" - GroZa
  • one
    @GroZa I see mutually exclusive paragraphs. If you need a universal solution, then this is just a DB, and not crutches with a cache, which tends to be cleaned for example. If you want direct cosmic velocities, then look at the in-memory database solutions. The whole hayload somehow lives with the bases and does not complain, and you have the buttons of the wrong color. - rjhdby
  • "The whole hayload somehow lives with the bases and doesn’t complain" - will there be a proof of "INSERT INTO users ..." at each request in the hayload project? - GroZa