百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

在nodejs中使用Redis缓存和查询数据及Session

wptr33 2024-12-31 15:03 43 浏览

在之前的这篇文章 在ExpressJS(NodeJS)中设置二级域名跨域共享Cookie中提及将Session存放到Mongodb中,其中有很多讲解的不是很详细。

我们为什么要把Session存放到数据中,以及又为什么要在子域名间跨域共享Cookie呢?

Session与Cookie的关系

客户端与服务会使用一个Sessionid的Cookie值来进行客户端和服务器端会话的匹配,这个Cookie一般是服务器端读/写的,并在Http请求响应的Header中的Set-Cookie属性设置:

HTTP/1.1 200 OK

Server: nginx

Date: Wed, 14 Jan 2015 02:29:09 GMT

Content-Type: text/html

Transfer-Encoding: chunked

Proxy-Connection: Keep-Alive

Connection: Keep-Alive

Content-Encoding: gzip

Set-Cookie: sessionid=i4w3axuzyj4nwwg75y6k5us2; path=/; domain=.ourjs.com; httponly

  • path=/ 表示这个cookie是设置在根目录的。

  • httponly 属性禁止客户端JavaScript的访问,防止当前会话(sessionid)被恶意的js脚本盗取

  • domain=.ourjs.com 表示将sessionid存放到主域名下,各个二级域名域名均使用此Cookie (sessionid)

注* 中间代理人攻击,即是通过代理服务器(如无线路由)盗取你的会话Cookie(SessionID等),从而访冒你的身份。因此Google建议网站全部采用HTTPS协议,加密传输内容,并提高了纯HTTPS网站的权重。

使用数据库来集中管理session,存放Session内容,并在各个子域名跨域共享Cookies (SessionID),即可实现为每一个子域分配一个独立的node.js Web服务器,各个服务程序均可依据sessionid从数据库中寻找到同一Session,从而实现不同Web Server中的会话同步,从而实现一定程度上的负载均衡。

要想实现完全意义的负载均衡还需要将Web服务做到完全状态无关,不仅仅是Session,所有的中间缓存数据都要转移到与服务器无关的缓存层中,这正是Redis最善长的地方。

但是为什么存放在Redis中要比MongoDB中好呢?

将Session存放到MongoDB

在MongoDB中是这样存放Session的, 使用connect-mongo 即用来将Express中的Session持久化到Mongodb的一个中间件,它也可以在connect上使用。

Express 4.x, 5.0 与 Connect 3.x配合使用:

varsession=require('express-session');

Express 2.x, 3.x 和 Connect 1.x, 2.x配合使用:

varMongoStore=require('connect-mongo')(express);

对于 Connect 只需要将express替换成connect即可

MongoDB是一个基于文档的数据库,所有数据是从磁盘上进行读写的。MongoDB善长的是对无模式JSON数据的查询。

而Redis是一个基于内存的键值数据库,它由C语言实现的,与Nginx/ NodeJS工作原理近似,同样以单线程异步的方式工作,先读写内存再异步同步到磁盘,读写速度上比MongoDB有巨大的提升。因此目前很多超高并发的网站/应用都使用Redis做缓存层,普遍认为其性能明显好于MemoryCache。当并发达到一定程度时,即可考虑使用Redis来缓存数据和持久化Session。

在NodeJS中使用Redis缓存数据

Redis (安装方法) 数据库采用极简的设计思想,最新版的源码包还不到2Mb。其在使用上也有别于一般的数据库。

node_redis

redis驱动程序多使用node_redis 此模块可搭载官方的 hiredis C 语言库 - 同样是非阻塞的,比使用JavaScript内置的解释器性能稍好。可选择将hiredis 与 redis 一同安装。

npminstallhiredisredis

如果 hiredis 安装成功, node_redis 会默认使用 hiredis, 否则会使用JavaScript的解释器。

Redis的一个Key不仅可以对应一个String类型的值,还支持hashes, lists, sets, sorted sets, bitmaps等。

比如存/取一组Hash值,Redis中有两个对应的命令

HMSET key field value [field value ...]、

为一个Key一次设置多个哈希键/值, 多用于JSON对象的写入(序列化的SESSION)。

HGETALL key

读取一个Key的所有 哈希键/值,多用于JSON对象读取

这两个命令即是在NodeJS中存取JSON对象的关键,

下面是node_reids中对应的例子:

varredis=require("redis"),

Redis没有严格意义上的表名和字段名,以 Key-Value 键值对的方式存储,因此一般采用 schema:key 形式做为键值,其中

schema: 可理解为传统数据库中的表名

key:    可理解为表中的主键

因此使用redis存放你的session时,需要一个schema前辍, 比如这个key: sessionid:i4w3axuzyj4nwwg75y6k5us2

Redis 也仅能对Key进行检索, 尚不支持对Key所存放的Hash Key的检索。 如要检索到所有session,只需匹配 sessionid:* 即可,

