session什么意思啊-会话含义是什么
特别是单机部署要么那种老旧的架构,你搞个 Global 变量,要么硬塞一堆临时表,结局运行出个 404 要么数据不保险,这时候你就会发现,它想要的实际上就是一套“会话机制”。
这机制的核心逻辑就两个字:连接。 你想啊,你登录网页,系统给你发个 ID,你存个 ID 过来,系统记住“嘿,你是 XXX 用户”,赶明儿你点那个按钮,系统就瞅着你的 ID 干活。你要是换了 IP,换了浏览器,就连换了手机,系统就懵了,它不知道你是你,这就叫无状态性。
这时候就需求 Session 来救场。它的功能就是把你刚刚的身份、刚刚的选择、刚刚修改过的数据状态,打包成一个包,发给服务器,服务器存个起来,下次你再回来,服务器一眼就能认出你是哪位,是哪位选的路,刚刚是不是把电池插反了。 那在 MySQL 里呢?你肯定搞过 session 配置表要么全局变量,可是那些配置表是有状态的,一旦重启,要么数据量大了,查询速度就慢了。
还有那个 Global,别看撇脱,可是数据量大的话,你得自己写个复杂的逻辑去查,要是查出来是脏数据要么没锁住,还得重新搞个,成本忒高了。
这时候,Session 表就派上用场了。你定义个 session_id 字段,每次登录都生成个 UUID 要么 ID 存进去,结构挺好办,就是 ID 对应一个虚拟的表结构,存了用户信息、选了啥参数、刚刚的 SQL 语句。下次来,你直接查这个 ID 拿数据,不用查表,直接拿,效率高多了。 这听起来是不是挺好办?但在实际项目里,大量人好办把 Conceptual Schema 和 Logical Schema 混为一谈就完事了。Conceptual 是画图,画个表,字段有那个,字段有那个。Logical 才是真正要做的 CRUD 和存。大量人认定,反正数据都存有, sessionStorage 要么 Redis 存个全局变量不就行了? 这就有个陷阱。 sessionStorage Inside your browser,它只存有本地,刷新就没了,并且性能依赖你大约的认知。Redis 别看快,可是它是缓存,不是真正的持久化存,要是数据量大要么需求长期保存状态,它需求背地做持久化,这就又扯远了。真正的 Session 服务,你要把它看作一个中间件。你客户端请求进来,`Session.init()`,系统给你个 ID,你保存上去,然后请求来了,系统直接查 ID 拿数据,不用查表,不用联网。 这就好比你去餐厅进食,你点菜,服务员记下来,你走的时候,服务员不用问“你是不是跟那老李点了”,只要你回来,他直接告诉你“你点的菜我都拿过来了,加上那个特色蘸料,总共多少钱”。
这就是 Session 的价值。 再说说数据的保险性,这点绝对不能落下。大量人认定 Session 就是存 ID 那么好办,结局数据全在数据库中,那就完了。Security First,Session 的数据务必加密。你要是没加密,别人偷了数据库,只要他能拿到你的 ID,就能翻出你的所有历史操作,彻底没意义。
故此,建议你这 IDs 一定要加密,哪怕只有几行数据,也要用 AES 要么那种行业标准加密方式,别真让你去猜个密码要么用那种弱加密的。 还有那个数据丢失的难题。万一数据库重启了,要么中间件挂了,你的数据会丢吗?这得看你如何设计。
要是是用 Redis 存,那得配个持久化方案。
要是是纯数据库存,那得配个备份方案。大量人写代码,发现数据没了,第一反应是“我是不是忘记改配置了”。
实际上大量时候,是出于你的重试机制没做好,要么你的连接池满了,害得那个 ID 查不到。
故此,Session 设计的时候,得寻思容错。
比方说,要是查不到 ID,系统能不能提示“当前会话无效,请重新登录”?
要么能不能自动帮你重置一下?这就涉及到整个系统的健壮性了。 说到这儿,我认定大量新手可能认定,Session 只是个概念,写代码的时候,大不了买个现成的库,比如 Spring Session,要么 Java 的 Web Session,要么 Python 的 threading.local,就连 Flask 的 `session` 模块。
这些库实际上就是把那个"ID 对应虚拟表”的逻辑封装好了,你不用自己去写 SQL,也不用自己实现加密逻辑,直接用库里的东西就行。 可是,别光盯着库。真正的难点在哪儿?在于如何把“虚拟表”里的数据,保险、高效、持久地存到数据库里。
比如你发个消息,系统发个 ID,你在数据库里存个 ID 和一条消息对应。
那这条消息万一数据库挂了,你消息就没法读了。
这时候就得用消息队列。系统发个 ID 进来,消息就躺在队列里,等消息来了,再取出来。
要是数据库挂了,消息在队列里,你处理完再取,不就完了。 这就涉及到那个“最终一致性”的概念了。消息来了,可能数据库还没回,可能 Redis 也没回,可能 Redis 碎了。
这时候,系统得有个兜底策略。
比方说,先从缓存里拿,拿不到再查数据库,拿不到再排队重试。
要么,要是数据库确实挂了,就提示用户重新登录,然后发个新消息,用户收到新消息,又发个 ID,消息又躺在队列里。
这样就形成了一个闭环,就算数据库彻底断了,你的消息也不会丢,只是多花点工夫。 还有那个并发难题。
要是两个用户与此同时用同一个 Session ID,哪位先哪位后?这得看你的实现。
要是硬塞两个 ID,那个 ID 就重复了,这就没法用了。
故此,核心思想是“一个 ID 对应一个实例”。你查 ID,DB 上只有一条记录,你存一个 ID 进去。下次再查,还是那条记录。
这是最稳妥的。 实际上,大量项目里,Session 用得顶多的地方不是存用户画像,而是存“上下文”。
比如你登录了,系统给你个 ID,你在后台写个 `@SessionScope` 的东西。你在前端写了个 `@Component`,这个 Component 拿到了 ID,就拿着 ID 去查数据库,查表取数据。后端用的那 Component 和前端用的那 Component 是同一个 ID,数据是同步的。 那前端如何保证和后端同步?前端有个全局变量,比如 `window.sessionId`,你在后端拿到 ID 的时候,把这个 ID 存个进去。前端调用接口的时候,把这个 ID 传那会儿。后端拿到 ID,就查数据库拿数据。前后端用的 ID 是一样的。
要是后端加密了,前端加密成 Base64 要么啥的。
最关键的是,前后端不要同步逻辑。前端只负责展示,后端负责逻辑。前端拿到数据,可能还不彻底,要么数据还没更新,后端才更新了,这时候前端得处理下缓存失效的难题,要么做个请求通知。 再说说具体的应用场景。
比如做高并发,比如秒杀,Session 如何用?Session 在这里就是个凭证。你登录了,系统给你个 ID,你在这个 ID 下买过东西,要是你刷新了页面,系统记得你买过。
这时候,你能够把这个买过的东西存一个 `pending` 状态,前端显示个“购买中”的提示,倒计时启动。倒计时终止,你就把它变成“已搞定”。
这时候,后端查数据库,发现有这个 pending 的记录,设置搞定。前端那数据也就变了。 那要是系统挂了如何办?这时候就得寻思分布式 Session。
比如 Redis,你存 ID,用户登录 Redis,用户访问 Redis。
然后数据库存 ID,数据库访问 Redis。
这样,用户登录了,ID 就有了。用户访问数据库,ID 就有了。
这时候,Redis 和数据库是独立的。
要是一个挂了,另一个还在。 那如何保证数据一致性?比如用户改了账号密码,系统要更新数据库,与此同时要更新 Redis。
这时候,你发个命令,系统直接改数据库,与此同时也改 Redis。
要么,发个命令,让数据库更新,与此同时让 Redis 更新。
要是是消息队列,系统发个 ID,ID 进入队列,然后数据库更新,再告诉 Redis 更新。
这就涉及到那个“双写”要么“最终一致性”的难题了。 实际上,大量人好办犯的毛病就是当作 Session 就是存数据。
实际上 Session 就是个容器,一个载体。你在这个容器里存数据,然后调用系统的方式,系统帮你维护这个容器。你不需求去管这个容器里是如何维护的,你只需求使用它来存数据。 另外,Session 的生命周期管理也挺关键。用户登录,Session 启动。用户访问页面,Session 存有。用户刷新页面,Session 被刷新。用户登出,Session 终止。
这时候,系统得记得把 Session ID 删掉。否则,下次用户再进来,系统找不到 ID,就提示“无权限”要么“已登出”。
还有,要是用户长工夫不活跃,可能就要关一下 Session,防止垃圾数据堆积。 那在实际写代码的时候,不要想着去造轮子。
比如 Java 里,Web 框架自带的 `session` 要么 `HttpSession`,就封装好了。你只需求在 Request 进来时,初始化一个 Session 对象,在 Request 出去前,把这个 ID 存进去,Request 回来,从这个对象里拿数据。
这比自己去写个 `SessionStore` 和 `SessionService` 要靠谱得多。 那要是是 Python 呢?Flask 的 `session` 模块要么 Django 的 `request.session`,也是一样的道理。你只需求在请求里获取一个 Session ID,存进去,下次请求再取出来。 那要是是 Node.js 呢?Express 的 `session` 模块也是一样的。你拿到一个 ID,存个进去,下次请求再查。 那要是是 Spring Boot 呢?`@SessionAttributeName`,要么 `@SessionScope`,也是一样的道理。 实际上,Session 在大量场景下,就连不需求确实存一个数据库表。有些框架,比如 Flask 的 config,要么 Redis 的配置,你能够直接存到 Redis 里去。
这样,不用搞数据库表,不用搞那套复杂的逻辑,直接用 Redis 存 ID 和配置。 比如,你在 Redis 里存个 key,`user:123`,值是 `{"id": 123, "name": "张三"}`。
然后你登录了,系统发你个 ID,你存个 `user:123` 到 Redis。你下次来,你直接查 `user:123`,拿到 ID,再去数据库查表。
这样,你就省去了那套 Session 服务,直接用了 Redis。 那这种方案有啥风险?那就是数据可能丢。
要是 Redis 挂了,你查不到 ID。
这时候,你得去数据库查。
要是数据量大,查数据库慢。
故此,这种方案也得面对那个“最终一致性”的难题。
比方说,用户登录了,ID 进入 Redis,与此同时进入数据库。
要是数据库更新慢了,Redis 还是旧数据。
这时候,你得有个兜底机制,比如,先查 Redis,拿不到再查数据库,拿不到的话,提示“无权限”。 那另一个方案是,直接用数据库存 ID。
比方说,你登录了,系统发你个 ID,你存个 `user:123` 到数据库。
然后你在 Redis 里存个 `user:123` 到 Redis。
这样,两个地方都有 ID。
这时候,你不用查数据库,直接查 Redis 拿 ID,再去数据库查表。
这样效率更高。 那有没有可能,Redis 挂了,数据库也挂了?这时候如何办?那就只能提示用户重新登录,要么自动重试。 那还有一种方案,就是分布式 Session。
比方说,你登录了,系统给你个 ID。你把这个 ID 存到 Redis 里。用户访问页面,系统查 Redis 拿到 ID。用户访问数据库,系统查 DB 拿到 ID。
这时候,Redis 和数据库是独立的。
要是 Redis 挂了,数据库还在。
要是数据库挂了,Redis 还在。
这时候,系统得有个兜底策略,比如,从数据库查 ID,查不到再查 Redis,查不到再提示用户重新登录。 那这种方案有没有风险?那就是数据不一致。
比方说,用户登录了,ID 进入 Redis,与此同时进入数据库。
然后用户访问页面,Redis 更新了,可是数据库没更新。
这时候,系统就得查数据库,看看有没有更新。 那实际操作的时候,你得看具体需求。
比方说,你要是做高并发,Redis 肯定要稳,那就要用 Redis 存 ID。你要是做离线记录,数据库肯定要稳,那就得用数据库存 ID。 那还有个难题,就是 Session 的加密。你要是没加密,数据全在数据库,那就完了。你要是加密了,那得保证你的加密算法是行业标准的,别用那种弱加密的。 还有,Session 的过期工夫。你要是没设过期工夫,那用户登录后,数据就一直存有。
这时候,万一数据库挂了,数据就还在,脏数据就多了。
故此,得给个合理的过期工夫,比如 24 小时,要么 7 天,然后根据业务调整。 那在实际项目中,大量人会搞个 `session_timeout` 参数,比如 30 分钟。
那用户要是没在这个工夫里访问页面,Session 就过期了。
这时候,系统得记得把 ID 删掉。 那要是是无状态的架构呢?比如 Redis 集群,那就不需求 Session 了。你直接存 ID 到 Redis 里,用户访问页面,系统查 Redis 拿到 ID。
然后,你查数据库,拿到数据。
这样,就不需求 Session 了。 那在旧的系统里,比如单机部署,要么那种老旧的架构,那就要搞 Session 了。 那在云端,比如 AWS,那肯定不需求人工 Session 了。AWS 有那个 EBS,有那个 Auto Scaling,系统会自动帮你管理 Session。 那在本地,比如我自己在写代码,那得自己搞 Session。 那总结一下,Session 就是个“记忆 ID"。它让你能记住刚刚的对话,记住刚刚的选择,记住刚刚的数据状态。你登录了,系统给你个 ID,你存个 ID 过来,系统记住了“嘿,你是 XXX 用户”。你刷新了页面,系统记得你刚刚的 ID,你就直接拿数据,不用重新登录。 那要是你搞错了,比如没搞对 Session,那你可能就得连登录都搞不那会儿。
要么,你登录了,但数据取不出来,那就是你的 Session 有难题。
要么,你数据取出来了,但数据是脏的,那就是你的 Session 逻辑有难题。 那在实际写代码的时候,不要纠结忒深。你要把 Session 当作一个工具,一个帮你管理状态的工具。你登录了,系统给你个 ID,你只需求用它来存数据,系统帮你维护这个 ID。你不需求去管这个 ID 是如何维护的,你只需求使用它来存数据。 那要是你实在搞不懂,那就买个现成的库,比如 Spring Session,要么 Java 的 Web Session,要么 Python 的 threading.local,要么 Flask 的 session,要么 Django 的 request.session,要么 Node.js 的 session 模块,要么 Spring 的 @SessionAttributeName。
这些库实际上就是把那个"ID 对应虚拟表”的逻辑封装好了,你不用自己去写 SQL,也不用自己实现加密逻辑,直接用库里的东西就行。 那要是还是搞不定,那就寻思分布式 Session,要么单机 Session。 那实际上,Session 在大量场景下,就连不需求确实存一个数据库表。有些框架,比如 Flask 的 config,要么 Redis 的配置,你能够直接存到 Redis 里去。
这样,不用搞数据库表,不用搞那套复杂的逻辑,直接用 Redis 存 ID 和配置。 比如,你在 Redis 里存个 key,`user:123`,值是 `{"id": 123, "name": "张三"}`。
然后你登录了,系统发你个 ID,你存个 `user:123` 到 Redis。你下次来,你直接查 `user:123`,拿到 ID,再去数据库查表。
这样,你就省去了那套 Session 服务,直接用了 Redis。 那这种方案有啥风险?那就是数据可能丢。
要是 Redis 挂了,你查不到 ID。
这时候,你得去数据库查。
要是数据量大,查数据库慢。
故此,这种方案也得面对那个“最终一致性”的难题。
比方说,用户登录了,ID 进入 Redis,与此同时进入数据库。
要是数据库更新慢了,Redis 还是旧数据。
这时候,你得有个兜底机制,比如,先查 Redis,拿不到再查数据库,拿不到的话,提示“无权限”。 那实际操作的时候,你得看具体需求。
比方说,你要是做高并发,Redis 肯定要稳,那就要用 Redis 存 ID。你要是做离线记录,数据库肯定要稳,那就得用数据库存 ID。 那还有个难题,就是 Session 的加密。你要是没加密,数据全在数据库,那就完了。你要是加密了,那得保证你的加密算法是行业标准的,别用那种弱加密的。 还有,Session 的过期工夫。你要是没设过期工夫,那用户登录后,数据就一直存有。
这时候,万一数据库挂了,数据就还在,脏数据就多了。
故此,得给个合理的过期工夫,比如 24 小时,要么 7 天,然后根据业务调整。 那在实际项目中,大量人会搞个 `session_timeout` 参数,比如 30 分钟。
那用户要是没在这个工夫里访问页面,Session 就过期了。
这时候,系统得记得把 ID 删掉。 那要是是无状态的架构呢?比如 Redis 集群,那就不需求 Session 了。你直接存 ID 到 Redis 里,用户访问页面,系统查 Redis 拿到 ID。
然后,你查数据库,拿到数据。
这样,就不需求 Session 了。 那在旧的系统里,比如单机部署,要么那种老旧的架构,那就要搞 Session 了。 那在云端,比如 AWS,那肯定不需求人工 Session 了。AWS 有那个 EBS,有那个 Auto Scaling,系统会自动帮你管理 Session。 那在本地,比如我自己在写代码,那得自己搞 Session。 那总结一下,Session 就是个“记忆 ID"。它让你能记住刚刚的对话,记住刚刚的选择,记住刚刚的数据
声明:演示网站所有内容,若无特殊说明或标注,均来源于网络转载,仅供学习交流使用,禁止商用。若本站侵犯了你的权益,可联系本站删除。
