ThinkPHP implements several ways to count online users

About the function of counting online users. I have done it before, using some relatively simple methods, but the shortcomings are also obvious: a balance must be made between accurate statistics and server and database pressure.
So I want to find a method that can calculate accurate statistics without taking up too many server resources. Let's talk about some common practices first:

One, update its online time every time the user operates

This method is very straightforward. Add a field update_time to the user table. Every time the user performs an operation, this field is updated to the current time. Generally, this operation is written in a base class inherited by all Actions.
Then define an expiration time, such as 10 minutes, which means that users who have not performed any operations for 10 minutes are offline by default. In this way, the sql statement to count the current online users is probably like this

select count(*)from think_user where update_time>now()-10*60

Advantages: simple to implement and easy to understand
Disadvantages: 1. The definition of "online" is ambiguous. If the user reads an article for a long time and does not perform any operation within 10 minutes, he will be ignored; 2. If the user table The amount of data is very large, the efficiency will be extremely poor

Second, put online users into a table separately

Improvements to method one. Create a new table think_inline, the fields include user_id and update_time. Each time a user operates, first determine whether there is a record of the user in the table, if not, add a new one, and update update_time if there is.
And at the same time add the operation of deleting invalid data

deletefrom think_inline where update_time

In this way, the statistics online can directly count this table. And the amount of data in this table will not be very large (at least much smaller than the user table)
Advantages: reduce database pressure
Disadvantages: still the definition of "online" is not accurate

Third, use JS timer

This method is a combination of one and two. Create a new table think_inline, and define the update time for each user operation in the base class, refer to the second practice.
The difference is that in each html template, add a js timer, setInterval('updateTime', 10*3600); send an ajax request every 10 minutes to update the update_time field. In this way, even if the user stays on a page for too long, it will not be mistaken for being offline. And you can increase the accuracy by reducing the request interval. Of course, the pressure on the server is even greater.
Advantages: The judgment of online is more accurate
. Disadvantages: It is still not accurate without increasing server pressure, and a trade-off must be made between the two.

Fourth, use TP's SessionDb driver for optimal design

This is the method that some people say on the Internet to store the session into the database. This method has many advantages. The specific approach is. . .

1. Why should the session be stored in the database?

A session is a set of temporary data stored on the server. Under normal circumstances, when we do user login, we will store user data in the session. In this way, it can be easily called on any page, and each client will generate a unique session_id, so there will be no confusion. And after closing the browser, the server will have a session recovery mechanism to automatically delete expired sessions.
This is the advantage of session: uniqueness, easy to call, and will not occupy too many resources. But there are also disadvantages: it is stored in cookies on the client side, and disabling cookies is useless.
So, how does the server store the session? He saves the session as a file on the hard disk by default. However, for our code farmers, operating the database is much more convenient than reading files, and can perform various operations on session data.
And counting the number of online users is achieved by counting how many session records there are.
2. How to store the session in the database?

TP's SessionDb driver implements this function. The principle is to achieve by rewriting PHP's default session operation, the core function session_set_save_handler(), if you are interested, you can study it. The driver puts session additions, reads, reads, and deletions into the database.
The method of use is also very simple:

1. Create a table, just run the sql statement in the driver's comment.
2. Add the configuration:

//Session configuration 'SESSION_TYPE' => 'db' , //database storage session 'SESSION_TABLE' => 'think_session' , //session table 'SESSION_EXPIRE' => 600 , //session expiration time

In this way, as long as we use the session() function in the program, there will be records in the database.

3. Use the database session to realize the statistics of online users
1 and the total number of online users

$map = array('session_expire'=>array('gt',NOW_TIME));$inline = D('Session')->where($map)->count();

2. Count the number of tourists (not logged in)

$map = array('session_expire'=>array('gt',NOW_TIME),'session_data'=>array('eq',''));$huiyuan = D('Session')->where($map)->count();

3. Count the number of members (logged in)

