简体   繁体   English

将数据存储到会话中并在“主要”操作时存储到数据库

[英]Storing data into session and storing to database upon “major” action

I know there are hundreds of these questions but what I am asking however is slightly different. 我知道有数百个问题,但我要问的是略有不同。

When the user logs in I would like to get all their data from each table in a database and store it in a session variable (obviously not sensative data such as encrypted password/salts etc basically data that would be useless or have no value to a hacker!!), and whilst the user uses the website the relevant data stored in the session will be used as opposed to accessing the database everytime. 当用户登录时,我希望从数据库中的每个表中获取所有数据并将其存储在会话变量中(显然不是敏感数据,如加密密码/盐等基本上是无用的数据或对于没有任何价值的数据)黑客!!),当用户使用网站时,将使用存储在会话中的相关数据,而不是每次访问数据库。 Moreover when the data is changed or added this will be written or added to the session file, and upon a major action such as "saving" or "loggin out" the new/changed data will be written to the database. 此外,当数据被更改或添加时,这将被写入或添加到会话文件中,并且在诸如“保存”或“登出”之类的主要动作时,新的/改变的数据将被写入数据库。

The reason I wish to do this is simply for efficieny, I want my application to not only be fast but less resource consuming. 我希望这样做的原因仅仅是为了提高效率,我希望我的应用程序不仅速度快,而且资源消耗更少。 I am no expert on either which may explain why my idea makes no differnece or is more resource intensive. 我不是任何一个专家,这可以解释为什么我的想法没有区别或资源密集。

If there is an alternative to my solution please let me know or if there is something to improve on my solution I will be glad to hear it. 如果我的解决方案有替代方案,请告诉我,或者如果我的解决方案有一些改进,我会很高兴听到它。

Thank you. 谢谢。 My application is using PHP and mysql. 我的应用程序是使用PHP和MySQL。

If any of these don't apply to your app, then please ignore. 如果其中任何一项不适用于您的应用,请忽略。 In general, I'm against using sessions as caches (especially if anything in the session is going to be written back to the DB). 一般来说,我反对使用会话作为缓存(特别是如果会话中的任何内容将被写回数据库)。 Here's why. 这就是原因。

  • Editing the session requires a request from the user. 编辑会话需要用户的请求。 Editing a php session outside of the request-response cycle is very difficult. 在请求 - 响应周期之外编辑php会话非常困难。 So if a user Alice makes a change which affects Bob, you have no way to dirty Bob's cache 因此,如果用户Alice进行了影响Bob的更改,则无法弄脏Bob的缓存
  • You can't assume users will log out. 您不能假设用户将退出。 They may just leave so you have to deal with saving info if the session times out. 他们可能只是离开,因此如果会话超时,您必须处理保存信息。 Again, this is difficult outside of the request-response cycle and you can't exactly leave session files lying around forever until the user comes back (php will gc them by default) 同样,在请求 - 响应周期之外这很困难,并且在用户返回之前你不能完全保留会话文件(默认情况下,php会gc)
  • If the user requires authentication, you're storing private information in the session. 如果用户需要身份验证,则会在会话中存储私人信息。 Some users may not be happy about that. 有些用户可能对此不满意。 More importantly, a hacker could imploy that private information to conduct a social engineering attack against the end-user. 更重要的是,黑客可以利用该私人信息对最终用户进行社会工程攻击。
  • Mallory (a hacker) might not be able to use the information you put in the session, but she can poison it (ie. cache poisoning), thereby causing all sorts of problems when you write your cache to your permanent storage. Mallory(黑客)可能无法使用您在会话中输入的信息,但是她可以使其中毒(即缓存中毒),从而在将缓存写入永久存储时导致各种问题。 Sessions are easier to poison then something like redis or memcache. 会话更容易中毒,比如redis或memcache。

TL;DR Lots of considerations when using a session cache. TL; DR使用会话缓存时需要考虑很多事项。 My recommendation is redis/memcache. 我的建议是redis / memcache。

You can also go for in HTML5, check The Guide and THE PAST, PRESENT & FUTURE OF LOCAL STORAGE FOR WEB APPLICATIONS 您也可以在HTML5中进行 ,查看指南以及本地应用的过去,现在和将来的Web应用程序

Local Storage in HTML5 actually uses your browsers database that works as cookies but it stores data permanently to your browser HTML5中的本地存储实际上使用您的浏览器数据库作为cookie,但它将数据永久存储到您的浏览器

  1. unless someone by force remove the data from the browser finding the data files 除非有人通过强制从浏览器中删除数据查找数据文件
  2. Or if someone remove/uninstall browser completely, 或者如果有人完全删除/卸载浏览器,
  3. or if someone uses the application in private/incognito mode of the browser, 或者如果有人在浏览器的私人/隐身模式下使用该应用程序,

What you need to do 你需要做什么

  1. Copy the schema for required tables and for required columns and update data at a regular interval 复制所需表的模式以及所需的列,并定期更新数据
  2. you dont have to worry about user's state, you only have to update the complete data from the localStorage to mysql Server (and from the mysql server to localStorage if required) every time user backs to your application and keep updating the data at regular interval 你不必担心用户的状态,每次用户都回到你的应用程序并定期更新数据时,你只需要将完整的数据从localStorage更新到mysql Server(以及从mysql服务器到localStorage,如果需要)。

Now this is turning out to be more of localStorage but I think this is one of the best solution available for me. 现在这更像是localStorage但我认为这是我可以使用的最佳解决方案之一。

