Skip to content

Commit 9b0b923

Browse files
redis
1 parent a55f018 commit 9b0b923

File tree

4 files changed

+229
-0
lines changed

4 files changed

+229
-0
lines changed

Diff for: Storage/Redis/project/index.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const fs = require('fs');
2+
const util = require('util');
3+
const Redis = require('ioredis');
4+
5+
const config = {
6+
host: '127.0.0.1',
7+
port: 6378,
8+
password: '123456',
9+
db: 0
10+
};
11+
const client = new Redis(config);
12+
const pub = new Redis(config);
13+
const sub = new Redis(config);
14+
15+
16+
17+
// demo 测试
18+
(async function () {
19+
20+
// normal
21+
await client.set('key1', 'value1');
22+
console.log(`get key: ${await client.get('key1')}`);
23+
24+
// pipeline
25+
let ret = await client.pipeline()
26+
.hmset('hash', 'key1', 'value1', 'key2', 'value2')
27+
.hmget('hash', 'key1', 'key2')
28+
.exec();
29+
console.log(`pipeline: ${JSON.stringify(ret)}`);
30+
31+
// transaction
32+
ret = await client.multi()
33+
.hmset('hash', 'key1', 'value1', 'key2', 'value2')
34+
.zadd('set', '0', 'a', '1', 'b')
35+
.zrange('set', 0, 10, 'WITHSCORES')
36+
.exec();
37+
console.log(`transaction: ${JSON.stringify(ret)}`);
38+
39+
// pub & sub
40+
sub.on('message', (channel, message) => {
41+
console.log(`sub on message: ${channel} ${message}`);
42+
});
43+
await sub.subscribe('channel');
44+
await pub.publish('channel', 'this is message from pub client');
45+
46+
47+
// lua
48+
client.defineCommand('script', {
49+
numberOfKeys: 2,
50+
lua: await util.promisify(fs.readFile)('lua/script.lua')
51+
});
52+
ret = await client.script('key1', 'key2', 1, 2.3);
53+
console.log(`script: ${JSON.stringify(ret)}`);
54+
55+
56+
57+
58+
59+
})().then(()=> client.disconnect()).catch(e => console.log(e));
60+
61+

Diff for: Storage/Redis/project/lua/script.lua

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
-- ******************************************** lua 基本语法 ********************************************
3+
4+
-- 变量声明
5+
local key = {KEYS[1],KEYS[2]};
6+
local value = {ARGV[1],ARGV[2]};
7+
8+
local table = {'this', 'is', 'table'};
9+
local luaNil = nil;
10+
local boolean = true
11+
local number = 3.2;
12+
local str = 'this is string';
13+
14+
15+
16+
-- 类型判断
17+
local tk1 = type(KEYS[1]);
18+
local tk2 = type(KEYS[2]);
19+
local tv1 = type(ARGV[1]);
20+
local tv2 = type(ARGV[2]);
21+
22+
-- 函数定义
23+
local function factorial(num)
24+
if num == 0 then
25+
return 1
26+
else
27+
return num * factorial(num-1);
28+
end
29+
end
30+
31+
32+
33+
34+
-- ******************************************** 与redis 交互 ********************************************
35+
-- redis.call(), 执行命令出错, 将导致脚本退出
36+
redis.call('set', 'lua-key1', 'lua-value1');
37+
local v1 = redis.call('get', 'lua-key1');
38+
39+
40+
41+
--[[
42+
redis.pcall(), 执行命令出错, 会返回一个带 err 域的 lua table
43+
44+
{
45+
err:
46+
}
47+
48+
--]]
49+
return {
50+
key,
51+
value,
52+
{table, boolean, number, str, luaNil}, -- nil 位置需注意
53+
{tk1, tk2, tv1, tv2},
54+
v1,
55+
factorial(10)
56+
};

Diff for: Storage/Redis/project/package.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"dependencies": {
3+
"ioredis": "^4.10.0"
4+
},
5+
"devDependencies": {
6+
"@types/ioredis": "^4.0.12"
7+
}
8+
}

Diff for: Storage/Redis/redis.md

+104
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ docker stop redis-latest
3333
docker rm redis-latest
3434
```
3535

36+
### redis 持久化
37+
#### 持久化类型
38+
* RDB
39+
* 在指定的时间间隔内生成数据集的时间点快照
40+
* AOF
41+
* 记录服务器所有写操作命令,新命令追加到文件末尾。
42+
* 可以在后台对 AOF 文件进行重写,使得 AOF 文件体积不会超过保存数据集状态所需的实际大小
43+
* RDB + AOF
44+
* 优先使用 AOF 还原数据集,通常 AOF 比 RDB 文件保存的数据集更完整
45+
* 不使用持久化,数据仅存在服务器运行时
46+
47+
### 优缺点
48+
* RDB
49+
* 适合备份,保存了 redis 某个时间点的数据集,方便还原指定版本
50+
* 文件紧凑,适合用于灾难恢复
51+
* 最大化性能,保存 RDB 时仅需要 fork 子进程,父进程无需 io 操作
52+
* 恢复速度相比 AOF 快
53+
* 故障时丢失数据,保存时间点间隔不能过近(至少 5 分钟)
54+
* 数据集较大 fork 可能耗时过长
55+
56+
* AOF
57+
* 完整性高,默认每秒一次保存,仍可保持良好性能,最多只丢失 1s 数据
58+
* append only,不需要 seek 文件操作
59+
* 自动重写,新的 AOF 文件保存恢复当前数据集最小的命令集合
60+
* 有序保存所有写操作,便于分析读取
61+
* aof 文件通常大于 rdb
62+
* aof 速度可能慢于 rdb
63+
* 可能部分写命令阻塞导致数据恢复异常
64+
65+
66+
67+
3668
### [redis 基本使用](http://redisdoc.com/)
3769

3870
```bash
@@ -180,6 +212,78 @@ PEXPIRE key 1000 # 设置过期时间,毫秒
180212
PEXPIREAT key 1560783424000 # 设置过期时间戳毫秒
181213
PTTL key # 返回剩余时间,类似 TTL,单位 毫秒
182214

