who's online with timestamp with high performance - php

i just created a user login system with php session and now users can register and login to site and do another things...
now i want to create online.php which will fetch all online users.i almost search everything in google and stackoverflow for this with no success.
ok now i want to describe the system which i want to create with high performance..
when a user logged in we just update table user.lastlogin which is a timestamp and then in online.php we SELECT * every user where time interval is < 5 minutes.
for this purpose i can update this timestamp lastlogin field in database when user load each page,and this cost many mysql query to do the job... then in each page load i have to update
UPDATE user set last=now()
that will cost me many mysql query.now i am looking for some another way like using sessions or something that i found in this link
"The normal solution is to store a timestamp in the table which you update every time the user does something. Users with a recent timestamp (say, five minutes) are shown as logged in, everybody else are logged out.
It doesn't even have to be updated on every page load. Keep a timestamp in the session with the last update time as well, and only update the table when the database flag are about to expire."
but unfortunately the answer wasnt quite helpful and i need an example or more describe on this.

1.) If you need more speed in sessions there is for example memcache. A simple key - value store to save your sessions or keys. You can configure Apache that all sessions will be automaticly stored in memcache.
2.) Another solution is to make a MEMORY Table which MySQL holds in RAM. Problem is when you restart your server the data in this table is lost. But i think in your case for last logon there is no problem.
3.) PHP Shared Memory: http://php.net/manual/de/ref.shmop.php for small data.
When you have implemented a solution i would prefer the MEMORY Table or the SHM solution.
Edit: The last paragraph with the searching on HDD was related to the comment on top: Find Number of Open Sessions

Related

Kohana Session Table

Currently i am hosting a website with ~10k unique visitors a day and ~6 clicks per user.
So round about 60k pageviews a day.
I use Kohana 3.2 and save the session datas from every user in the "sessions" table. Every page request execute a timestamp refresh in this table! So it's round about 60k updates (excl. Selects / Inserts / .. ) refreshing timestamps only.
The mysql process is getting pretty low..
So that's my question:
Should i stop using the SESSIONS table for saving user
How can i use the $_SESSION instead the values from the table?
Is there another alternative to handle this problem right now? We orderd more server capacity but have to wait..
EDIT:
Maybe it's enough to deny all these "updates" by every click..?
Okay. At least it was enough to truncate the table "sessions" - for the first moment. There was more than 1kk records - thats why the database operations getting pretty slow..?
Maybe it's just a simple mysql problem, and it's enough when i change it NOSQL.

PHP: how to update user logged in timer without using AJAX calls

