0%

Strings 命令

字符串是基础的 key-value 类型, 存储字节序列, 包括文本、序列化对象和二进制数组, 一个 key 对应一个 value, value 可以是字符串、整数或浮点数, value 最多可以是 512MB.

String 类型的底层的数据结构实现主要是 int 和 SDS(Simple Dynamic String)

因为 C 语言的字符串并不记录自身长度, 所以获取长度的复杂度为 O(n), SDS 结构里用 len 属性记录字符串长度, 所有复杂度为 O(1)

设置值

  • SET key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL]

    为 key 设置字符串的值, 执行成功返回 ok, 每次更新 key 的值时会自动清除过期时间

    • NX 仅当 key 不存在时设置
    • XX 仅当 key 存在时设置
    • EX 过期时间, 单位秒
    • PX 过期时间, 单位毫秒
    • EXAT 过期时间戳, 单位秒
    • PXAT 过期时间戳, 单位毫秒
    • KEEPTTL 保留 key 关联的生存时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
127.0.0.1:6379> SET age 18
OK
127.0.0.1:6379> EXPIRE age 100
(integer) 1
127.0.0.1:6379> TTL age
(integer) 98
127.0.0.1:6379> SET age 20
OK
127.0.0.1:6379> TTL age
(integer) -1

# 使用 KEEPTTL 保留 key 关联的生存时间
127.0.0.1:6379> SET age 18 EX 100
OK
127.0.0.1:6379> TTL age
(integer) 98
127.0.0.1:6379> SET age 20 KEEPTTL
OK
127.0.0.1:6379> GET age
"20"
127.0.0.1:6379> TTL age
(integer) 79
  • SETNX key value 当 key 不存在时设置指定 key 的值, 返回值 1 成功, 0 失败
1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> KEYS *
1) "xiaoming"
2) "name"
127.0.0.1:6379> SETNX age 18
(integer) 1
127.0.0.1:6379> SETNX age 18
(integer) 0
127.0.0.1:6379> KEYS *
1) "xiaoming"
2) "age"
3) "name"
  • APPEND key value 在指定 key 末尾(如果为字符串)追加内容, key 不存在同 SET 并返回追加内容的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> APPEND age 1
(integer) 3
127.0.0.1:6379> GET age
"181"
127.0.0.1:6379> APPEND addr beijing
(integer) 7
127.0.0.1:6379> KEYS *
1) "xiaoming"
2) "age"
3) "addr"
4) "name"
127.0.0.1:6379> APPEND a hello
(integer) 5
127.0.0.1:6379> APPEND b gg
(integer) 2

过期时间

  • SETEX key seconds value 设置 key 的值并设置过期时间(单位秒), 返回 ok
  • PSETEX key milliseconds value 设置 key 的值的值并设置过期时间(单位毫秒), 返回 ok
1
2
3
4
127.0.0.1:6379> SETEX addr 20 beijing
OK
127.0.0.1:6379> PSETEX addr 20000 beijing
OK

批量设置值

  • MSET key value [key value …] 批量设置 key 的值
  • MSETNX key value [key value …] 批量设置 key 的值且当所有的 key 不存在时, 返回值 1 成功, 0 失败
1
2
3
4
5
6
7
127.0.0.1:6379> KEYS *
1) "age"
2) "name"
3) "hash:zhang"
# 当且仅当所有 key 都不存在时设置成功返回 1
127.0.0.1:6379> MSETNX name zhangsan age 18 addr beijing
(integer) 0
  • SETRANGE key offset value

    覆盖指定 key 的从指定偏移量开始的字符串的一部分, 返回修改后字符串长度, key 不存在则新建

1
2
3
4
127.0.0.1:6379> SETRANG name 1 xyz
(integer) 8
127.0.0.1:6379> GET name
"axyz1234"
阅读全文 »

Redis

Remote Dictionary Server 即远程字典服务, 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API, Redis 能读的速度是 11 万次/s,写的速度是 8.1 万次/s
Redis 通常被称为数据结构服务器, 因为它的核心数据类型包括字符串、列表、字典(或哈希)、集合和排序集合等大多编程语言都支持的数据类型. 高版本版的 Redis 还添加了计算基数、地理定位和流处理等高级功能

数据类型

redis-1

阅读全文 »

范式

键: 数据库中由一个或多个属性组成
超键: 在关系中能唯一标识记录的属性集称为关系模式的超键
候选键: 不包含多余属性的超键
主键: 被作为记录标识的候选键

