一、node JS 中的 redis
- 解决方案
redis
,如下所示:
- 将
web server
和redis
拆分为两个单独的服务 - 双方都是独立的,都是可扩展的,例如都扩展成集群
- 包括
mysql
,也是一个单独的服务,也可扩展
session
适用于redis
,如下所示:
session
访问频繁,对性能要求极高session
可不考虑断电丢失数据的问题,这也是内存的硬伤session
数据量不好太大,相比于mysql
中存储的数据
- 网站数据不适合用
redis
,如下所示:
- 操作频率不是太高,相比
session
操作 - 断电不能丢失,必须保留
- 数据量太大,内存成本太高
-
通过
npm i redis koa-redis koa-generic-session --save
命令下载redis、koa-redis 和 koa-generic-sessio
。 -
在
redis
目录下,新建两个CMD
窗口,分别输入redis-server.exe redis.windows.conf
和redis-cli.exe -h 127.0.0.1 -p 6379
命令,启动redis
。 -
新建
config
目录,在里面建立db.js
文件,进行redis
和mysql
的一些配置,代码如下所示:
const {
isProd } = require('../utils/env')
let REDIS_CONF = {
port: 6379,
host: '127.0.0.1'
}
let MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '123456',
port: '3306',
database: 'koa2_weibo_db'
}
if (isProd) {
REDIS_CONF = {
port: 6379,
host: '127.0.0.1'
}
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: '123456',
port: '3306',
database: 'koa2_weibo_db'
}
}
module.exports = {
REDIS_CONF,
MYSQL_CONF
}
- 新建
cache
目录,在里面建立_redis.js
文件,进行设置连接redis
的set
和get
方法,代码如下所示:
// 连接 redis 方法的 get set
const redis = require('redis')
const {
REDIS_CONF } = require('../config/db')
// 创建客户端
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host)
redisClient.on('errno', err => {
console.log('redis errno', err)
})
// set
/**
* redis set
* @param {string} key 键
* @param {string} val 值
* @param {number} timeout 过期时间,单位 s
*/
function set(key, val, timeout = 60 * 60 ) {
if (typeof val === 'object') {
val = JSON.stringify(val)
}
// 设置键和值
redisClient.set(key, val)
// 设置过期时间
redisClient.expire(key, timeout)
}
// get
/**
* redis get
* @param {string} key 键
*/
function get(key) {
const promise = new Promise((resolve, reject) => {
redisClient.get(key, (err, val) => {
if (err) {
reject(err)
return
}
if (val == null) {
resolve(null)
return
}
try {
resolve(JSON.parse(val))
} catch (ex) {
resolve(val)
}
})
})
return promise
}
module.exports = {
set,
get
}
- 在
app.js
文件中,引入koa-redis
和koa-generic-session
,让redis
与session
之间进行关联,代码如下所示:
const session = require('koa-generic-session')
const redisStore = require('koa-redis')
// session 配置
app.keys = ['Uas*305wf29#']
app.use(session({
key: 'weibo.sid', // cookie name 默认是 `koa.sid`
prefix: 'weibo:sess', // redis key 的前缀,默认是 `koa.sess:`
cookie: {
path: '/',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000 // ms cookie 过期时间
},
ttl: 24 * 60 * 60 * 1000, // redis 过期时间
store: redisStore({
all: `${
REDIS_CONF.host}:${
REDIS_CONF.port}`
})
}))
- 完整
app.js
,代码如下所示:
// 业务逻辑
const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const session = require('koa-generic-session')
const redisStore = require('koa-redis')
const {
REDIS_CONF } = require('./config/db')
const {
isProd } = require('./utils/env')
// 路由
const index = require('./routes/index')
const users = require('./routes/users')
const errorViewRouter = require('./routes/view/error')
// error handler
let onerrorConfig = {
}
if (isProd) {
onerrorConfig = {
redirect: '/error'
}
}
onerror(app, onerrorConfig)
// middlewares
app.use(bodyparser({
enableTypes:['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))
app.use(views(__dirname + '/views', {
extension: 'ejs'
}))
// debugger
// session 配置
app.keys = ['Uas*305wf29#']
app.use(session({
key: 'weibo.sid', // cookie name 默认是 `koa.sid`
prefix: 'weibo:sess', // redis key 的前缀,默认是 `koa.sess:`
cookie: {
path: '/',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000 // ms cookie 过期时间
},
ttl: 24 * 60 * 60 * 1000, // redis 过期时间
store: redisStore({
all: `${
REDIS_CONF.host}:${
REDIS_CONF.port}`
})
}))
// logger
app.use(async (ctx, next) => {
const start = new Date()
await next()
const ms = new Date() - start
console.log(`${
ctx.method} ${
ctx.url} - ${
ms}ms`)
})
// routes
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())
app.use(errorViewRouter.routes(), errorViewRouter.allowedMethods())
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
module.exports = app
- 在
routes
文件下的index.js
文件中,去进行使用redis
,当访问http://localhost:3000/json
这个路由的时候,session
就会产生,存入redis
,代码如下所示:
const router = require('koa-router')()
router.get('/json', async (ctx, next) => {
const session = ctx.session
if (session.viewNum == null) {
session.viewNum = 0
}
session.viewNum++
ctx.body = {
title: 'koa2 json',
viewNum: session.viewNum
}
})
- 当在浏览器窗口进行访问
http://localhost:3000/json
,就会进行计数,同时redis
中也会有值,如下图所示