$map = array('session_expire'=>array('gt',NOW_TIME),'session_data'=>array('neq',''));$huiyuan = D('Session')->where($map)->count();

4. Determine whether a user is online.
Add a new field to the user table: session_id.
(1) In the login operation, save the session_id of the user,

$session_id = session_id();D('User')->where(array('id'=>$user_id))->save('session_id'=>$session_id);

(2) Check whether the session_id exists in the session table, has not expired and has a value,

$map = array ( 'session_id' => $session_id , 'session_expire' => array ( 'gt' , NOW_TIME ), 'session_data' => array ( 'neq' , '' )); $res = D ( 'Session ' )-> where ( $map )-> find (); if ( $res ){ dump ( 'The user is online.' )} else { dump ( 'The user is not online.')}

The code word is too troublesome, so write so much first, and then summarize the advantages and precautions of this method.

4. Summary
1. Implementation steps: add a new field in the user table to save session_id; use TP's SessionDb driver. Is not it simple?
2. Advantages:
(1) Compared with the above three methods, the pressure on the database and the server is less, and the operation is simple
(2) It can distinguish whether the online user is a member or a tourist (whether the session_data field has a value), and discuz does this
(3) You can delete a user's session record to achieve the function of "kicking off the line".
3. Disadvantages:
(1) It is still not possible to accurately count the number of people online in XX seconds.
4. Notes:
(1) Due to The SessionDb driver of this method must use the session() function to trigger, so it must be configured to automatically open the session (the default is open). TP will use the session() function in the execution process, so if you don't write anything, the session data will also be stored in the database.
(2) Because the session data of the database will not be deleted by itself, for expired data, the session() method must be called to delete it.
This also means that if no one visits your website, the expired session records in the database will always exist.
That is, due to this mechanism, for some emergencies (the user directly X the browser, directly shuts down, an earthquake...), after the browser is closed for a period of time (session expiration time), other users' access to the website will It will trigger session recycling and delete expired records. Therefore, there is no fear of inaccurate statistics.
Of course, even if no one visits, you can add session_expire>time() to count to count.

But there are also errors, that is, the session expiration time, which expires after 5 minutes, there is a 5-minute error. The smaller the time is, the more frequent operations are to the database; the larger the time, the lower the accuracy.
(3) This session expiration time means that if the user does not perform any operation within 5 minutes, it will automatically log out. Therefore, for a good user experience, please add the cookie automatic login function. The current website does just that.
(4) Someone mentioned in the comments that the verification code will also be stored in the session, so when we judge, we cannot count the valuable records.
It is necessary to obtain valuable data first, and then determine whether there is a parameter name for saving user information in it. Although the session_data field is stored in binary, the query is a string.
For example, we use the user subscript to save the user information,

session ( 'user' , $data ); //User login information //Get the real number of members //Query session records with value $list = D ( 'Session' )-> where ( array ( 'session_data' => array ( 'NEQ' , '' ), 'session_expire' => array ( 'lt' , NOW_TIME )))-> select (); //Determine whether there is a member ID in the value foreach ( $list as $k =>$value){if(strpos( $value [ 'session_data' ], 'user' ) === false ){ $count ++; } dump ( $count ); //real number of members }

(5) Since each browser has its own session mechanism, if a person opens 5 browsers at the same time on a computer, the database will save 5 different records.
When actually using it, you still need to consider searching. engine error. When it crawls our page, it also generates a session.
V. Final conclusion

Due to the limitations of the HTTP protocol: the connection to the client is disconnected after the request is completed. So actually,

We simply cannot accurately and real-time count the number of people online

! Although there are various ways to increase statistical precision, they are all temporary solutions. Only by abandoning the HTTP protocol and using the "long connection" link method can we accurately determine whether the user is in or away.

Keywords : ThinkPHP, online statistics, SESSION storage table

Original link: http://wbloc.com/index.php/article-50.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324812110&siteId=291194637