1
2
3
-- 超键: {学号} {身份证号} 或者 {学号} {性别} 或者 {身份证号} {年龄} 的组合属性集可以确定唯一一条记录
-- 候选键: {学号} 或者 {身份证号} 可以是候选键
-- 主键: {学号} 候选键作为主键
  • 1NF: 数据库表中的每一列的字段都是不可再分的, 原子性
  • 2NF: 数据库表中不存在非关键字段对任意候选关键字段的部分函数依赖(指存在着组合关键字中的某一关键字决定非关键字的情况)
    • 部分函数依赖:没有包含在主键中的列必须完全依赖于主键, 而不能只依赖于主键的一部分
  • 3NF: 数据库表中不存在非关键字段对任意候选关键字段的传递函数依赖
    • 传递函数依赖: 非主键列必须直接依赖于主键列,不能存在非主键列依赖于非主键列的情况
  • BCNF: 数据库表中不存在任何关键字段对任意候选关键字段(组合关键字)的传递函数依赖
1
2
3
4
5
6
7
8
9
10
/*
2NF:
例如 订单明细表(orderDetail): orderId, productId, productName, unitPrice, discount, quantity; 主键为 (orderId, productId). 一个订单可以包含多个商品.
discount, quantity 完全依赖主键, 而 unitPrice, productName 只依赖于 productId, 不符合 2NF.
将 unitPrice, productName 和 productId 拆分为单独的表消除原订单明细表 unitPrice, productName 多次重复的情况
3NF:
例如 订单表(order): orderId, orderDate, customerId, customerName, customerAddr, customerCity; 主键为 orderId
customerName, customerAddr, customerCity 直接依赖 customerId(非主键列), 通过传递才依赖主键, 所以不符合 3NF.
将 customerName, customerAddr, customerCity 拆分为单独的表达到满足 3NF.
*/

事务隔离级别

mysql 事务隔离级别定义了一个事务在多大程度上能够看到其他并发事务所做的修改

1
2
3
4
5
6
7
8
9
10
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL <level>;

-- 全局设置
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 当前会话设置
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 事务开始时设置
SET TRANSACTION ISOLATION LEVEL <level>;

读未提交(Read Uncommitted)

最低级别的隔离, 允许一个事务读取另一个事务尚未提交的数据, 通常不推荐使用此级别, 除非对数据一致性要求非常低的场景

问题:

  • 脏读(Dirty Read), 一个事务可以读取到另一个事务未提交的数据, 如果该事务回滚, 则会导致数据不一致
  • 不可重复读(Non-repeatable Read), 在一个事务中多次读取同一数据可能会得到不同的结果
  • 幻读(Phantom Read), 在一个事务中执行相同的查询可能会返回不同的行集, 因为其他事务插入了新的行
1
2
3
4
5
6
7
8
9
10
11
12
-- 事务 A
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 暂时不提交
COMMIT;

-- 事务 B
START TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT balance FROM accounts WHERE id = 1;
-- 可能读取到 900 (脏读)
COMMIT;
阅读全文 »

聚合操作

操作处理多个文档并返回计算结果, 由 一个或多个处理文档的 阶段 组成

  • 每个阶段对输入文档执行一个操作
  • 从一个阶段输出的文档将传递到下一个阶段
  • 一个聚合管道可以返回针对文档组的结果

字段路径, 使用 $ 前缀启用字段路径表达式访问输入文档中的字段.

管道优化, 该阶段会尝试重塑管道以提高性能, 优先使用 $match、$sort、$limit、$skip 阶段限制进入管道的文档

限制

  • 结果大小限制, 每个文档均受 MB16 BSON 文档大小的限制的约束
  • 阶段数量限制, 单个管道中允许的聚合管道阶段数量最大为 1000 个
  • 内存限制, 6.0 开始 allowDiskUseByDefault 参数控制需要 100MB 以上内存容量来执行的管道阶段是否默认会将临时文件写入磁盘

db.[collectionName].aggregate() 方法运行的聚合管道不会修改集合中的文档, 除非管道包含 $merge$out 阶段

1
2
3
4
5
6
7
8
db.orders.aggregate([
// stage 1: Filter pizza order document by pizza size
{$match: {size: 'medium'}},
// stage 2: Group remaining document by pizza name and calcuate total quantity
{$group: {_id: '$name', totalQuantity: {$sum: "$quantity"}}},
// stage 3: Sort document by totalQuantity in descending order
{$sort: {totalQuantity: -1}}
])

变量

变量可以保存任何 BSON 类型的数据, 访问变量时需要使用 $$ 前缀.

用户变量

变量名称可包含 ASCII 字符和任意非 ASCII 字符, 必须以小写 ASCII 字符开头

