0%

Lua 是一门强大、快速、轻量的嵌入式动态类型脚本语言, 使用 ANSI C 语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中, 从而为应用程序提供灵活的扩展和定制功能

数据类型

Lua 有八种基本数据类型: nil、boolean、number、string、function、userdata、thread、table

  • nil 表示一个有意义的值不存在时的状态, nil 和 false 逻辑表达式中都表示假, 其他任何值都表示真
  • userdata 表示任意存储在变量中的 C 数据, 完全用户数据: 指一块由 Lua 管理的内存对应的对象; 轻量用户数据: 指一个简单的 C 指针
  • table 本质是一个关联数组, 数组的索引可以是数字、字符串或表类型, 下标默认从 1 开始, table 可以包含任何类型的值(nil 除外), 任何键的值若为 nil 就不会被记入表内, table 的创建通过 构造表达式 {} 完成

table、function、thread、userdata 在 Lua 中是引用类型, 对其操作都是针对引用而不是针对值的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print("数据类型: nil boolean number string userdata function trhead table")
print("nil 表示一个无效值(在条件表达式中相当于false)")
print("boolean 表示 true 和 false, 除了 nil 和 false 值表示为 false, 其他值(包括0)都为 true, ")
print("number 表示双精度类型的实浮点数, 数字字符串相加将转换成数字相加")
print("string 表示一对双引号或者单引号包含的内容, [[ 内容 ]] 表示块字符串, .. 字符串拼接, # 计算字符串或表的长度")
print("userdata 表示任意存储在变量中的 C 数据结构")
print("function 由 C 或 Lua 编写的函数")
print("thread 表示执行的独立线程, 用于执行协同程序")
print("table 其实是一个关联数组, 数组的索引可以是数字、字符串或者表类型, 下标默认从 1 开始, table 的创建通过'构造表达式'完成, 空表: {}")
print("---------------------------------------")

print("变量的三种类型: 全局变量, 局部变量(local 声明), 表中的域")
print("变量批量赋值时, 多余的变量会赋值为 nil, 多余的值会被忽略")
print("---------------------------------------")
阅读全文 »

Lists 命令

Redis 3.2 之后, List 数据类型底层使用 quickList 代替双向链表和压缩列表

List 是一个有序重复的双向链表, 按照添加的顺序排序, 可以添加一个元素到列表的头部(左边)、尾部(右边), 一个列表最多可以包含 2^32-1(40 多亿) 个元素.

List 类型的底层数据结构是由双向链表压缩列表实现的

  • 如果列表元素的个数小于 512 个,列表每个元素值都小于 64B 时, Redis 使用压缩列表作为底层数据结构
  • 如果列表元素不满足上面的条件, Redis 使用双向链表作为底层数据结构
1
2
3
# 配置底层数据结构存储数量限制
hash-max-listpack-entries 512
hash-max-listpack-value 64

添加元素

LPUSH 和 LPUSHX 命令将多个元素逆序插入到列表头部

  • LPUSH key element [element …] 批量添加多个元素到列表头部并返回列表的长度, 列表为空或者不存在新建
  • LPUSHX key element [element …] 批量添加多个元素到已存在的列表头部并返回列表的长度, 列表为空或者不存在返回 0
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
127.0.0.1:6379> LPUSH list:zhang name1 name2 name3
(integer) 3
127.0.0.1:6379> LPUSHX list:zhang name1 name4 name5 name6
(integer) 7
127.0.0.1:6379> LPUSH list:zhang name1 name4 name5 name6
(integer) 11

# LPUSH 和 LPUSHX 命令将多个元素**逆序**插入到列表头部
127.0.0.1:6379> LRANGE list:zhang 0 11
1) "name6"
2) "name5"
3) "name4"
4) "name1"
5) "name6"
6) "name5"
7) "name4"
8) "name1"
9) "name3"
10) "name2"
11) "name1"

# LPUSHX 对空列表或不存在的列表不进行操作
127.0.0.1:6379> LPUSHX list:zhang:1 name1 name2 name3
(integer) 0
127.0.0.1:6379> KEYS *
1) "list:zhang"
2) "age"
3) "name"
4) "hash:zhang"
阅读全文 »

HyperLogLog