I am creating a web application named Online Exam using PHP+MySQL and AngularJS. Now I am getting some trouble on project like changing the user looged in status. Let us take this condition as a example:
Suppose a authorized user/student successfully logged in online exam section(After successfully logged current time will be inserted in the db in exam_start_time column as unix timestamp format and exam_status will be set as 'ACTIVE`.
1hr(60 min) countdown timer is initialize for him/her as per the inserted exam_start_time in db.
Now suppose after 15 min the system shuts down automatically, then if user logged in again(In same system or other) then the countdown timer should be set for 45 minutes only.
Previously I was updating the last_activity_time in our table in every 10 sec(using ajax calls). but now I want to change this way, Is there any way like(socket or network programming using PHP) to update the column.
Here is my table structure which is managing user logged in status
Please give me some suggestions on it.
A Php socket server programming tutorial : http://www.christophh.net/2012/07/24/php-socket-programming/
Sockets, as Pascal Le Merrer mentioned, is IMO your best option. But beware of Apache! Every WebSocket holds one Apache thread, and Apache wasn't designed to do that. when too many (and by too many I mean few dozen) clients connect to your site, it will crash. (I've been there while trying to implement long polling/comet, ended up using NodeJS. If you're using nginx, it is more likely that it will become low on resources and effective, but there are also other ways. Take a look here:
Using WebSocket on Apache server
If you find this uncomfortable/hard to learn, try also another idea:
try to add hidden iFrame to your exam page, pointing to prepared site that updates database row. Use javascript to refresh this page every 10-15 seconds. Every refresh causes update of specific row in DB, using current date and time. It should work (not tested, but give it a try).

Undo in PHP CRUD application

What would be the best way to achieve an undo function in a PHP CRUD application? The only solution I've been able to come up with is using a sort of buffer table in my database that is periodically wiped.
If the user clicks the "Undo" button after deleting a record for example, the id of the last change will be passed to a handler which will pull the buffer record and reinstate it into the main table for that data type. If the "Undo" is not done in say, 4 or 5 minutes, a reaper script will drop the entry.
Does this sound feasible? Is there a better way of accomplishing this?
You could use a flag field in your database to mark a row for delete.
And you can setup task (crontab in linux) to delete all rows with delete flag set to true and time difference > to 5 mins.
I've learned to not delete anything, but simply do as Ignacio Ocampo stated by using a flag column in your DB such as status. By default set the status column to open. If your client clicks your delete button, just update that records status column to void, or deleted..
In doing this, you'll need to update your data request to pull only those records with the status column set to open. This allows the data to not be lost, but also not seen.
all undo(s) or redo(s) if applicable can reset the open status to - or + 1 record sorted by a timestamp column.
If db space is at a premium, and you need to remove old data then crontab does work, but I prefer the simplicity phpmyadmin conjob to loop a file that will wipe all void or deleted records older than time()-'(last cron run).
Depending on what and how you're building, you might also want to consider using one of the following solutions.
1) A pure PHP CRUD solution would be something along the lines you've mentioned, with also possibly storing cookies on the client side to track which actions are being done. Every action a new cookie is created, then your application will only have to sort the cookies by date and time. You could also set the cookies to be automatically expire after x amount of time. (Although I would expire after a x amount of steps, instead of time)
2) If you are able to use HTML5 local storage (http://www.w3schools.com/html/html5_webstorage.asp) along with some Javascript would be perfect for this, since you wouldn't have to wait around for the server to respond everytime 'undo' is clicked since all the processing would be handled locally.

Checking if user is online or not (updating activity time on each page visit)

So basically, I have a cronjob, that will check user database activity time, and if user has not done anything in last 10 minutes, it will automatically logout user and set it's status to offline.
Now about the hard part - On each user page visit, I'm doing an update to database, and inserting new activityTime, for example, if he visits homepage, database will automatically update, if he will go to users online page, again, the database will update e.c. That happens to all of users.
So the question is - is there any other, better solutions, or this is good enough solution for that?
Can it cause any troubles in long term, or will it reduce the website speed cause of too many db connections?
Hope you understood what I ment :)!
Basicly having sessions last 10 minutes, and send a simple UPDATE on each page load isn't a big deal. I can promise you that there are far more worse way to overload your database than this. For instance every time you need a value from the user, to extract it from the database every time instead of storing all the values through cookies or global values.
Don't worry about this approach since it will only require 1 more command per session. Some codes can run 25 unnecessary queries per page request without the programmer realizing it.
If you wish to have a number saying how many is online, simply run this through cron aswell:
$str_time = date('Y-m-d H:i:s', strtotime('-10 Minutes'));
$query = $this->db->query("
SELECT COUNT(*) AS online
FROM users
WHERE last_online >= ?
", array($str_time));
if ($query->num_rows())
$int_online = $query->row()->online;
else $int_online = 0;
// Save into database, .json file or whatever
If your site logins are session/cookie based, you can just set the session/cookie timeout to be 10 minutes, then update that timeout/expiration each time someone visits a new page. This method would be less intensive, but also not as secure as someone could modify the cookie.
I have done this in the past with good success.

Can I count sessions to determine number of people online?

I am confused about something. When I try to search how to count online users in PHP, all answers related with MySQL and many different ways.
In my script, any user that submits the login form creates a $_SESSION['$nickname']
So I thought, can I count login sessions with count($_SESSION['$nickname']); and show it in my page?
Or is this totally a wrong logic?
Totally wrong logic. $_SESSION is a per-user thing. One user's session is not shared with any other user's session. Think about it - an online bank written in PHP, all sharing a single $_SESSION - everyone would see everyone's account details.
Assuming you're on the standard PHP file-based sessions, you can count the session files in whatever directory they're stored, e.g.
$users = count(glob(session_save_path() . '/*'));
Note that this just counts session files - it will undoubtedly contain stale/dead sessions that haven't been garbage collected yet. If you want an actual "really is online right now", you'd have to parse each session file and examin its contents.
At first, you have to define what "to be online" means.
Should the user have clicked on a link within the last 5 minutes?
I assume that you already have a user table in your database.
So the simplest way is to add a new column, e.g. lastAction TIMESTAMP.
And when the user clicks on a link on your page, your script should update this value.
And on your statistics page or whatever, you get the number of online users with that code:
SELECT COUNT(*) FROM users WHERE lastAction > (NOW() - 60*5)
PHP is pretty flexible in terms of session storage, you can define your own session save/restore handlers.
However, the default session storage is files, where each session is individually stored to disk. Which means, that in order to find out how many users there are "online" (here, i assume "online = session exists with $_SESSION['$nickname'] set"), you would need to open all the session files stored on disk, and check how many unique nicknames exist within them. This is very heavy in both time and required resources.
Hence, most tutorials suggest counting this in the database, by maintaining a last-seen timestamp per user (and checking how many users were last seen in last X minutes).
If you wish to combine, that is doable via defining your own session save handler to store session information in the database...
Several additional notes on sessions:
Sessions are not destroyed immediately when closing a browser. In fact, the browser does not tell the server in any way that it is being closed. It means that the server should come up with some time-based algorithm to decide who's online and who is not.
Sessions are isolated from one another so $_SESSION["foo"] can not be shared by multiple different sessions - there is no equivalent to Global.asa in PHP. Not off the box.
This is the wrong logic and the session is only stored and immediately destroyed locally on the end user's PC, so it cannot be read from the server for any kind of confirmation without the user doing something. Server-side sessions are only destroyed on garbage cleanup.
Your best bet is to have a timestamp for each user which is updated whenever a user does anything. This means you will need to have this update triggered via JS/AJAX, PHP. Then you can check to see how many timestamps are within the last 5 minutes for example, and this would give you a rough idea of how many users are currently online.
You could also have a hidden iframe which continually refreshes every few seconds and updates the timestamp, or JS/AJAX which updates the timestamp every X seconds as well...

Categories