redis is a good solution if it is available for you (sometimes developers can't install external modules for some reason) what I would do is either go with your Session approach but with encoded/encrypted and serialized data. redis是一个很好的解决方案,如果它可供你使用(有时开发人员因某些原因无法安装外部模块)我会做的是使用Session方法,但使用编码/加密和序列化数据。 Or, which I really prefer is to use HTML5 data properties such as: 或者,我更喜欢使用HTML5数据属性,例如:

<someElement id="someId" data-x="HiX" data-y="Hi-Y" />

which BTW works fine with all browsers even with IE6 but with some tweaks, specially if your application uses jquery and ajax. 哪个BTW适用于所有浏览器, 即使使用IE6但有一些调整,特别是如果你的应用程序使用jquery和ajax。 this would really be handful. 这真的很少。

You need to use Memcache for this kind of work. 您需要使用Memcache进行此类工作。 To solve the problem of keeping the updated data everywhere you can create functions for fetching the data, for example when the user logs in you, authenticate the user and after that insert all the user data into the memcache with unique keys like :- 为了解决在任何地方保存更新数据的问题,您可以创建用于获取数据的功能,例如,当用户登录时,对用户进行身份验证,然后将所有用户数据插入到具有以下唯一键的内存缓存中: -

USER_ID_USERNAME for user's username 用户名的USER_ID_USERNAME

USER_ID_NAME for user's name etc... USER_ID_NAME用户名等...

Now create some more functions to fetch all this data whenever you need it. 现在创建更多函数以在需要时获取所有这些数据。 For ex 对于前者

function getName($user_id){
    if(Memcache::get($user_id."_name"){
        return Memcache::get($user_id."_name");
    } else {
        //Call another function which will fetch the data from the DB and store it in the cache
    }
}

You will need to create functions to fetch every kind of data related to the user. 您需要创建函数来获取与用户相关的每种数据。 And as you said you want to update this data on some major event. 正如你所说,你想在一些重大事件上更新这些数据。 You can try updating the data using CRON or something like that, because as tazer84 mentioned users may never log out. 您可以尝试使用CRON或类似的东西更新数据,因为tazer84提到用户可能永远不会注销。

I also use what the OP described to avoid calls to db. 我还使用OP描述的内容来避免调用db。 For example, when a user logs-in, i have a "welcome-tip" on their control panel like 例如,当用户登录时,我的控制面板上有一个“欢迎提示”

Welcome, <USERS NAME HERE>

If i stored only his user_id on $_SESSION then in every pageview i would have to retrieve his information from the database just to have his name available, like SELECT user_name FROM users WHERE user_id = $_SESSION['user']['user_id'] So to avoid this, i store some of his information in $_SESSION. 如果我只将他的user_id存储在$ _SESSION上,那么在每个网页浏览中我都必须从数据库中检索他的信息只是为了让他的名字可用,比如SELECT user_name FROM users WHERE user_id = $_SESSION['user']['user_id']所以为了避免这种情况,我将他的一些信息存储在$ _SESSION中。

Be careful! 小心! When there is a change on data, you must modify the data in db and if successfull also modify the $_SESSION. 当数据发生更改时,您必须修改db中的数据,如果成功,还要修改$ _SESSION。

In my example, when a user edits his name (which i also store in $_SESSION so i can use it to welcome-tip), i do something like: 在我的例子中,当用户编辑他的名字(我也存储在$ _SESSION中,所以我可以使用它来欢迎提示),我做了类似的事情:

If (UpdateCurrentUserData($new_data)) // this is the function that modifies the db
{
    $_SESSION['user']['user_name']=$new_data['user_name']; // update session also!
}

Attention to: session.gc_maxlifetime in your php.ini 注意:你的php.ini中的session.gc_maxlifetime

This value says how much time the $_SESSION is protected from being erased by the garbage collector (the file that exists on your disk in which the $_SESSION data are stored) 此值表示保护$ _SESSION多长时间不被垃圾收集器(存储$ _SESSION数据的磁盘上存在的文件)擦除

If you set this very low, users may start getting logged-out unexpectedly if they are idle more than this amount of time because garbage collector will delete their session file too quickly 如果将此值设置得非常低,用户可能会因空闲时间超过此时间而意外开始注销,因为垃圾收集器会过快地删除其会话文件

if you set this very high, you may end up with lots of unused $_SESSION files of users that have left your website a long time ago. 如果你设置这么高,你可能会得到许多未使用过的$ _SESSION文件的用户很久以前就离开了你的网站。

also i must add that gc_maxlifetime works together with session.gc_probability where in general you need lower probability for high-traffic websites and bigger probability for lower traffic since for each pageview there is a session.gc_probability that garbage collector will be activated. 另外,我必须补充一点, gc_maxlifetimesession.gc_probability一起工作,一般来说,你需要较低的流量网站概率和较低的流量概率,因为每个网页浏览都有一个session.gc_probability垃圾收集器将被激活。

A nice more detailed explanation here http://www.appnovation.com/blog/session-garbage-collection-php 这里有一个更详细的解释http://www.appnovation.com/blog/session-garbage-collection-php

I know this sounds stupid but .... If ur data is not sensitive the best way to make it accessible faster is to store it in hidden variables inside the forms itself. 我知道这听起来很愚蠢但是......如果你的数据不敏感,那么让它更快可访问的最好方法就是将它存储在表单本身的隐藏变量中。 You can save comma separated or values in an array. 您可以在数组中保存逗号分隔或值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM