Express+Redis使用
最近,看同事在 Express 中使用了 Redis,在好奇心的驱使下,我也学习了下,特此记录下。
1、在项目中安装 redis
npm install redis
2、新建 redis 配置文件,redisUtils.js
const redis = require("redis")
// 生成redis的client,此处为4.x版本写法
const redisClient = redis.createClient({
/*
* redis://[[username][:password]@][host][:port][/db-number]
* 写密码redis://:123456@127.0.0.1:6379/0
* 写用户redis://uername@127.0.0.1:6379/0
* 或者不写密码 redis://127.0.0.1:6379/0
* 或者不写db_number redis://:127.0.0.1:6379
*
*/
url: "redis://127.0.0.1:6379/0"
});
// 如果redis版本为3.x,那么写法如下
// const redisClient = redis.createClient(port, 'ip', {auth_pass: "password"})
redisClient.on('ready', () => {
console.log('redis is ready...')
})
redisClient.on('error', err => {
console.log(err)
})
redisClient.connect() // 连接
// 存储值
const setValue = (key, value) => {
if (typeof value === 'string') {
redisClient.set(key, value)
} else if (typeof value === 'object') {
for (let item in value) {
redisClient.hmset(key, item, value[item], redis.print)
}
}
}
// 获取string
const getValue = (key) => {
return new Promise((resolve, reject) => {
redisClient.get(key).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
// 导出
module.exports = {
setValue,
getValue
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
至此,就可以在需要使用的地方引入该文件,进行使用了。
使用Redis作为缓存在高并发场景下有可能出现以下几个问题
1、缓存击穿:大量的高并发请求同时访问同一个在 redis 中不存在的数据,就会导致大量的请求绕过 redis 同时并发访问数据库,对数据库造成了高并发访问压力。
解决办法:
使用互斥锁:是在缓存失效的时候(判断拿出来的值为空),不是立即去查询数据库,而是先使用 Redis 的 SETNX 去 set 一个互斥 key,当操作返回成功时,再进行 load db 的操作并回设缓存;否则,就重试整个 get 缓存的方法。SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现互斥的效果。
2、缓存穿透:大量的请求一个数据库中不存在的数据,首先在 redis 中无法命中,最终所有的请求都会访问数据库,同样会导致数据库承受巨大的访问压力
(1)、把不存在的 key 设置 null 值到缓存中,并设置过期时间。
(2)、使用布隆过滤器,在查询缓存前先通过布隆过滤器判断 key 是否存在,存在再去查询缓存。
设置 null 值可能被恶意针对,攻击者使用大量不存在的不重复 key ,那么方案一就会缓存大量不存在 key 数据。此时我们还可以对 Key 规定格式模板,然后对不存在的 key 做正则规范匹配,如果完全不符合就不用存 null 值到 redis,而是直接返回错误。
3、缓存雪崩:缓存中大量的数据集中过期,导致请求这些数据的大量的并发请求会同时访问数据库
解决方案:
(1)、将缓存中的数据设置成不同的过期时间
(2)、在访问洪峰到达前缓存热点数据,过期时间设置到流量最低时段