215+
# 事务
216+
MULTI # 开始一个事务,此命令后的多条命令会按先后顺讯放入队列,由 EXEC 命令原子性的执行
217+
EXEC # 执行事务块内的命令,如果某些 key 处于 watch 监视,且事务块中有和这个 key 相关的命令,那么 exec 只在这些 key 没有被其他命令所改动的情况下执行生效,否则事务被打断
218+
DISCARD # 放弃当前事务,若此时 watch 了某些 key,则取消所有 watch
219+
WATCH key1 key2 # 监视一个或多个 key,若在事务执行前这些 key 被其他命令改动,那么事务被打断
220+
UNWATCH # 取消对所有 key 的监视,EXEC 或 DISCARD 先执行,就不需要 UNWATCH 了
221+
222+
# lua 脚本
223+
EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 value1 value2 # 执行一段脚本,指定参数个数,参数名称和对应的值
224+
EVALSHA a42059b356c875f0717db19a51f6aaca9ae659ea 2 k1 k2 v1 v2 # 执行脚本,类似 EVALSHA,若脚本缓存不存在 报错 NOSCRIPT
225+
SCRIPT LOAD "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" # 加载 lua 脚本,返回 sha1 校验和,可通过 EVALSHA 执行
226+
SCRIPT EXISTS a42059b356c875f0717db19a51f6aaca9ae659ec a42059b356c875f0717db19a51f6aaca9ae659ea # 判断一个或多个脚本是否存在,返回列表 0 表示不存在, 1 表示存在
227+
SCRIPT FLUSH # 清空脚本缓存
228+
SCRIPT KILL # 关闭当前运行的且没有执行过写操作的脚本,若脚本进行了写操作,且无限循环,只能通过 SHUTDOWN NOSAVE 停止 redis 进程来停止脚本运行
229+
230+
# 持久化
231+
SAVE # 同步保存,rdb,会阻塞所有操作
232+
BGSAVE # 后台异步保存,rdb,fork 子进程保存,保存完毕子进程自动退出
233+
BGREWRITEAOF # 后台执行 aof 重写操作,重新创建 aof,
234+
LASTSAVE # 最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示,十位
235+
236+
# pub、sub
237+
PUBLISH channel "this is message form channel" # 向指定频道发送消息
238+
SUBSCRIBE channel1 channel2 # 监听指定频道消息
239+
PSUBSCRIBE channel* new* # 监听符合表达式的频道
240+
UNSUBSCRIBE channel1 channel2 # 取消消息订阅
241+
PUNSUBSCRIBE channel* new* # 取消符合表达式的监听,无参则取消 使用PSUBSCRIBE 订阅的频道
242+
PUBSUB CHANNELS * # 获取符合表达式的活跃频道列表, 模式订阅的不算
243+
PUBSUB NUMSUB channel1 channel2 # 获取频道订阅者个数
244+
PUBSUB NUMPAT # 客户端订阅的所有模式的数量总和
245+
SLAVEOF 127.0.0.1 6378 # 将当前服务器变为 指定服务器的从服务器
246+
SLAVEOF NO ONE # 不丢弃同步所得,转为主服务器
247+
ROLE # 返回当前服务器角色,master 、 slave 或者 sentinel, 主服务器将返回属下从服务器的 IP 地址和端口。从服务器将返回自己正在复制的主服务器的 IP 地址、端口、连接状态以及复制偏移量。Sentinel 将返回自己正在监视的主服务器列表。
248+
249+
# 客户端与服务器
250+
CONFIG SET requirepass 123456 # 设置密码(建议通过配置文件设置)
251+
AUTH password # 认证密码
252+
QUIT # 关闭连接
253+
INFO # redis 信息
254+
SHUTDOWN SAVE # 保存并关闭,可用 NOSAVE 不保存
255+
TIME # 返回服务器时间,第一个字符串是当前时间戳(10 位),第二个则是当前这一秒已过去的微妙数
256+
CLIENT SETNAME client1 # 为当前链接命名
257+
CLIENT GETNAME # 获取当前链接的名称,未设置则返回 nil
258+
CLIENT LIST # 返回所有连接到服务器的客户端信息和统计数据
259+
CLIENT KILL 127.0.0.1:61312 # 关闭指定客户端链接,数据来源 CLIENT LIST
260+
261+
# 配置相关
262+
CONFIG GET * # 获取符合表达式的 redis 可配置参数列表
263+
CONFIG SET requirepass 123456 # 动态调整redis 配置,立即生效,可配置参数使用 CONFIG GET * 获取
264+
CONFIG RESETSTAT # 重置 info 中的某些统计状态
265+
CONFIG REWRITE # 将当前配置写入 redis.conf 中
266+
267+
# 调试相关
268+
PING # 检测链接是否正常服务器正常返回 PONG
269+
ECHO message # 打印信息,返回 message
270+
OBJECT REFCOUNT key # 返回 key 引用所存储值的次数
271+
OBJECT ENCODING key # 返回 key 的编码类型
272+
OBJECT IDLETIME key # 返回 key 自存储以来空闲的时间,单位:秒
273+
CONFIG get slowlog* # 查看当前 slowlog 的配置
274+
SLOWLOG GET 1 # 查看 slowlog 日志, 数字指定数量,不传则默认 slowlog-max-len
275+
SLOWLOG LEN # 查看当前慢日志列表
276+
MONITOR # 实时输出 redis 接收到的命令
277+
DEBUG OBJECT key # 返回 key 对应的 obeject 信息,内存地址,引用次数,编码类型等
278+
DEBUG SEGFAULT # 崩溃redis,模拟 bug
279+
280+
# 内部命令
281+
MIGRATE 127.0.0.1 6378 poster_123 0 100 AUTH 123456 COPY # 迁移 key 至指定 redis 的 0 号 db,设置超时 100ms,指定密码 123456, copy 则是保留当前实例 key ,replace 则会删除当前实例的 key
282+
DUMP key # 序列化指定 key
283+
RESTORE r-key 0 "\x00\x05value\b\x008\xdb-\x87h\xb3\x11V" REPLACE # 反序列化某个值到指定键上,并设置 ttl,0 标记不设置过期时间 replace 指定若 key 存在则覆盖,否则若 key 存在则报错
284+
SYNC # 复制功能的内部命令
285+
PSYNC ? -1 # 复制功能的内部命令
286+
183287
```
184288
185289

0 commit comments

Comments
 (0)