client.keys('session:*',function(err,keys){

有些第三方库会支持检索值中的Hash Key,但这不是一个原子性操作,redis本身并不提供。

因此在采用Redis缓存与检索数据时,要使用一些独特的数据类型,如集合(Sets)

>saddmyset123//添加123到集合myset

Redis集合不允许添加相同成员。多次添加同一元素到集合中最终只会包含一个元素。多个集合之间可以进行连接/交集这样的操作。从而实现类似传统数据库中索引、条件和连接查询的效果。

#添加3个用户和信息

将Session存放到Redis中

connect-reids 是一个 Redis 版的 session 存储器,使用node_redis作为驱动。借助它即可在Express中启用Redis来持久化你的Session.

安装

$npminstallconnect-redis

在 Express 3.x 中还需要安装express-session

$npminstallexpress-session

参数

client 你可以复用现有的redis客户端对象, 由 redis.createClient() 创建

host Redis服务器名

port Redis服务器端口

socket Redis服务器的unix_socket

可选参数

ttl Redis session TTL 过期时间 (秒)

disableTTL 禁用设置的 TTL

db 使用第几个数据库

pass Redis数据库的密码

prefix 数据表前辍即schema, 默认为 "sess:"

使用

将express-session传给connect-redis来启用

varsession=require('express-session');

检验

app.use(function(req,res,next){

这样你的Session就转移到了Redis数据库,这样做的一个额外好处是,当你的Express服务器突然重启后,用户仍然可以使用当前Cookie中的SessionID从数据库中获取到他的会话状态,做到会话不丢失,在一定程度上提高网站的键壮性。

如果你的NodeJS网站上的所有缓存数据都转移到了Redis后,就可做到完全状态无关,按需扩展网站的规模。

可水平扩展的NodeJS网站服务器集群(非cluster模块 不同,它们是相互独立的,可分布在不同的物理服务器上),这样的架构,对于应对超大规模并发也是有好处的。

相关推荐

开发者必看的八大Material Design开源项目

MaterialDesign是介于拟物和扁平之间的一种设计风格,自从它发布以来,便引起了很多开发者的关注,在这里小编介绍在Android开发者当中里最受青睐的八个MaterialDesign开源项...

另类插这么可爱,一定是…(另类t恤)

IT之家(www.ithome.com):另类插图:这么可爱,一定是…OSXMavericks和Yosemite打破了苹果对Mac操作系统传统的命名方式,使用加州的某些标志性景点来替换猫...

Android常用ADB命令(安卓adb工具是什么)

杀死应用①根据包名获取APP的PIDadbshellps|grep应用包名②执行kill命令...

微软Mac版PowerPoint测试Reading Order Pane功能

IT之家5月20日消息,微软公司昨日(5月19日)发布博文,邀请Microsoft365Insiders成员,测试macOS新版PowerPoint演示文稿应用,重点引入...

Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍

前言不同于iOS,Xamarin在VisualStudio中针对Android,可以直接设计使用者界面.在本篇教学文章中,笔者会针对Android的专案目录结构以及基本控制项进行介绍,包...

用云存储30分钟快速搭建APP,你信吗?

背景不管你承认与否,移动互联的时代已经到来,这是一个移动互联的时代,手机已经是当今世界上引领潮流的趋势,大型的全球化企业和中小企业都把APP程序开发纳入到他们的企业发展策略当中。但随着手机APP上传的...

谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果

Pine发自凹非寺量子位|公众号QbitAI当你拍照片时,“模特不好好配合”怎么办?...

iOS文本编辑控件UITextField和UITextVie

记录一个菜鸟的IOS学习之旅,如能帮助正在学习的你,亦枫不胜荣幸;如路过的大神如指教几句,亦枫感激涕淋!细心的朋友可能已经注意到了,IOS学习之旅系列教程在本篇公众号的文章中,封面已经换成美女图片了,...

Android入门图文教程集锦(android 入门教程)

Android入门视频教程集锦AndroidStudio错误gradientandroid:endXattributenotfound...

如何使用Android自定义复合视图(如何使用android自定义复合视图)

在最近的一个客户应用中,我遇到了一个需求,根据选定的值来生成指定数量的编辑框字段,这样用户可以输入人物信息。最初我的想法是把这些逻辑放到Fragment中,只是根据选中值的变化来向线性布局容器中增加编...

原生安卓开发app的框架frida常用关键代码定位

前言有时候可能会对APP进行字符串加密等操作,这样的话你的变量名等一些都被混淆了,看代码就可能无从下手...

教程10 | 三分钟搞定一个智能输入法程序

一案例描述1、考核知识点网格布局线性布局样式和主题Toast2、练习目标掌握网格布局的使用掌握Toast的使用掌握线性布局的使用...

(Android 8.1) 功能与新特性(android的功能)

和你一起终身学习,这里是程序员AndroidAndroid8.1(API级别27)为用户和开发人员引入了各种新特性和功能。本文档重点介绍了开发人员的新功能。通过本章阅读,您将获取到以下内容:Andr...

怎样设置EditText内部文字被锁定不可删除和修改

在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白了就是不可操作,只能在后面输入内容。在E...

如何阻止 Android 活动启动时 EditText 获得焦点

技术背景在Android开发中,当活动启动时,EditText有时会自动获得焦点并弹出虚拟键盘,这可能不是用户期望的行为。为了提升用户体验,我们需要阻止...