HyperLogLog 是用来做基数统计的算法, 优点是在输入元素的数量或者体积非常大时, 计算基数所需的空间总是固定的、并且是很小的. 每个 HyperLogLog 键只需要花费 12KB 内存, 就可以计算接近 2^64 个不同元素的基数, 并产生标准误差接近于 0.81% 的近似值, 因为 HyperLogLog 只会根据输入元素来计算基数, 而不会储存输入元素本身

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为 5. 基数估计就是在误差可接受的范围内,快速计算基数

  • PFADD key [element [element …]] 添加元素

  • PFCOUNT key [key …] 根据 key 计算基数并返回, 0 表示 key 不存在

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> PFADD hll foo bar zap
(integer) 1
127.0.0.1:6379> PFADD hll zap zap zap
(integer) 0
127.0.0.1:6379> PFADD hll foo bar
(integer) 0
127.0.0.1:6379> PFCOUNT hll
(integer) 3
127.0.0.1:6379> PFADD other-hll 1 2 3
(integer) 1
127.0.0.1:6379> PFCOUNT hll other-hll
(integer) 6
阅读全文 »

Sets 命令

Set 是无序不重复的集合, 集合成员是唯一的, 集合对象的编码可以是 intset 或者 hashtable, 集合是通过哈希表实现的, 最大的成员数为 2^32-1(40 多亿)个成员.

Set: 键名: key, 键类型: set, 键值: string

Set 类型的底层数据结构是由哈希表整数集合实现的

  • 如果集合中的元素都是整数且元素个数小于 512 个, Redis 使用整数集合作为底层数据结构
  • 如果集合中的元素不满足上面条件, Redis 使用哈希表作为底层数据结构
1
2
# 配置底层数据结构存储数量限制
set-max-intset-entries 512

成员操作

  • SADD key member [member …] 向集合中添加多个成员并返回添加成功的数量, 0 表示有重复成员

  • SCARD key 获取集合成员的数量, 集合为空或者不存在返回 0

  • SMEMBERS key 获取集合中所有的成员, 集合为空或者不存在返回 (empty array)

是否包含成员
  • SISMEMBER key member 判断 member 是不是集合的成员, 1 是, 0 不是或者集合为空或者不存在
  • SMISMEMBER key member [member …] 批量判断多个 member 是不是集合的成员, 1 是, 0 不是或者集合为空或者不存在, Redis 6.2.0 支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
127.0.0.1:6379> KEYS *  # 查看当前数据库中的 key
(empty array)
# 空集合判断是否包含成员
127.0.0.1:6379> SMISMEMBER myset hello hehe
1) (integer) 0
2) (integer) 0
# 向 myset 添加成员
127.0.0.1:6379> SADD myset hello world hehe haha gg
(integer)
# 判断 myset 是否包含成员
127.0.0.1:6379> SMISMEMBER myset hello yy hehe
1) (integer) 1
2) (integer) 0
3) (integer) 1
阅读全文 »

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

阅读全文 »

命令行输出内容变身

格式: \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'

ssh 操作

  • ssh-keyscan 收集公钥中的主机地址
  • ssh-copy-id 将本地的公钥文件复制到远程主机对应账户下的 authorized_keys 文件中
  • ssh-keygen 生成非对称密钥对
阅读全文 »

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 网络

Docker 网络架构源自一种叫作容器网络模型(CNM)的方案, 该方案是开源的并且支持插接式连接

Libnetwork 是 Docker 对 CNM 的一种实现, 提供了 Docker 核心网络架构的全部功能. 不同的驱动可以通过插拔的方式接入 Libnetwork 来提供定制化的网络拓扑

CNM 定义了 3 个基本要素:沙盒(Sandbox)、终端(Endpoint)和网络(Network)

  • 沙盒是一个独立的网络栈, 其中包括以太网接口、端口、路由表以及 DNS 配置
  • 终端就是虚拟网络接口。就像普通网络接口一样,终端主要职责是负责创建连接. 在 CNM 中, 终端负责将沙盒连接到网络
  • 网络是 802.1d 网桥(类似大家熟知的交换机)的软件实现. 因此, 网络就是需要交互的终端的集合, 并且终端之间相互独立

docker 网络采用 veth-pair 技术, 每次启动容器时会自动创建一对虚拟网络设备接口, 一端连着网络协议栈, 一端彼此相连, 停止容器时自动删除, docker0 网卡作为中间的桥梁, 常见的网络模式包含 bridge, host, none, container, overlay 等.

阅读全文 »