系统变量

  • NOW 返回当前日期时间值的变量, 为部署的所有成员返回相同的值, 并在聚合管道的所有阶段保持不变.
  • CLUSTER_TIME 返回当前时间戳值的变量
    • 仅适用于副本集和分片的集群
    • 为部署的所有节点返回相同的值, 并在管道的所有阶段保持不变
  • ROOT 引用根文档, 即当前正在聚合管道阶段处理的顶层文档
    • 引用聚合管道中当前正在处理的完整文档
    • 常用于需要保留原始文档内容的场景
    • 在 $group、$project 等阶段特别有用
  • CURRENT 引用聚合管道阶段正在处理的 字段路径 的起始位置
  • REMOVE 一个求值为缺失的变量, 允许排除 $addFields 和 $project 阶段的字段
  • DESCEND $redact 表达式的允许结果之一, 返回当前文档级别的字段, 不包括嵌入式文档
  • PRUNE $redact 表达式的允许结果之一, 排除当前文档/嵌入式文档级别的所有字段, 而不进一步检查任何已排除的字段
  • KEEP $redact 表达式的允许结果之一, 返回或保留此当前文档/嵌入式文档级别的所有字段, 而不进一步检查此级别的字段
  • SEARCH_META search 查询元数据结果的变量, 在所有支持的聚合管道阶段中, 设立变量 $SEARCH_META 的字段会返回查询的元数据结果
  • USER_ROLES 返回分配给当前用户的角色
阅读全文 »

1
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
{
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.removeUnusedImports": "explicit",
},
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.removeUnusedImports": "explicit",
},
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.removeUnusedImports": "explicit",
},
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar",
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.removeUnusedImports": "explicit"
}
},
}

命令行输出内容变身

格式: \033[显示方式;前景色;背景色 m …… \033[0m

  • \033[ 固定格式
  • \033[0m 非必需, 如果省略表示后面输出内容的样式都会应用当前设置的样式

属性集

前景色 背景色 色值
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

显示方式

显示方式 表现行为
0 默认
1 高亮
4 下划线
5 闪烁
7 反色
8 不可见
1
2
3
4
5
6
7
8
# 输出字体为绿色的 你好hello world
[root@localhost ~]# printf '\033[1;32m你好hello world\033[0m\n'
# 输出字体为绿色并带有下划线的 你好hello world
[root@localhost ~]# printf '\033[4;32m你好hello world\033[0m\n'
# 输出背景色为绿色的 你好hello world
[root@localhost ~]# printf '\033[7;32m你好hello world\033[0m\n'
# 输出内容不可见
[root@localhost ~]# printf '\033[8;32m你好hello world\033[0m\n'
阅读全文 »

systemd

systemd(system daemon)是 linux 下的一种 init 软件, 提供更优秀的框架以表示系统服务间的依赖关系, 并依此实现系统初始化时服务的并行启动, 同时达到降低 shell 的系统开销的效果, 最终代替常用的 System V 与 BSD 风格 init 程序

  • 采用 socket 激活式与总线激活式服务, 以提高相互依赖的各服务的并行运行性能
  • 采用 cgroup 代替 PID 来追踪进程, 依此即使是两次 fork 之后生成的守护进程也不会脱离 systemd 的控制

CGroup

cgroup 是 linux 内核的一个功能, 用来限制、控制与分离一个进程组的资源(如 CPU、内存、磁盘输入输出等)

cgroup 是 linux 内核提供的一种机制, 这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内, 从而为系统资源管理提供一个统一的框架. 简单说, cgroup 可以限制、记录任务组所使用的物理资源, 本质上来说, cgroup 是内核附加在程序上的一系列钩子(hook), 通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的.

作用

  • 资源限制: cgroup 可以对任务需要的资源总额进行限制, 例如设定任务运行使用的内存上限, 一旦超出就触发 OOM
  • 优先级分配: 通过分配的 CPU 时间片数量和磁盘 IO 带宽, 实际上就等于控制了任务运行的优先级
  • 资源统计: cgroup 可以统计系统的资源使用量, 例如 CPU 使用时长、内存使用量等
  • 任务控制: cgroup 可以对任务执行挂起、恢复等操作
阅读全文 »

敲黑板

onMenuShareAppMessage (微信提示: 即将废弃)

  • jweixin-1.4.0.js

企微(4.0.6) 中使用此 API 的位置

  • 转发
  • 转发给客户
  • 群发到客户群
  • 发表到客户的朋友圈
  • 分享到同事吧
  • 分享到微信
  • 分享到微信朋友圈使用此 onMenuShareTimeline, 但无法设置分享信息
阅读全文 »

Docker Compose

  • Docker Compose 以服务为单位, 将为每一个服务部署一个容器
  • 默认以 应用名称-服务名称-数字 方式作为容器名称
  • 默认以 应用名称_数据卷名 方式作为数据卷名称
  • 默认以 应用名称_网络名 方式作为网络名称

Docker Compose 是定义和运行多容器 Docker 应用程序的工具, 运行部分命令时需要在 compose.yaml/docker-compose.yaml 文件所在目录中, 以 应用名称-服务名称-数字 编号为规则命名容器, 配置文件使用 yaml 语法, yaml 是一个可读性高,用来表达数据序列化的格式.

yaml 文件中不能使用 tab 缩进, 只能使用空格

1
2
3
4
${VAR:-default}   如果 变量名 对应的环境变量未设置或为空, 则使用 默认值, 否则使用环境变量的值 
${VAR-default} 仅当 变量名 对应的环境变量 完全未定义 时才用默认值(为空时不会替换)
${VAR:?error} 严格模式, 如果 变量名 对应的环境变量 未设置/为空, 则报错并显示错误信息 error
${VAR:+alternate} 反向逻辑, 如果 变量名 已设置且非空, 则使用 alternate
1
2
3
4
# 启动指定服务, 不加参数则默认启动所有服务
docker compose -f -p -c --env-file .env.development up [service_name]

# 以下的命令不带服务名称则默认对所有服务执行相同操作
阅读全文 »

Docker Swarm

介绍

Swarm 是 Docker 官方提供的一款集群管理工具, 其主要作用是把若干台 Docker 主机抽象为一个整体, 并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源

从集群角度来说, 一个 Swarm 由一个或多个 Docker 节点组成. 这些节点可以是物理服务器、虚拟机、树莓派(Raspberry Pi)或云实例. 唯一的前提就是要求所有节点通过可靠的网络相连

节点会被配置为管理节点(Manager)或工作节点(Worker). 管理节点负责集群控制面(Control Plane), 进行诸如监控集群状态、分发任务至工作节点等操作. 工作节点接收来自管理节点的任务并执行.

Swarm 的配置和状态信息保存在一套位于所有管理节点上的分布式 etcd 数据库中. 该数据库运行于内存中, 并保持数据的最新状态. 关于该数据库最棒的是, 它几乎不需要任何配置, 作为 Swarm 的一部分被安装, 无须管理

  • Swarm 和 Kubernetes 比较类似, 但是更加轻, 具有的功能也较 kubernetes 更少一些
  • Docker Swarm 包含两方面:一个企业级的 Docker 安全集群, 以及一个微服务应用编排引擎
  • Swarm 默认内置有加密的分布式集群存储(encrypted distributed cluster store)、加密网络(Encrypted Network)、公用 TLS(Mutual TLS)、安全集群接入令牌 Secure Cluster Join Token)以及一套简化数字证书管理的 PKI(Public Key Infrastructure). 我们可以自如地添加或删除节点
  • 编排方面, Swarm 提供了一套丰富的 API 使得部署和管理复杂的微服务应用变得易如反掌. 通过将应用定义在声明式配置文件中, 就可以使用原生的 Docker 命令完成部署

docker-7

令牌格式

1
2
3
PREFIX - VERSION - SWARM ID - TOKEN

SWMTKN-1-5uqag7ddbx6jp9l273blxmda6308l5cn23487hbwsnw71w6dsh-eh4h7yhzchi0p6cy2ihg539jh
  • PREFIX 令牌前缀,便于区分 固定为 SWMTKN
  • VERSION Swarm 的版本信息
  • SWARM ID Swarm 认证信息的一个哈希值
  • TOKEN 标识管理节点还是工作节点的准入令牌

初始化 init

  • --advertise-addr 指定其他节点用来连接到当前管理节点的 IP 和端口, 当节点上有多个 IP 时指定
  • --listen-addr 指定用于承载 Swarm 流量的 IP 和端口. 其设置通常与 --advertise-addr 相匹配, 但是当节点上有多个 IP 的时候,可用于指定具体某个 IP
  • --autolock 启用锁

开放端口

  • 每个节点都需要安装 Docker, 并且能够与 Swarm 的其他节点通信

需要在路由器和防火墙中开放如下端口

  • 2377/tcp: 用于客户端与 Swarm 进行安全通信
  • 7946/tcp 与 7946/udp: 用于控制面 gossip 分发
  • 4789/udp: 用于基于 VXLAN 的覆盖网络
1
2
3
4
5
6
7
8
[root@localhost ~]# docker swarm init --advertise-addr 192.168.1.2 --listen-addr 192.168.1.2
Swarm initialized: current node (5r1q8c5jaawi9w1wd8yr7w3u2) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-5uqag7ddbx6jp9l273blxmda6308l5cn23487hbwsnw71w6dsh-eh4h7yhzchi0p6cy2ihg539jh 192.168.1.2:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
阅读全文 »