增加部分文档

This commit is contained in:
zhengchiliu 2026-04-09 01:28:15 +08:00
parent 1231a6be15
commit 39bf1884ec
35 changed files with 8586 additions and 1812 deletions

View File

@ -1,130 +1,143 @@
## 1、文本分析概览
# 文本分析
Linux 中很多日志分析和数据整理工作,都依赖文本分析命令。常见工具包括:
> Linux 日志分析与数据整理的常用命令。
- `wc`:统计文本信息
- `sort`:排序
- `uniq`:去重或统计重复次数
- `cut`:按列提取内容
---
它们经常和管道一起使用,是文本处理的基础组合。
## 1. 命令概览
## 2、`wc`
| 命令 | 用途 |
|------|------|
| `wc` | 统计行数、单词数、字节数 |
| `sort` | 文本排序 |
| `uniq` | 去重、统计重复次数 |
| `cut` | 按列提取 |
`wc` 用于统计文本的行数、单词数、字节数等。
这些命令常通过管道组合使用,是文本处理的基础工具
### 2.1 常见选项
---
- `-l`:统计行数
- `-w`:统计单词数
- `-c`:统计字节数
## 2. `wc` - 文本统计
### 2.2 示例
### 常用选项
```shell
| 选项 | 说明 |
|------|------|
| `-l` | 统计行数 |
| `-w` | 统计单词数 |
| `-c` | 统计字节数 |
### 示例
```bash
# 统计文件行数
wc -l access.log
```
用于统计文件共有多少行。
---
## 3、`sort`
## 3. `sort` - 文本排序
`sort` 用于对文本内容进行排序,默认输出到标准输出,不会直接修改原文件。
> 默认输出到标准输出,不会修改原文件。
### 3.1 常见选项
### 常用选项
- `-R`:随机排序
- `-n`:按数值大小排序
- `-h`:按人类可读格式排序,例如 `1K``2M`
- `-u`:排序后去重
- `-r`:逆序排序
| 选项 | 说明 |
|------|------|
| `-n` | 按数值排序 |
| `-h` | 按人类可读格式排序1K、2M |
| `-u` | 排序后去重 |
| `-k` | 按第几列排序 |
| `-t` | 指定分隔符 |
| `-r` | 逆序排序 |
| `-R` | 随机排序 |
### 3.2 示例
### 示例
```shell
sort -n scores.txt
```bash
sort -n scores.txt # 按数值排序
sort -h disk_usage.txt # 按人类可读格式排序
```
```shell
sort -h disk_usage.txt
```
---
## 4`uniq`
## 4. `uniq` - 去重与统计
`uniq` 用于去除**相邻重复行**,因此通常会先配合 `sort` 使用。
> 只能去除**相邻重复行**,需先配合 `sort` 使用。
### 4.1 常见选项
### 常用选项
- `-c`:统计每行重复次数
- `-d`:只显示重复行
- `-u`:只显示不重复行
| 选项 | 说明 |
|------|------|
| `-c` | 统计每行重复次数 |
| `-d` | 只显示重复行 |
| `-u` | 只显示不重复行 |
### 4.2 示例
### 示例
```shell
```bash
# 统计高频内容
sort access.log | uniq -c | sort -nr | head
```
这个组合常用于统计高频内容。
---
## 5`cut`
## 5. `cut` - 按列提取
`cut` 用于按列或按字符位置提取文本。
### 常用选项
### 5.1 常见选项
| 选项 | 说明 |
|------|------|
| `-d` | 指定分隔符 |
| `-f` | 按字段提取 |
| `-c` | 按字符位置提取 |
- `-d`:指定分隔符
- `-c`:按字符位置提取
- `-f`:按字段提取
### 示例
### 5.2 示例
按冒号分隔提取 `/etc/passwd` 的第一列和第三列:
```shell
```bash
# 提取第一列和第三列(以冒号分隔)
cut -d: -f1,3 /etc/passwd
```
## 6、常见组合用法
---
### 6.1 统计访问次数最多的请求来源
## 6. 实战组合
```shell
### 统计访问次数最多的来源
```bash
cut -d" " -f1 access_log | sort | uniq -c | sort -nr | head -3
```
这条命令的思路是:
**执行流程:**
1. `cut` → 提取第一列
2. `sort` → 排序(让相同内容相邻)
3. `uniq -c` → 统计重复次数
4. `sort -nr` → 按数字逆序
5. `head -3` → 取前 3 条
- 用 `cut` 取出第一列
- 用 `sort` 排序
- 用 `uniq -c` 统计重复次数
- 再按数字逆序排序
- 用 `head` 取前 3 条
### 统计文件行数
### 6.2 统计某个文件有多少行
```shell
```bash
wc -l file.txt
```
### 6.3 查看唯一用户列表
### 获取唯一用户列表
```shell
```bash
cut -d: -f1 /etc/passwd | sort -u
```
## 7、实战建议
---
- 只做统计:优先考虑 `wc`
- 只做排序:优先考虑 `sort`
- 去重或重复次数统计:优先考虑 `sort | uniq`
- 按列提取:优先考虑 `cut`
- 一旦涉及多步分析,优先用管道把几个命令串起来
## 7. 小结
## 8、小结
| 场景 | 推荐命令 |
|------|---------|
| 统计数量 | `wc` |
| 排序 | `sort` |
| 去重/统计重复 | `sort \| uniq` |
| 按列提取 | `cut` |
| 多步分析 | 管道组合 |
- `wc` 用于统计
- `sort` 用于排序
- `uniq` 用于去重和统计重复行
- `cut` 用于按列抽取文本
- 这几个命令经常组合使用,是日志分析和文本整理的基础工具
掌握这些命令,可高效处理各类日志与文本数据。

View File

@ -1,179 +1,215 @@
## 1、Vim 概览
# 文本编辑 - Vim
Vim 是 Linux 中最常见的文本编辑器之一,特点是:
> Linux 中最常见的文本编辑器,适合终端快速编辑文件。
- 几乎所有 Linux 环境都能遇到
- 适合终端内快速编辑文件
- 对运维排障、改配置、写脚本都很常用
---
学习 Vim 的关键,不是死记命令,而是先理解它的**模式切换**。
## 1. 三种模式
## 2、Vim 的常见模式
### 2.1 普通模式
打开 Vim 后默认进入普通模式,用于:
- 移动光标
- 删除、复制、粘贴
- 查找
- 执行命令
### 2.2 插入模式
用于输入和编辑文本。
常见进入方式:
- `i`:在当前位置前插入
- `a`:在当前位置后插入
- `o`:在下一行插入
`Esc` 可以回到普通模式。
### 2.3 命令行模式
在普通模式下输入 `:` 进入,用于:
- 保存
- 退出
- 查找替换
- 设置选项
- 执行外部命令
## 3、常用命令操作
### 3.1 文件读写
- `:w`:保存文件
- `:q`:退出
- `:wq`:保存并退出
- `:q!`:强制退出不保存
- `:w filename`:另存为其他文件
- `:r filename`:把另一个文件内容读入当前文件
### 3.2 调用外部命令
- `:!command`:执行外部命令
- `:r !command`:读取命令输出到当前文件
示例:
```vim
:!ls
:r !date
```
┌─────────────────────────────────────┐
│ 插入模式 │
│ (i / a / o 进入,输入文本) │
└──────────────┬──────────────────────┘
│ Esc
┌─────────────────────────────────────┐
│ 普通模式 │
│ (默认模式,移动/删除/复制/查找) │
└──────────────┬──────────────────────┘
│ : 或 /
┌─────────────────────────────────────┐
│ 命令行模式 │
│ (:w / :q / :s/// / !cmd) │
└─────────────────────────────────────┘
```
### 3.3 删除、复制、粘贴
### 1.1 普通模式(默认)
- `d`:删除
- `dd`:删除当前行
- `y`:复制
- `yy`:复制当前行
- `p`:在后面粘贴
- `P`:在前面粘贴
- 移动光标、删除、复制、粘贴、查找、执行命令
### 3.4 撤销与恢复
### 1.2 插入模式
- `u`:撤销
- `Ctrl + r`:恢复撤销的内容
- `U`:某些版本中用于撤销当前行的修改,但现代 Vim 更常用 `u`
| 按键 | 说明 |
|------|------|
| `i` | 当前字符前插入 |
| `a` | 当前字符后插入 |
| `o` | 下一行插入新行 |
| `I` | 行首插入 |
| `A` | 行尾插入 |
| `O` | 上一行插入新行 |
## 4、常用设置项
`Esc` 返回普通模式。
以下命令通常在命令行模式执行:
### 1.3 命令行模式
- `:set nu`:显示行号
- `:set nonu`:取消行号
- `:set ic`:查找时忽略大小写
- `:set noic`:查找时区分大小写
- `:set ai`:启用自动缩进
- `:set noai`:关闭自动缩进
- `:set list`:显示不可见字符
- `:set nolist`:不显示不可见字符
在普通模式下输入 `:``/` 进入,用于保存、退出、查找替换、设置选项、执行外部命令。
### 4.1 加密说明
---
```vim
:set key=passwd
## 2. 基础操作
### 2.1 文件读写
| 命令 | 说明 |
|------|------|
| `:w` | 保存 |
| `:q` | 退出 |
| `:wq` | 保存并退出 |
| `:q!` | 强制退出不保存 |
| `:w filename` | 另存为 |
| `:r filename` | 读取文件内容到当前位置 |
### 2.2 调用外部命令
| 命令 | 说明 |
|------|------|
| `:!command` | 执行外部命令 |
| `:r !command` | 读取命令输出到当前文件 |
```bash
:!ls # 查看当前目录
:r !date # 插入当前日期
```
可以为文件设置编辑时的加密口令。
### 2.3 删除、复制、粘贴
```vim
:set key=
| 命令 | 说明 |
|------|------|
| `d` | 删除 |
| `dd` | 删除当前行 |
| `dw` | 删除当前单词 |
| `y` | 复制 |
| `yy` | 复制当前行 |
| `yw` | 复制当前单词 |
| `p` | 粘贴到后面 |
| `P` | 粘贴到前面 |
配合数字:`3dd` 删除 3 行,`2yy` 复制 2 行。
### 2.4 撤销与恢复
| 命令 | 说明 |
|------|------|
| `u` | 撤销 |
| `Ctrl + r` | 重做 |
| `U` | 撤销当前行修改 |
---
## 3. 多行编辑(重点)
### 3.1 可视模式Visual Mode
在普通模式下按 `v` 进入可视模式,选择区域后可执行删除、复制等操作。
| 按键 | 说明 |
|------|------|
| `v` | 进入字符可视模式 |
| `V` | 进入行可视模式 |
| `Ctrl + v` | 进入块可视模式(多列编辑) |
### 3.2 块可视模式(多列编辑)
`Ctrl + v` 进入块可视模式后:
1. **批量插入**:选中多行开头 → `I` → 输入内容 → `Esc`
2. **批量删除**:选中多列 → `d``x`
3. **批量替换**:选中多列 → `r` → 输入替换字符
**示例:在多行行首添加 `#` 注释**
```
1. Ctrl + v 进入块可视模式
2. j/k 或 G 选择多行
3. I 进入插入模式
4. 输入 #
5. Esc 退出(所有选中行行首都会添加 #
```
取消口令。
**示例:在多行行首删除 `#`**
不过这类方式现在并不是最常见的安全手段,实际生产中更常依赖系统权限和加密存储方案。
```
1. Ctrl + v 进入块可视模式
2. 选择 # 所在列
3. d 删除
```
## 5、查找与替换
### 3.3 批量缩进
### 5.1 查找
| 命令 | 说明 |
|------|------|
| `>` |向右缩进 |
| `<` |向左缩进 |
| `3>` |连续 3 行向右缩进 |
| `=` | 自动缩进选中区域 |
在普通模式下输入:
---
```vim
## 4. 查找与替换
### 4.1 查找
```
/关键字
n # 下一个
N # 上一个
```
然后:
### 4.2 替换
- `n`:向下查找下一个
- `N`:向上查找上一个
### 5.2 替换
基本格式:
```vim
```
:s/旧内容/新内容/修饰符
```
### 5.3 常见修饰符
| 修饰符 | 说明 |
|--------|------|
| `i` | 忽略大小写 |
| `g` | 全局替换(一行内全部) |
| `gc` | 逐个确认替换 |
- `i`:忽略大小写
- `g`:一行内全局替换
- `gc`:替换前逐个确认
### 4.3 常用示例
### 5.4 示例
替换当前行第一个 `old`
```vim
:s/old/new/
```bash
:s/old/new/ # 替换当前行第一个
:s/old/new/g # 替换当前行全部
:%s/old/new/g # 替换全文
:%s/old/new/gc # 替换全文(逐个确认)
:1,5s/old/new/g # 替换第 1-5 行
```
替换当前行全部 `old`
---
```vim
:s/old/new/g
## 5. 常用设置
| 命令 | 说明 |
|------|------|
| `:set nu` | 显示行号 |
| `:set nonu` | 隐藏行号 |
| `:set ic` | 忽略大小写查找 |
| `:set ai` | 自动缩进 |
| `:set list` | 显示不可见字符 |
| `:set wrap` | 自动换行 |
### 5.1 文件加密
```bash
:set key=password # 设置密码
:set key= # 取消密码
```
替换全文所有 `old`
> 注意:生产环境建议使用系统权限和专业的加密方案。
```vim
:%s/old/new/g
```
---
替换全文并逐个确认:
## 6. 小结
```vim
:%s/old/new/gc
```
| 场景 | 关键命令 |
|------|---------|
| 基础编辑 | `i``a``o``dd``yy``p` |
| 多行编辑 | `Ctrl + v` + `I` / `d` |
| 查找替换 | `/``:s///g` |
| 保存退出 | `:wq``:q!` |
## 6、日常使用建议
- 改系统配置文件前,先备份
- 编辑大文件时优先用查找和行号定位
- 做全局替换时,尽量先用 `gc` 确认,避免误改
- 需要长期使用时,可以把常用设置写入 `~/.vimrc`
## 7、小结
- Vim 的核心是理解普通模式、插入模式和命令行模式
- `:w``:q``:wq``:q!` 是最常用的保存退出命令
- `dd``yy``p``u` 是高频编辑命令
- `/` 查找和 `:%s///g` 替换是最常用功能
- 熟练掌握 Vim 后,终端下改配置文件会高效很多
掌握普通模式、插入模式、命令行模式 + 块可视模式,即可高效完成大多数编辑任务。

View File

@ -1,20 +1,164 @@
## 1、硬件管理概览
# 硬件管理
在 Linux 中查看硬件信息,常见关注点主要有三类:
> 本文档涵盖服务器硬件基础知识与 Linux 系统硬件信息查看方法。
- CPU核心数、线程数、架构、缓存、是否虚拟化
- 内存总量、可用量、缓存、Swap 使用情况
- 磁盘:设备、分区、文件系统类型、挂载点
---
做系统巡检或排障时,通常也是按这个顺序查看。
## 第一部分:硬件基础知识
## 2、查看 CPU 信息
### 1. CPU
### 2.1 使用 `lscpu`
#### 1.1 指令集
`lscpu` 是查看 CPU 信息最直观的命令,适合快速了解当前机器的处理器概况。
| 类型 | 代表架构 | 特点 |
|------|---------|------|
| **CISC**(复杂指令集) | X86、AMD64 | 指令丰富但复杂,执行速度慢,编译程序复杂 |
| **RISC**(精简指令集) | ARM | 指令精简MAC 已使用Windows 生态待完善 |
```shell
#### 1.2 主频
CPU 主频是 CPU 的时钟频率,单位 Hz。主频越高CPU 运算速度越快。
---
### 2. 存储
#### 2.1 ROM只读存储器
- **作用**:存放 BIOS 信息
- **特点**:断电后数据不丢失
#### 2.2 RAM随机存取存储器
##### DRAM
- **作用**:服务器的内存条
- **带宽计算**:内存带宽 = 内存总线频率 × 数据总线位数 / 8
##### SRAM
- **作用**:作为 CPU 内的高速缓存Cache
##### DRAM vs SRAM
| 特性 | DRAM | SRAM |
|------|------|------|
| 刷新电路 | 需要 | 不需要 |
| 性能 | 较低 | 高 |
| 价格 | 便宜 | 贵 |
| 集成度 | 高 | 低 |
##### 内存分级
```
CPU 寄存器L0 → L1 Cache → L2 Cache → L3 Cache → 内存DRAM → 本地磁盘 → 远程存储NAS
```
**为什么需要分级?** CPU 处理速度远快于 IO为避免 IO 阻塞CPU 优先从高速缓存读取数据。
**缓存未命中时**CPU 从 L1 找不到数据时会去 L2 查找,找到后会复制到 L1 以便后续快速访问。
---
### 3. 硬盘
#### 3.1 接口类型
| 接口 | 全称 | 速度 |
|------|------|------|
| **SATA** | Serial ATA | : 1.5Gb/sⅡ: 3Gb/sⅢ: 6Gb/s |
| **SAS** | Serial Attached SCSI | 更高 |
| **M.2** | 固态硬盘专用接口 | 10Gb/s |
> 注意:以上为接口最大带宽上限,不代表实际速度。
#### 3.2 结构分类
| 类型 | 组成 | 特点 |
|------|------|------|
| **机械 HDD** | 盘片、磁头、马达 | 成本低,容量大,寿命长 |
| **固态 SSD** | 闪存芯片、主控 | 速度快,无噪音,抗震动 |
#### 3.3 关键参数
- 容量、转速、传输速率、缓存
#### 3.4 磁盘尺寸
| 尺寸 | 应用场景 | 特点 |
|------|---------|------|
| **3.5 寸** | 企业级 | 转速快、容量大、需要外接电源 |
| **2.5 寸** | 个人电脑/便携 | 无需外接电源,支持热插拔 |
---
### 4. 网卡
| 类型 | 说明 |
|------|------|
| 板载网卡 | 主板集成 |
| PCIE 拓展卡 | 通过 PCIE 插槽扩展 |
---
### 5. 远程管理卡BMC
- **全称**Baseboard Manager Controller
- **特点**:服务器关机状态下也能运行
- **协议**IPMI
- **功能**:远程访问、查看状态、调整 BIOS、配置 RAID、安装系统、重启机器
---
### 6. 阵列卡RAID 卡)
- **作用**实现磁盘阵列RAID释放 CPU 资源,提供缓存和阵列保护
- **功能**RAID 建立/重建、错误检测、故障磁盘自动监测
#### RAID 级别对比
| 级别 | 最少盘数 | 冗余 | 性能 | 适用场景 |
|------|---------|------|------|---------|
| **RAID 0** | 2 | 无 | 最高 | 不考虑数据安全的场景 |
| **RAID 1** | 2 | 镜像 | 读快写慢 | 系统盘、关键数据 |
| **RAID 5** | 3 | 校验 | 平衡 | 通用业务数据 |
| **RAID 6** | 4 | 双校验 | 较高 | 高可靠性场景 |
| **RAID 10** | 4 | 镜像+条带 | 高 | 数据库、高 IO 应用 |
---
### 7. 电源
| 类型 | 说明 |
|------|------|
| 服务器电源 | 通常采用双电源冗余 |
| UPS不间断电源 | 稳压,市电异常时提供备用供电 |
---
### 8. 显卡
| 类型 | 说明 |
|------|------|
| 亮机卡 | 服务器显示输出用,通常为集成显卡 |
| 专业卡 | 图形渲染用,非服务器必选 |
---
### 9. 机柜
- **计量单位**U1U ≈ 4.5cm
- **用途**:标准 19 英寸机架式服务器安装
---
## 第二部分Linux 硬件信息查看
### 2.1 查看 CPU 信息
#### 使用 `lscpu`
```bash
[root@tencentos ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
@ -36,179 +180,132 @@ L2 cache: 4096K
L3 cache: 36608K
```
### 2.2 重点字段说明
#### 关键字段说明
- `Architecture`CPU 架构,例如 `x86_64` 表示 64 位架构
- `CPU op-mode(s)`CPU 支持运行 32 位和 64 位操作系统
- `CPU(s)`:逻辑 CPU 数量,不一定等于物理核心数
- `Thread(s) per core`:每个核心的线程数,开启超线程时通常大于 1
- `Core(s) per socket`:每个物理 CPU 的核心数
- `Socket(s)`:物理 CPU 颗数
- `Model name`CPU 型号
- `Hypervisor vendor`:当前是否运行在虚拟化环境中,例如 KVM
- `L1/L2/L3 cache`:不同层级的 CPU 缓存大小
| 字段 | 含义 |
|------|------|
| Architecture | CPU 架构,如 x86_64 |
| CPU(s) | 逻辑 CPU 数量 |
| Thread(s) per core | 每核心线程数(超线程 >1 |
| Core(s) per socket | 每颗物理 CPU 的核心数 |
| Socket(s) | 物理 CPU 颗数 |
| Model name | CPU 型号 |
| Hypervisor vendor | 虚拟化环境(如 KVM |
| L1/L2/L3 cache | 各层级缓存大小 |
### 2.3 使用 `/proc/cpuinfo`
#### 使用 `/proc/cpuinfo`
如果你想看更底层、更详细的信息,可以直接查看:
```shell
```bash
[root@tencentos ~]# cat /proc/cpuinfo
```
这个文件会按每个逻辑 CPU 分别列出详细参数,例如:
可查看processor、vendor_id、model name、cpu MHz、cache size、flags、bugs 等详细信息。
- `processor`:逻辑 CPU 编号
- `vendor_id`CPU 厂商
- `model name`CPU 型号名称
- `cpu MHz`:当前频率
- `cache size`:缓存大小
- `flags`CPU 支持的指令集特性
- `bugs`:已知 CPU 漏洞或风险标记
- `address sizes`:物理地址和虚拟地址位数
#### 使用场景建议
### 2.4 使用场景建议
- **快速巡检**`lscpu`
- **深度分析**`/proc/cpuinfo`
- **判断虚拟机**:关注 `Hypervisor vendor`
- **计算核心/线程数**:结合 CPU(s) × Thread(s) × Core(s) × Socket(s)
- **快速巡检**:优先用 `lscpu`
- **查看更细节的 CPU 参数**:使用 `/proc/cpuinfo`
- **判断是否是虚拟机**:关注 `Hypervisor vendor`
- **判断核心、线程、物理 CPU 数**:结合 `CPU(s)``Thread(s) per core``Core(s) per socket``Socket(s)` 一起看
---
## 3、查看内存信息
### 2.2 查看内存信息
### 3.1 使用 `free -h`
#### 使用 `free -h`
`free` 是查看内存最常用的命令,`-h` 可以用更适合阅读的单位显示。
```shell
```bash
[root@tencentos ~]# free -h
total used free shared buff/cache available
Mem: 1.7Gi 323Mi 341Mi 35Mi 1.0Gi 1.2Gi
Swap: 0B 0B 0B
```
### 3.2 重点字段说明
#### 关键字段说明
- `total`:内存总量
- `used`:已使用内存
- `free`:完全空闲的内存
- `shared`:共享内存
- `buff/cache`:被缓冲区和页缓存占用的内存
- `available`:当前可供应用程序使用的内存,通常比 `free` 更有参考价值
- `Swap`:交换分区使用情况
| 字段 | 含义 |
|------|------|
| total | 内存总量 |
| used | 已使用内存 |
| free | 完全空闲 |
| shared | 共享内存 |
| buff/cache | 缓冲区和页缓存 |
| available | 可用内存(推荐关注) |
| Swap | 交换分区 |
### 3.3 使用 `/proc/meminfo`
#### 使用 `/proc/meminfo`
如果需要更完整的内存明细,可以查看:
```shell
```bash
[root@tencentos ~]# cat /proc/meminfo
```
其中比较常见字段
常见字段:MemTotal、MemFree、MemAvailable、Buffers、Cached、SwapTotal、SwapFree、Slab、Dirty
- `MemTotal`:物理内存总量
- `MemFree`:当前空闲内存
- `MemAvailable`:当前可用内存
- `Buffers`:块设备缓冲区使用量
- `Cached`:页缓存使用量
- `SwapTotal`Swap 总量
- `SwapFree`Swap 剩余量
- `Slab`:内核 slab 缓存占用
- `Dirty`:等待写回磁盘的数据量
#### 排障建议
### 3.4 排障时怎么看内存
- 日常巡检:`free -h`
- 重点关注 `available` 而非 `free`
- Swap 持续上升需关注内存压力
- 日常巡检时优先看 `free -h`
- 不要只盯着 `free`,应重点关注 `available`
- 如果 `Swap` 持续上升,通常需要关注内存压力
- 如果想进一步排查缓存、页表、HugePages 等问题,再看 `/proc/meminfo`
---
## 4、查看磁盘与分区信息
### 2.3 查看磁盘与分区
### 4.1 使用 `lsblk`
#### 使用 `lsblk`
`lsblk` 用于查看块设备、分区和挂载关系,是查看磁盘结构时最常用的命令之一。
```shell
```bash
[root@tencentos ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 50G 0 disk
└─vda1 253:1 0 50G 0 part /
```
### 4.2 重点字段说明
#### 使用 `/proc/partitions`
- `NAME`:设备名称
- `MAJ:MIN`:主设备号和次设备号
- `RM`:是否可移动设备,`1` 表示是,`0` 表示否
- `SIZE`:设备或分区大小
- `RO`:是否只读
- `TYPE`:设备类型,例如 `disk``part`
- `MOUNTPOINT`:挂载点
### 4.3 使用 `/proc/partitions`
```shell
```bash
[root@tencentos ~]# cat /proc/partitions
major minor #blocks name
253 0 52428800 vda
253 1 52427759 vda1
```
这个文件更偏底层,适合查看系统识别到的块设备和分区情况。
#### 使用 `blkid`
### 4.4 使用 `blkid`
`blkid` 可以查看设备的文件系统类型、UUID、分区 UUID 等信息。
```shell
```bash
[root@tencentos ~]# blkid
/dev/vda1: UUID="ded6c45d-0699-43e5-bc44-f31c21449dcc" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="5f3d9d70-01"
```
### 4.5 `blkid` 常见用途
- 查看文件系统类型ext4、xfs
- 获取 UUID 用于 /etc/fstab
- 查看文件系统类型,例如 `ext4``xfs`
- 获取 `UUID`,便于写入 `/etc/fstab`
- 排查磁盘挂载失败、设备识别异常等问题
---
## 5、常用巡检思路
### 2.4 常用巡检命令
如果只是做一次简单的硬件巡检,通常可以按下面的顺序:
### 5.1 看 CPU
```shell
```bash
# 1. 看 CPU
lscpu
```
关注:架构、核心数、线程数、虚拟化信息。
### 5.2 看内存
```shell
# 2. 看内存
free -h
```
关注总量、可用内存、Swap 是否被使用。
### 5.3 看磁盘
```shell
# 3. 看磁盘
lsblk
blkid
```
关注:磁盘和分区结构、挂载点、文件系统类型。
---
## 6、小结
## 小结
- `lscpu` 适合快速查看 CPU 总体情况
- `/proc/cpuinfo` 更详细,适合深入分析 CPU 参数
- `free -h` 是查看内存使用最常用的命令
- `/proc/meminfo` 提供更细的内存统计信息
- `lsblk` 适合看块设备和挂载关系
- `blkid` 适合看 UUID 和文件系统类型
| 命令 | 用途 |
|------|------|
| `lscpu` | CPU 概况 |
| `/proc/cpuinfo` | CPU 详细信息 |
| `free -h` | 内存使用情况 |
| `/proc/meminfo` | 内存详细统计 |
| `lsblk` | 块设备与挂载 |
| `blkid` | UUID 与文件系统类型 |
这几个命令已经能覆盖 Linux 中大部分基础硬件巡检场景。
掌握以上命令,可覆盖 Linux 基础硬件巡检的常见需求

View File

@ -0,0 +1,503 @@
# OpenSSL
> OpenSSL 是开源的 SSL/TLS 工具包,用于实现加密通信和数据安全。
---
## 1. 加密算法概述
### 1.1 对称加密
**特性**
- 加密和解密使用同一个密钥,效率高
- 将原始数据分割成固定大小的块,逐个进行加密
**缺陷**
- 密钥过多:需要管理大量密钥
- 密钥分发:安全分发密钥困难
- 数据来源无法确认
**常见算法**
| 算法 | 密钥长度 | 说明 |
|------|---------|------|
| DES | 56 bits | 废弃,安全性低 |
| 3DES | 168 bits | 废弃,兼容性差 |
| **AES** | 128/192/256 bits | 当前主流 |
| Blowfish | 可变 | 开源免费 |
| Twofish | 128/192/256 bits | AES 候选 |
**使用示例**
```bash
# 加密
openssl enc -aes-256-cbc -in plain.txt -out cipher.bin -pass pass:mypassword
# 解密
openssl enc -d -aes-256-cbc -in cipher.bin -pass pass:mypassword
```
### 1.2 非对称加密(公钥加密)
#### 1.2.1 基础概念
**密钥对**
- **公钥**public key公开给所有人用于加密
- **私钥**secret key自己留存用于解密/签名
**功能**
- 数据加密:适合加密较小数据(如对称密钥)
- 数字签名:确认发送方身份
**缺点**:密钥长、算法复杂、效率低
#### 1.2.2 加密原理
```
接收者 B
1. 生成密钥对 (公钥 Pb, 私钥 Sb)
2. 公开公钥 Pb保管好私钥 Sb
发送者 A
1. 使用接收者公钥 Pb 加密数据 M
2. 发送加密数据 Pb(M) 给 B
接收者 B
1. 使用私钥 Sb 解密
2. 得到原始数据 M = Sb(Pb(M))
```
#### 1.2.3 数字签名原理
```
发送者 A
1. 生成密钥对 (公钥 Pa, 私钥 Sa)
2. 公开公钥 Pa保管好私钥 Sa
3. 使用私钥 Sa 对数据 M 签名
4. 发送 (M, Sa(M)) 给接收者 B
接收者 B
1. 使用发送者公钥 Pa 验证签名
2. 验证通过 = 确认数据来自 A 且未被篡改
```
> **关键**:私钥签名,公钥验证。签名只能由私钥产生,任何人可用公钥验证。
#### 1.2.4 常见算法对比
| 算法 | 密钥长度 | 用途 | 安全性 | 性能 |
|------|---------|------|--------|------|
| **RSA** | 2048/4096 bits | 加密/签名 | 高 | 慢 |
| **DSA** | 1024/2048 bits | 仅签名 | 高 | 快 |
| **ECC** | 256/384 bits | 加密/签名 | 高 | 快 |
| **Ed25519** | 256 bits | 仅签名 | 最高 | 最快 |
#### 1.2.5 RSA 算法详解
**数学原理**
- 基于大整数分解难题
- 两个大素数相乘容易,但分解乘积困难
- RSA 取名来自 Rivest、Shamir、Adleman 三位发明者
**密钥生成过程**
```
1. 选择两个大素数 p 和 q
2. 计算 n = p × q
3. 计算 φ(n) = (p-1)(q-1)
4. 选择 e满足 1 < e < φ(n) gcd(e, φ(n)) = 1
5. 计算 d满足 d × e ≡ 1 (mod φ(n))
6. 公钥 = (n, e)
7. 私钥 = (n, d)
```
**数学公式**
```
加密M^e mod n = C
解密C^d mod n = M
签名H(M)^d mod n = S
验证S^e mod n = H(M)
```
**密钥长度选择**
| 密钥长度 | 安全性 | 推荐场景 |
|----------|--------|----------|
| 1024 bits | 不安全 | 已废弃 |
| 2048 bits | 安全 | 个人/小型业务 |
| 4096 bits | 高安全 | 金融/政府 |
#### 1.2.6 ECC椭圆曲线密码学
**优势**
- 相同安全强度下,密钥更短
- 256-bit ECC ≈ 2048-bit RSA
- 计算更快,资源消耗更低
**曲线类型**
| 曲线 | 密钥长度 | 应用 |
|------|---------|------|
| secp256r1 (P-256) | 256 bits | 通用 |
| secp384r1 (P-384) | 384 bits | 高安全 |
| secp521r1 (P-521) | 521 bits | 最高安全 |
**OpenSSL 生成 ECC 密钥**
```bash
# 生成 ECC 私钥secp256r1
openssl genpkey -algorithm EC -out ec Private key.pem -pkeyopt ec_paramgen_curve:secp256r1
# 生成 ECC CSR
openssl req -new -key ec_private.key -out request.csr
# 自签名 ECC 证书
openssl req -new -x509 -key ec_private.key -out cert.pem
```
#### 1.2.7 Ed25519现代签名算法
**特点**
- 现代签名算法,高性能
- 密钥短256 bits签名短64 bytes
- 安全性极高,无侧信道攻击风险
**生成密钥**
```bash
# Ed25519 私钥
openssl genpkey -algorithm ed25519 -out ed25519key.pem
# 自签名证书
openssl req -new -x509 -key ed25519key.pem -out cert.pem
```
#### 1.2.8 非对称加密实战
**RSA 加密文件**
```bash
# 方法1使用公钥加密
openssl rsautl -encrypt -pubin -inkey pub.key -in plaintext.txt -out ciphertext.bin
# 方法2使用私钥签名
openssl rsautl -sign -inkey priv.key -in data.txt -out signature.bin
```
**AES 密钥交换(混合加密)**
```bash
# 1. 生成随机 AES 密钥
openssl rand -hex 32 > aes.key
# 2. 用接收者公钥加密 AES 密钥
openssl rsautl -encrypt -pubin -inkey recipient_pub.key -in aes.key -out aes.key.enc
# 3. 用 AES 加密数据
openssl enc -aes-256-cbc -in data.txt -out data.enc -pass file:aes.key
# 接收者解密
# 1. 用私钥解密 AES 密钥
openssl rsautl -decrypt -inkey recipient_priv.key -in aes.key.enc -out aes.key
# 2. 用 AES 解密数据
openssl enc -d -aes-256-cbc -in data.enc -pass file:aes.key
```
#### 1.2.9 算法选择建议
| 场景 | 推荐算法 | 原因 |
|------|---------|------|
| HTTPS/TLS | ECDHE + RSA/ECDSA | 性能与安全平衡 |
| 代码签名 | Ed25519 或 RSA-2048 | 高安全性 |
| 文档签名 | Ed25519 | 快速、签名短 |
| 密钥交换 | ECDH 或 RSA | 成熟稳定 |
| IoT 设备 | ECC | 资源受限 |
---
## 2. 非对称加密算法详解
### 2.1 RSA
**生成 RSA 密钥**
```bash
# 标准 RSA 私钥2048位
openssl genrsa -out rsa_private.key 2048
# 带密码保护的 RSA 私钥
openssl genrsa -aes256 -out rsa_private.key 2048
# 提取公钥
openssl rsa -in rsa_private.key -pubout -out rsa_public.key
# 查看密钥信息
openssl rsa -in rsa_private.key -noout -text
```
**加解密**
```bash
# 加密(使用公钥)
openssl rsautl -encrypt -pubin -inkey pub.key -in plaintext.txt -out encrypted.bin
# 解密(使用私钥)
openssl rsautl -decrypt -inkey priv.key -in encrypted.bin -out decrypted.txt
# 签名(使用私钥)
openssl rsautl -sign -inkey priv.key -in data.txt -out signature.bin
# 验证(使用公钥)
openssl rsautl -verify -pubin -inkey pub.key -in signature.bin -signed data.txt
```
### 2.2 DSA
> DSA 仅用于签名,不能加密解密。
```bash
# 生成 DSA 参数
openssl dsaparam -out dsaparam.pem 2048
# 生成 DSA 私钥
openssl gendsaparam dsaparam.pem -out dsa_private.key
# 生成 CSR
openssl req -new -key dsa_private.key -out request.csr
# 签名
openssl dgst -sha256 -sign dsa_private.key -out signature.bin data.txt
```
### 2.3 DH密钥交换
```bash
# 生成 DH 参数
openssl dhparam -out dhparam.pem 2048
# 生成 DH 私钥
openssl genpkey -paramfile dhparam.pem -out dh_private.key
# 提取公钥
openssl pkey -in dh_private.key -pubout -out dh_public.key
```
---
## 3. 单向哈希算法
### 3.1 基础概念
将任意数据转换为固定长度的"指纹"(摘要)。
**特性**
- 任意长度输入,固定长度输出
- 雪崩效应:数据微小改变,指纹变化巨大
- 单向性:无法从指纹恢复原数据
### 3.2 常见算法
| 算法 | 输出长度 | 安全性 |
|------|---------|--------|
| md5 | 128 bits | 不安全,仅用于兼容性 |
| sha1 | 160 bits | 弱安全,不推荐 |
| sha256 | 256 bits | 推荐 |
| sha512 | 512 bits | 推荐 |
| blake2b | 可变 | 高性能,高安全 |
### 3.3 常用命令
```bash
echo -n "hello" | md5sum
sha256sum file
openssl dgst -sha256 file
带密钥的哈希HMAC
openssl dgst -sha256 -hmac "mykey" file
```
---
## 4. 密钥交换
### 4.1 DHDiffie-Hellman
让双方通过不安全信道建立共享密钥。
**原理**
```
A: 选取 g, p → 计算 g^a%p → 发送给 B
B: 选取 g, p → 计算 g^b%p → 发送给 A
A: 计算 (g^b%p)^a%p = g^ab%p → 密钥
B: 计算 (g^a%p)^b%p = g^ab%p → 密钥
```
> 私密数据 a、b 在生成密钥后丢弃,不长期存储,安全性高。
### 4.2 ECDH椭圆曲线 DH
更短密钥,更高安全性。
---
## 5. TLS/SSL 协议
### 5.1 协议版本
| 版本 | 年份 | 状态 |
|------|------|------|
| SSL 1.0 | 1994 | 从未公开 |
| SSL 2.0 | 1995 | 废弃,有漏洞 |
| SSL 3.0 | 1996 | 废弃POODLE |
| TLS 1.0 | 1999 | 废弃BEAST |
| TLS 1.1 | 2006 | 废弃 |
| **TLS 1.2** | 2008 | 推荐 |
| **TLS 1.3** | 2018 | 当前最佳 |
### 5.2 TLS 1.3 改进
- 更快的握手1-RTT / 0-RTT
- 移除不安全算法MD5、SHA1、RC4
- 前向保密FS强制
- 简化密码套件
### 5.3 密码套件格式
```
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
│ │ │ │ │
│ │ │ │ 摘要算法
│ │ │ 对称加密算法
│ │ 密钥协商算法
│ 签名算法
密钥交换算法
```
---
## 6. CA 与证书
### 6.1 PKI 架构
```
CA证书颁发机构
├── Root CA根CA- 自签,可信锚点
├── Intermediate CA中间CA- 签名子CA
└── 最终用户/服务器
```
### 6.2 证书格式
| 格式 | 说明 |
|------|------|
| PEM | Base64 文本 |
| DER | 二进制 |
| PKCS#12 | 含私钥(.pfx/.p12 |
| PKCS#7 | 证书链(.p7b/.p7c |
### 6.3 自建 CA 与证书管理
```bash
# 创建目录
mkdir -p /etc/pki/CA/{certs,crl,newcerts,private}
touch /etc/pki/CA/index.txt
echo 01 > /etc/pki/CA/serial
# CA 私钥
openssl genrsa -aes256 -out /etc/pki/CA/private/cakey.pem 2048
# 自签 CA
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650
# 用户申请证书
openssl genrsa -out user.key 2048
openssl req -new -key user.key -out user.csr
openssl ca -in user.csr -out user.crt -days 365
```
### 6.4 证书吊销
```bash
# 吊销证书
openssl ca -revoke /etc/pki/CA/newcerts/11.pem
# 查看状态
openssl ca -status 11
# 生成 CRL
openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem
```
---
## 7. 实战应用
### 7.1 生成强密钥
```bash
# RSA 4096位
openssl genrsa -aes256 4096 > server.key
# ECC
openssl genpkey -algorithm EC -out ec.key -pkeyopt ec_paramgen_curve:secp256r1
# Ed25519
openssl genpkey -algorithm ed25519 -out ed25519.key
```
### 7.2 测试 TLS 连接
```bash
openssl s_client -connect example.com:443 -showcerts
openssl s_client -tls1_2 -connect example.com:443
```
### 7.3 随机数与哈希
```bash
openssl rand -hex 32
openssl dgst -sha256 file
```
---
## 8. 常用命令速查
### 8.1 密钥操作
| 场景 | 命令 |
|------|------|
| 生成 RSA 私钥 | `openssl genrsa -out key.pem 2048` |
| 生成 RSA 私钥(带密码) | `openssl genrsa -aes256 -out key.pem 2048` |
| 提取公钥 | `openssl rsa -in key.pem -pubout -out pub.key` |
| 查看密钥 | `openssl rsa -in key.pem -noout -text` |
### 8.2 证书操作
| 场景 | 命令 |
|------|------|
| 生成 CSR | `openssl req -new -key key.pem -out req.csr` |
| 自签证书 | `openssl req -new -x509 -key key.pem -out cert.pem` |
| CA 签发 | `openssl ca -in req.csr -out cert.pem` |
| 验证证书 | `openssl verify -CAfile ca.pem cert.pem` |
| 查看证书 | `openssl x509 -in cert.pem -noout -text` |
### 8.3 加密/签名
| 场景 | 命令 |
|------|------|
| RSA 加密 | `openssl rsautl -encrypt -pubin -inkey pub.key -in f.txt -out f.enc` |
| RSA 解密 | `openssl rsautl -decrypt -inkey priv.key -in f.enc -out f.txt` |
| 签名 | `openssl dgst -sha256 -sign priv.key -out sig.bin data.txt` |
| 验证 | `openssl dgst -sha256 -verify pub.key -signature sig.bin data.txt` |
---
## 9. 小结
| 类别 | 用途 | 推荐算法 |
|------|------|----------|
| 对称加密 | 数据加密 | AES-256 |
| 非对称加密 | 密钥交换 | RSA-2048 / ECDH |
| 数字签名 | 身份认证 | Ed25519 / RSA-2048 / ECDSA |
| 单向哈希 | 完整性校验 | SHA-256 |
| 密钥交换 | 协商会话密钥 | ECDH / X25519 |
掌握非对称加密的核心概念:
- **公钥加密,私钥解密**:保密通信
- **私钥签名,公钥验证**:身份认证
- **混合加密**:用对称加密数据,用非对称加密密钥,兼顾效率与安全
> 生产环境推荐TLS 1.3 + ECDHE-ECDSA + AES-256-GCM + SHA-384

View File

@ -1,289 +0,0 @@
# MySQL 索引优化
索引就是为特定的mysql字段进行一些特定的算法排序比如二叉树的算法和哈希算法哈希算法是通过建立特征值然后根据特征值来快速查找。而用的最多并且是mysql默认的就是二叉树算法 BTREE通过BTREE算法建立索引的字段比如扫描20行就能得到未使用BTREE前扫描了2^20行的结果。
## Explain优化查询检测
EXPLAIN可以帮助开发人员分析SQL问题explain显示了mysql如何使用索引来处理select语句以及连接表可以帮助选择更好的索引和写出更优化的查询语句。
使用方法在select语句前加上Explain就可以了
```
Explain select * from peopleinfo where idCard = 167575863462536759;
```
执行explain 时后面的SQL语句是不会执行的。
**示例**
```
mysql> Explain select * from peopleinfo where idCard = 167575863462536759;
-- 结果:
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | peopleinfo | NULL | const | PRIMARY | PRIMARY | 8 | const | 1 | 100.00 | NULL |
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
select_type: SIMPLE -- 查询类型(简单查询、联合查询、子查询)
table: user -- 显示这一行的数据是关于哪张表的 。
type: range -- 区间索引在小于1990/2/2区间的数据)这是重要的列显示连接使用了何种类型。从最好到最差的连接类型为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL,const代表一次就命中ALL代表扫描了全表才确定结果。一般来说得保证查询至少达到range级别,最好能达到ref。
possible_keys: birthday -- 指出MySQL能使用哪个索引在该表中找到行。如果是空的没有相关的索引。这时要提高性能可通过检验WHERE子句看是否引用某些字段或者检查字段不是适合索引。
key: birthday -- 实际使用到的索引。如果为NULL则没有使用索引。如果为primary的话表示使用了主键。
key_len: 4 -- 最长的索引宽度。如果键是NULL长度就是NULL。在不损失精确性的情况下长度越短越好。
ref: const -- 显示哪个字段或常数与key一起被使用。
rows: 1 -- 这个数表示mysql要遍历多少数据才能找到在innodb上是不准确的。
Extra: Using where; Using index -- 执行状态说明这里可以看到的坏的例子是Using temporary和Using
```
**select_type**
1. simple:简单select不使用union或子查询
2. primary:最外面的select。
3. union:union中的第二个或后面的select语句。
4. dependent union:union中的第二个或后面的select语句取决于外面的查询。
5. union result:union的结果。
6. subquery:子查询中的第一个select。
7. dependent subquery:子查询中的第一个select取决于外面的查询。
8. derived:导出表的selectfrom子句的子查询
**其它说明**
1. Distinct:一旦MYSQL找到了与行相联合匹配的行就不再搜索了。
2. Not exists: MYSQL优化了LEFT JOIN一旦它找到了匹配LEFT JOIN标准的行就不再搜索了。
3. Range checked for each Record(index map:#):没有找到理想的索引因此对于从前面表中来的每一个行组合MYSQL检查使用哪个索引并用它来从表中返回行。这是使用索引的最慢的连接之一。
4. Using filesort: 看到这个的时候查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。
5. Using index: 列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候。
6. Using temporary 看到这个的时候查询需要优化了。这里MYSQL需要创建一个临时表来存储结果这通常发生在对不同的列集进行ORDER BY上而不是GROUP BY上。
7. Where used 使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行并且连接类型ALL或index这就会发生或者是查询有问题不同连接类型的解释按照效率高低的顺序排序
8. system 表只有一行system表。这是const连接类型的特殊情况。
9. const:表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待。
10. eq_ref:在连接中MYSQL在查询时从前面的表中对每一个记录的联合都从表中读取一个记录它在查询使用了索引为主键或惟一键的全部时使用。
11. ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于索引匹配的记录多少,越少越好。
12. range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
13. index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描比ALL更好因为索引一般小于表数据
14. ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免。
其中type:
1. 如果是Only index这意味着信息只用索引树中的信息检索出的这比扫描整个表要快。
2. 如果是where used就是使用上了where限制。
3. 如果是impossible where 表示用不着where一般就是没查出来啥。
4. 如果此信息显示Using filesort或者Using temporary的话会很吃力WHERE和ORDER BY的索引经常无法兼顾如果按照WHERE来确定索引那么在ORDER BY时就必然会引起Using filesort这就要看是先过滤再排序划算还是先排序再过滤划算。
## 索引的类型
**UNIQUE唯一索引**
不可以出现相同的值可以有NULL值。
**INDEX普通索引**
允许出现相同的索引内容。
**PRIMARY KEY主键索引**
不允许出现相同的值且不能为NULL值一个表只能有一个primary_key索引。
**fulltext index 全文索引**
上述三种索引都是针对列的值发挥作用但全文索引可以针对值中的某个单词比如一篇文章中的某个词然而并没有什么卵用因为只有myisam以及英文支持并且效率让人不敢恭维但是可以用coreseek和xunsearch等第三方应用来完成这个需求。
## 索引的CURD
**索引的创建**
ALTER TABLE
适用于表创建完毕之后再添加。
ALTER TABLE 表名 ADD 索引类型 (unique,primary key,fulltext,index)[索引名](字段名)
```
ALTER TABLE `table_name` ADD INDEX `index_name` (`column_list`) -- 索引名,可要可不要;如果不要,当前的索引名就是该字段名。
ALTER TABLE `table_name` ADD UNIQUE (`column_list`)
ALTER TABLE `table_name` ADD PRIMARY KEY (`column_list`)
ALTER TABLE `table_name` ADD FULLTEXT KEY (`column_list`)
```
CREATE INDEX
CREATE INDEX可对表增加普通索引或UNIQUE索引。
```
--例:只能添加这两种索引
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)
```
**另外,还可以在建表时添加:**
```
CREATE TABLE `test1` (
`id` smallint(5) UNSIGNED AUTO_INCREMENT NOT NULL, -- 注意,下面创建了主键索引,这里就不用创建了
`username` varchar(64) NOT NULL COMMENT '用户名',
`nickname` varchar(50) NOT NULL COMMENT '昵称/姓名',
`intro` text,
PRIMARY KEY (`id`),
UNIQUE KEY `unique1` (`username`), -- 索引名称,可要可不要,不要就是和列名一样
KEY `index1` (`nickname`),
FULLTEXT KEY `intro` (`intro`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='后台用户表';
```
**索引的删除**
```
DROP INDEX `index_name` ON `talbe_name`
ALTER TABLE `table_name` DROP INDEX `index_name`
-- 这两句都是等价的,都是删除掉table_name中的索引index_name;
ALTER TABLE `table_name` DROP PRIMARY KEY -- 删除主键索引,注意主键索引只能用这种方式删除
```
**索引的查看**
```
show index from tablename;
```
**索引的更改**
更改个毛线,删掉重建一个既可
## 创建索引的技巧
1. 维度高的列创建索引。
- 数据列中**不重复值**出现的个数,这个数量越高,维度就越高。
- 如数据表中存在8行数据a,b ,c,d,a,b,c,d这个表的维度为4。
- 要为维度高的列创建索引,如性别和年龄,那年龄的维度就高于性别。
- 性别这样的列不适合创建索引,因为维度过低。
2. 对 where,on,group by,order by 中出现的列使用索引。
3. 对较小的数据列使用索引,这样会使索引文件更小,同时内存中也可以装载更多的索引键。
4. 为较长的字符串使用前缀索引。
5. 不要过多创建索引除了增加额外的磁盘空间外对于DML操作的速度影响很大因为其每增删改一次就得从新建立索引。
6. 使用组合索引,可以减少文件索引大小,在使用时速度要优于多个单列索引。
## 组合索引与前缀索引
注意,这两种称呼是对建立索引技巧的一种称呼,并非索引的类型。
**组合索引**
MySQL单列索引和组合索引究竟有何区别呢
为了形象地对比两者,先建一个表:
```
CREATE TABLE `myIndex` (
`i_testID` INT NOT NULL AUTO_INCREMENT,
`vc_Name` VARCHAR(50) NOT NULL,
`vc_City` VARCHAR(50) NOT NULL,
`i_Age` INT NOT NULL,
`i_SchoolID` INT NOT NULL,
PRIMARY KEY (`i_testID`)
);
```
假设表内已有1000条数据在这 10000 条记录里面 7 上 8 下地分布了 5 条 vc_Name=”erquan” 的记录,只不过 city,age,school 的组合各不相同。来看这条 T-SQL
```
SELECT `i_testID` FROM `myIndex` WHERE `vc_Name`='erquan' AND `vc_City`='郑州' AND `i_Age`=25; -- 关联搜索;
```
首先考虑建MySQL单列索引
在 vc_Name 列上建立了索引。执行 T-SQL 时MYSQL 很快将目标锁定在了 vc_Name=erquan 的 5 条记录上,取出来放到一中间结果集。在这个结果集里,先排除掉 vc_City 不等于”郑州”的记录,再排除 i_Age 不等于 25 的记录,最后筛选出唯一的符合条件的记录。虽然在 vc_Name 上建立了索引查询时MYSQL不用扫描整张表效率有所提高但离我们的要求还有一定的距离。同样的,在 vc_City 和 i_Age 分别建立的MySQL单列索引的效率相似。
为了进一步榨取 MySQL 的效率,就要考虑建立组合索引。就是将 vc_Name,vc_City,i_Age 建到一个索引里:
```
ALTER TABLE `myIndex` ADD INDEX `name_city_age` (vc_Name(10),vc_City,i_Age);
```
建表时vc_Name 长度为 50这里为什么用 10 呢?这就是下文要说到的前缀索引,因为一般情况下名字的长度不会超过 10这样会加速索引查询速度还会减少索引文件的大小提高 INSERT 的更新速度。
执行 T-SQL 时MySQL 无须扫描任何记录就到找到唯一的记录!
如果分别在 vc_Name,vc_City,i_Age 上建立单列索引,让该表有 3 个单列索引,查询时和上述的组合索引效率一样吗?答案是大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但 MySQL 只能用到其中的那个它认为似乎是最有效率的单列索引,另外两个是用不到的,也就是说还是一个全表扫描的过程。
建立这样的组合索引,其实是相当于分别建立了:
- vc_Name,vc_City,i_Age
- vc_Name,vc_City
- vc_Name
这样的三个组合索引!为什么没有 vc_City,i_Age 等这样的组合索引呢?这是因为 mysql 组合索引 “最左前缀” 的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个 T-SQL 会用到:
```
SELECT * FROM myIndex WHREE vc_Name=”erquan” AND vc_City=”郑州” SELECT * FROM myIndex WHREE vc_Name=”erquan”
```
而下面几个则不会用到:
```
SELECT * FROM myIndex WHREE i_Age=20 AND vc_City=”郑州” SELECT * FROM myIndex WHREE vc_City=”郑州”
```
也就是name_city_age(vc_Name(10),vc_City,i_Age) 从左到右进行索引如果没有左前索引Mysql不执行索引查询。
**前缀索引**
如果索引列长度过长这种列索引时将会产生很大的索引文件不便于操作可以使用前缀索引方式进行索引前缀索引应该控制在一个合适的点控制在0.31黄金值即可(大于这个值就可以创建)。
SELECT COUNT(DISTINCT(LEFT(`title`,10)))/COUNT(*) FROM Arctic; — 这个值大于0.31就可以创建前缀索引Distinct去重复 ALTER TABLE `user` ADD INDEX `uname`(title(10)); — 增加前缀索引SQL将人名的索引建立在10这样可以减少索引文件大小加快索引查询速度。
## 什么样的sql不走索引
**要尽量避免这些不走索引的sql**
```
SELECT `sname` FROM `stu` WHERE `age`+10=30;-- 不会使用索引,因为所有索引列参与了计算
SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990; -- 不会使用索引因为使用了函数运算原理与上面相同
SELECT * FROM `houdunwang` WHERE `uname` LIKE'后盾%' -- 走索引
SELECT * FROM `houdunwang` WHERE `uname` LIKE "%后盾%" -- 不走索引
-- 正则表达式不使用索引这应该很好理解所以为什么在SQL中很难看到regexp关键字的原因
-- 字符串与数字比较不使用索引;
CREATE TABLE `a` (`a` char(10));
EXPLAIN SELECT * FROM `a` WHERE `a`="1" -- 走索引
EXPLAIN SELECT * FROM `a` WHERE `a`=1 -- 不走索引
select * from dept where dname='xxx' or loc='xx' or deptno=45 --如果条件中有or即使其中有条件带索引也不会使用。换言之就是要求使用的所有字段都必须建立索引我们建议大家尽量避免使用or 关键字
-- 如果mysql估计使用全表扫描要比使用索引快则不使用索引
```
多表关联时的索引效率
- SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990; 不会使用索引因为使用了函数运算原理与上面相同
- SELECT * FROM `houdunwang` WHERE `uname` LIKE后盾% — 走索引
- SELECT * FROM `houdunwang` WHERE `uname` LIKE “%后盾%” — 不走索引
![img](C:\Users\zhengchiliu\Desktop\笔记汇总\数据库\Mysql\MySQL 索引优化.assets\efcba9a9093fafa3879f44db4a3808fb.jpeg)
从上图可以看出所有表的type为all表示全表索引。也就是6 6 6共遍历查询了216次。
除第一张表示全表索引必须的要以此关联其他表其余的为range索引区间获得也就是6+1+1+1共遍历查询9次即可。
所以我们建议在多表join的时候尽量少join几张表因为一不小心就是一个笛卡尔乘积的恐怖扫描另外我们还建议尽量使用left join以少关联多。因为使用join 的话,第一张表是必须的全扫描的,以少关联多就可以减少这个扫描次数。
## 索引的弊端
不要盲目的创建索引,只为查询操作频繁的列创建索引,创建索引会使查询操作变得更加快速,但是会降低增加、删除、更新操作的速度,因为执行这些操作的同时会对索引文件进行重新排序或更新。
但是在互联网应用中查询的语句远远大于DML的语句甚至可以占到80%~90%,所以也不要太在意,只是在大数据导入时,可以先删除索引,再批量插入数据,最后再添加索引。

View File

@ -1,319 +0,0 @@
---
title: MySQL技术详解
categories:
- 概念
date: 2023-04-18 19:07:33
---
# MySQL技术详解
## 一、数据和数据库
数据:可以是数字、文字、图片、视频等
数据库:存储数据的仓库,易共享、易拓展、高并发、支持事务(要么做完、要么不做)
```
DMLData Manipulation Language数据操作语言用于检索或者修改数据。
DML包括
SELECT用于检索数据
INSERT用于增加数据到数据库
UPDATE用于从数据库中修改现存的数据
DELETE用于从数据库中删除数据。
DDLData Definition Language数据定义语言 用于定义数据的结构,比如 创建、修改或者删除数据库对象。
DDL包括DDL语句可以用于创建用户和重建数据库对象。下面是DDL命令
CREATE TABLE创建表
ALTER TABLE
DROP TABLE删除表
CREATE INDEX
DROP INDEX
DCLData Control Language数据控制语言用于定义数据库用户的权限。
DCL包括
ALTER PASSWORD
GRANT
REVOKE
CREATE SYNONYM
```
## 二、数据库类型
### **关系型数据库 :二维表和表之间的联系组成**
关系型:二维表模型,如下。
| | |
| ---- | ---- |
| | |
**记录**:一行数据就叫记录
**字段**:列名叫字段
### **非关系型数据库 强调Key-Value和文档数据库**
Redis、MongoDB等
## 三、MySQL约束类型
| 约束类型 | 作用 |
| --------------------------------- | ------------------------------------------------------------ |
| 主键约束 primary key | 唯一约束+非空约束,每个表最多只允许一个主键,创建完成之后会默认创建一个唯一索引 |
| 外键约束 foreign key | 外键约束是保证一个或两个表之间的参照完整性,外键基于两个表的两个字段的参照关系 |
| 唯一约束 unique | 列或者列组合不能重复,保证数据的唯一性 |
| 非空约束not null 和默认值 default | 可以确保不为空或者空的时候为什么值 |
## 四、MySQL索引
**定义****索引是存储引擎用于快速找到记录的一种数据结构**。举例说明如果查找一本书中的某个特定主题一般会先看书的目录类似索引找到对应页面。在MySQL存储引擎采用类似的方法使用索引高效获取查找的数据。
表的存储由数据和索引组成,如果没有索引就要从磁盘上读每一个数据页,如果有则只需查找索引页(类似于目录)
### 索引分类
**普通索引:**一个索引只包含单个列,一个表可以有多个单列索引
**唯一索引:**索引的列的值必须唯一,但允许有空值
**复合索引:**一个索引包含多个列
数据库保存的数据是存储在磁盘上,**查找数据时需要将磁盘中的数据加载到内存中**,在介绍索引的实现之前
### 建立索引的原则
1. 最左前缀匹配原则非常重要的原则mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引d是用不到索引的如果建立(a,b,d,c)的索引则都可以用到a,b,d的顺序可以任意调整。
2. =和in可以乱序比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序mysql的查询优化器会帮你优化成索引可以识别的形式。
3. 尽量选择区分度高的列作为索引区分度的公式是count(distinct col)/count(*)表示字段不重复的比例比例越大我们扫描的记录数越少唯一键的区分度是1而一些状态、性别字段可能在大数据面前区分度就是0那可能有人会问这个比例有什么经验值吗使用场景不同这个值也很难确定一般需要join的字段我们都要求是0.1以上即平均1条扫描10条记录。
4. 索引列不能参与计算保持列“干净”比如from_unixtime(create_time) = 2014-05-29就不能使用到索引原因很简单b+树中存的都是数据表中的字段值但进行检索时需要把所有元素都应用函数才能比较显然成本太大。所以语句应该写成create_time = unix_timestamp(2014-05-29)。
5. 尽量的扩展索引不要新建索引。比如表中已经有a的索引现在要加(a,b)的索引,那么只需要修改原来的索引即可。
**explain详解**
| 列 | 作用 |
| ------------- | ------------------------------------------------------------ |
| id | id列的编号是 select 的序列号,有几个 select 就有几个id并且id的顺序是按 select 出现的顺序增长的。MySQL将 select 查询分为简单查询(SIMPLE)和复杂查询(PRIMARY)。复杂查询分为三类简单子查询、派生表from语句中的子查询、union 查询。id越大执行优先级越高 |
| select_type | 表示是简单还是复杂的查询 |
| table | 正在访问哪个表,当 from 子句中有子查询时table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。当有 union 时UNION RESULT 的 table 列的值为<union1, 2>1和2表示参与 union 的 select 行id。 |
| partitions | |
| type | MySQL决定如何查找表中的行查找数据行记录的大概范围。依次从最优到最差分别为null(直接查询索引,无需查询数据) > system > const > eq_ref > ref > range > index > ALL |
| possible_keys | 如果该列是NULL则没有相关的索引。在这种情况下可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况这种情况是因为表中数据不多mysql认为索引对此查询帮助不大选择了全表查询。 |
| key | 这一列显示mysql实际采用哪个索引来优化对该表的访问。如果没有使用索引则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引在查询中使用 force index、ignore index。 |
| key_len | 这一列显示了mysql在索引里使用的字节数通过这个值可以算出具体使用了索引中的哪些列。 |
| ref | 这一列显示了在key列记录的索引中表查找值所用到的列或常量常见的有const常量字段名film. id |
| rows | 这一列是mysql估计要读取并检测的行数注意这个不是结果集里的行数。 |
| filtered | |
| Extra | **Using index**查询的列被索引覆盖并且where筛选条件是索引的前导列(最左侧索引),是性能高的表现。一般是使用了覆盖索引(索引包含了所有查询的字段)。对于innodb来说如果是辅助索引性能会有不少提高。<br />**Using where**查询的列未被索引覆盖where筛选条件非索引的前导列。<br />**Using where Using index**查询的列被索引覆盖并且where筛选条件是索引列之一但不是索引的前导列意味着无法直接通过索引查找来查询到符合条件的数据, Using index代表select用到了覆盖索引。<br />**NULL**查询的列未被索引覆盖并且where筛选条件是索引的前导列意味着用到了索引但是部分字段未被索引覆盖必须通过“回表”来实现不是纯粹地用到了索引也不是完全没用到索引。<br />**Using index condition**与Using where类似查询的列不完全被索引覆盖where条件中是一个前导列的范围<br />**Using temporary**mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的首先是想到用索引来优化。<br />**Using filesort**mysql 会对结果使用一个外部索引排序而不是按索引次序从表里读取行。此时mysql会根据联接类型浏览所有符合条件的记录并保存排序关键字和行指针然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化的。 |
### 操作索引
```
###创建普通索引
CREATE INDEX indexName ON table_name (column_name)
###后增加索引
ALTER table tableName ADD INDEX indexName(columnName)
###创建表的时候增加索引
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
###删除索引
drop index [indexName] ON mytable;
###创建唯一索引
CREATE UNIQUE INDEX indexName ON mytable(username(length))
###后增加唯一索引c
ALTER table mytable ADD UNIQUE [indexName] (username(length))
###创建表时指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE [indexName] (username(length))
);
###显示索引
SHOW INDEX FROM table_name\G
```
## 五、MySQL锁
当事务对某个数据对象进行操作前,先向系统发出加锁请求,在该事务释放锁之前,其他事物不能对此数据对象进行更新操作
## 六、MySQL的存储引擎
存储引擎就是存储数据建立索引更新查询数据等等技术的实现方式存储引擎针对数据表的oracle 和SQL Server等数据库只有一种存储引擎而MySQL提供插件式的存储引擎
## 七、事务
事务主要用于处理操作量大,复杂度高的数据,比如脚本,比如银行转账,从一个账号扣款并使另外一个账号增款,这两个操作妖魔都执行,要么都不执行。
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
一般来说事务是必须满足4个条件ACID原子性**A**tomicity或称不可分割性、一致性**C**onsistency、隔离性**I**solation又称独立性、持久性**D**urability
- **原子性:**一个事务transaction中的所有操作要么全部完成要么全部不完成不会结束在中间某个环节。事务在执行过程中发生错误会被回滚Rollback到事务开始前的状态就像这个事务从来没有执行过一样。
- **一致性:**在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- **隔离性:**数据库允许多个并发事务同时对其数据进行读写和修改的能力隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别包括读未提交Read uncommitted、读提交read committed、可重复读repeatable read和串行化Serializable
- **持久性:**事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
### 操作事务
```
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
```
## 八、复制
## 九、备份
**mysqldump**
```
mysqldump -u 用户名 -p 数据库名 > /备份路径/备份文件名 #备份整个数据库
mysqldump -u 用户名 -p 数据库名 表1 表2 > /备份路径/备份文件名 #备份数据表
--databases 库1库2 #备份多个数据库
--all-databases #备份所有数据库
mysql 数据库 < 备份文件
```
**mysql-binlog日志备份**
二进制日志(log-bin日志):所有对数据库状态更改的操作(create、drop、update等)
```
vim /etc/my.cnf
log-bin=mysql-bin #开启二进制日志
mysqlbinlog --start-datetime YY-MM-DD HH:MM:SS --stop-datetime YY-MM-DD HH:MM:SS 二进制日志 | mysql -u root -p #按照时间恢复
```
## 十、MySQL运维
### 常识
服务mysqld 端口3306
主配置文件:/etc/my.cnf 初始化脚本mysql_install_db
启动命令musqld_safe 数据目录:/var/lib/mysql
日志文件:/var/log/mysql.log
套接字文件:/var/lib/mysql/mysql.sock
进程文件:/var/run/mysqld/mysqld.pid
### 常用命令
**操作用户**
```
###创建用户
create user 用户名@远程主机 indentified by ‘密码’;
%:代替可代替主机位,代表任意远程主机
###修改用户密码
alter user 'root'@'localhost' identified with mysql_native_password by '密码';
set password=password(‘密码’); #为自己修改密码
set password for 用户名@% =password(‘新密码’); #root为其他人修改密码
###授权
select user from mysql.user; #查看用户
grant all on 数据库.表名 to 用户名@'%'; #授权
revoke all on 数据库.表名 to 用户名@'%'; #取消授权
###设置root 用户远程登录
update user set host='%' where user='root';
```
**操作数据库**
```
###创建数据库
create database 数据库名; #创建数据库
CREATE DATABASE IF NOT EXISTS 数据库名 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
###删除数据库
drop database 数据库名; #删除数据库
###查看所有数据库
show databases; #查看所有数据库
```
**操作数据表**
```
###创建数据表
create table 表名 (
字段;
字段
)ENGINE=InnoDB DEFAULT CHARSET=utf8; #指定使用的引擎和字符编码
###删除数据表
drop table 表名; #删除数据表
alter tabe 表名 drop 字段名; #删除表的字段
###删除外键约束
alter table tableName drop foreign key keyName;
###查看数据表
describe 表名; #查看数据表
SHOW COLUMNS FROM 表名 #查看表结构
###修改表的存储引擎
alter table tableName engine=myisam;
###修改表名
alter table 旧表名 rename 新表名 #给表改名
alter table 表名 change name 表名 字段名 char(50) not null defult; #给字段改名
###修改字段
alter table tableName modify name1 type1 first|after name2; #修改字段的相对位置这里name1为想要修改的字段type1为该字段原来类型first和after二选一这应该显而易见first放在第一位after放在name2字段后面
alter table 表名 add 字段名 字段属性; #增加字段
```
**操作数据**
```
###插入数据
insert into 表名 (字段1,字段2) values (1,2,3),(4,5,6); #插入多个数据
insert into 表1 (字段1,字段2) select 字段1,字段2 from 表2; #复制数据
###删除数据
delete from 表名 where 字段=值; #删除单条数据
###修改数据
update 表名 set 字段=数值 where 字段=值; #修改表中数据
```
**查询操作**
```
select 字段1字段2 from 表名 where 字段[=> and or]数值 limit 数值 offset 偏移量
group by #通过某个字段对数据分组
order by #通过某个字段排序
JOIN 按照功能大致分为如下三类:
INNER JOIN内连接,或等值连接):获取两个表中字段匹配关系的记录。
LEFT JOIN左连接获取左表所有记录即使右表没有对应匹配的记录。
RIGHT JOIN右连接 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
select 表1/2.字段 from 表1 inner join 表2 on 表1.字段=表2.字段
```
**显示数据表的属性信息 SHOW COLUMNS FROM 数据表 **
**显示数据表的详细索引信息 SHOW INDEX FROM 数据表**

View File

@ -1,592 +0,0 @@
用户对于数据表或视图等最常用的操作就是查询。也叫检索。通过select语句来实现
语法规则:
```
select {columns}
from {table|view|other select}
[where 查询条件]
[group by 分组条件]
[having 分组后再限定]
[order by 排序]
```
注意事项:
1. sql的语句对于大小写不敏感。数值也不分。(Oracle中数值区分大小写)
2. 关键字不能被分行
## 一、简单查询
select 的检索语句中只有select 以及from子句。也是一个select语句必须的。
### 1.1 指定列名
查询指定的列:
```
select 列名,列名 from 表名
```
> 如果查询表中所有的字段,使用*。
### 1.2 指定别名
```
select 列名 as 别名,列名 别名 from 表名
```
> as关键字其实也可以省略。
### 1.3 列运算
可以使用算术表达式
在select语句中检索到字段类型如果是numberdate可以使用算术表达式
加:+,减:-,乘:*,除:/,括号
> 如果某一列有null数值那么计算后的结果也是null。通用函数:ifnull(a,b),a为null那么取b如果a不为null那么取a的值。
### 1.4 字符串类型可以做连续运算
concat(“我的名字是”, name,'我今年。。');
把搜索到的列和列进行拼接显示。
### 1.5 去重重复distinct 字段名
distinct 列名,表示去除重复
distinct 列名1列名2一行的数据都相同才会被认为是重复的数据去除。
## 二、 条件查询
在实际查询的过程中, 我们需要根据需要来过滤出我们想要的数据, 这种查询就叫条件查询。在检索数据信息的时候,使用限定条件。表示满足条件才会被检索到。
使用where子句语法格式
```
select 检索列 from 表名 where 筛选条件
```
> 条件查询使用`where`子句对表中的数据进行筛选, 结果为`true`的行会出现的结果集中.
> 条件的表达式支持多种运算:
### 2.1 比较运算符
- 等于 `=`
- 大于 `>`
- 小于 `<`
- 大于等于 `>=`
- 小于等于 `<=`
- 不等于 `!=``<>`
---
查找年龄大于30岁的:
```
select * from stus where age>30;
```
查询姓名不是`王二狗`的:
```
select * from stus where name!='王二狗';
或者
select * from stus where name<>'王二狗';
```
### 2.2 逻辑运算符
- and, && (与)
- or, || (或)
- not, !(非)
---
查询年龄大于30并且性别是女的:
```
select * from stus where age>30 and sex='女';
select * from stus where age>30 && sex='女';
```
查询年龄小于30或者性别是男的:
```
select * from stus where age<30 or sex='男';
select * from stus where age<30 || sex='男';
```
---
### 2.3 模糊查询
比如想查询姓名中含有'张'的这种需求, 就需要用到模糊查询.
模糊查询用到关键字 `like`
```
select * from stus name like '%张%';
李李张张
王张
张三
张三三
```
语法:
1. `%`表示任意多个字符0-多个)
2. `_`(下划线)表示任意一个字符
查询姓名是两个字符的:
```
select * from stus where name like '张__';
```
---
### 2.4 区间查询
#### 2.4.1 in (...)
- `in` 表示在一个离散的非连续的范围中查找
查找id的值等于1或3或4的:
```
select * from stus where id in (1, 3,4);
```
#### 2.4.2 between...and...
- `between...and...`
- 表示在一个连续的区间中查找.
查找id的值在3到7之间的:
```
select * from stus where id between 3 and 7;
```
### 2.5 NULL判断
`is NULL` 用来判断某列是否为空. 注意: `NULL`用小写也是可以的.
## 三、排序
默认情况下, 我们查到的顺序是按照数据在数据库中的插入顺序排列的.
但是在实际情况下,我们需要根据不同的条件来排序, 比如按照更新日期排序, 或者按照价格从低到高排序, 或者按照人气从高到底排序等等.
**mysql支持对查询的结果进行重新排序.**
使用order by 列子句可以完成排序的功能. 后面的列表示排序规则.
> order by 子句。语法上位于一条sql语句的末尾。
### 3.1 升序(asc)
默认是升序排序
按照年龄从低到高排序.
```
select * from stus order by age;
```
> 说明:
>
> 1. 默认情况下是按照升序排序.asc
也可以在列的后面添加asc(ascend 提升)表示升序.
> 2. 使用desc表示降序
desc是单词 descend(下降)的缩写, 来表示降序排序.
### 3.2 降序(desc)
```
select * from stus order by age asc;
```
### 3.3 多种排序规则
可以先按照一定规则来排序, 当碰到相同的情况下, 按照第二种规则来排序, ...
先按照年龄升序排序, 如果年龄相等再按照id的降序排序.
```
select * from stus order by age asc,id desc;
```
## 四、聚合函数
在查询中,统计,求和等是很常用的,通过聚合函数完成能十分省事.
如果没有聚合函数可能需要各种子查询各种sql嵌套才能完成.
但是有了**聚合函数**,很多问题迎刃而解。
mysql提供了5个常用的聚合函数:`sum(), max(), min(), avg(), count()`
当然配合聚合函数使用的还有分组`group by 和 having子句`, 下一节再细讲.
### 4.1 sum(列)
这个聚合函数用来对那些列不是`null`的值进行求和.
- 对所有的age求和
- 多所年龄小于100的age求和
### 4.2 max(列)
这个聚合函数用来计算那些列不是`null`的值最大值.
- 找到最大的年龄
### 4.3 min(列)
这个聚合函数用来计算那些列不是`null`的值最小值.
- 找到最小的年龄
### 4.4 avg(列)
这个聚合函数用来计算那些列不是`null`的值平均值.
- 计算`age`的平均值
### 4.5 count(列)
统计函数.
count(*)--->统计所有行的数据,16
count(主键列)-->16
count(非主键列1),是否存在null数值。
count(comm)-->6
- 统计一共有多少行数据
- 统计性别不为`null`的数据 行数
## 五、分组查询
分组(group by)
group by 列名, 按照指定的列进行分组, 值相同的会分在一组.
语法:
```
select 列名 from 表名 group by 列名;
```
说明:
1. select后面跟的列名必须和group by后的列列名保持一致.
2. 当group by单独使用时, 只显示每组的第一条记录. 所以group by单独使用的意义不大.大多要配合聚合函数。
3. group by后面也可以给多个列进行分组, 表示这些列都相同的时候在一组.
### 5.1 按照某列分组
```
select sex from stus group by sex;
```
### 5.2 按照多列分组
```
select name, sex from stus group by name,sex;
```
### 5.3 分组后使用聚合函数
```
select sex,count(*) from stus group by sex;
```
> 注意:
> 1. 如果没有分组,那么组函数(max,min,avg,count....)作用在整张表上。
> 2. 如果有分组,组函数作用在分组后的数据上。
> 3. 在写select 子句中列如果没有在组函数里那么就要在group by后边。
```
select abcount(c),sum(d) from 表 group by a,b;
```
### 5.4 分组后限定查询having
二次筛选:二次筛选是指分组后再对数据进行筛选.
需要使用having子句来完成.
```
select 列名 from 表名 group by 列名 having 条件
```
也就是说分组后再限定使用having子句
having子句对于group by分组后的结果进行再次筛选。最后输出的结果就满足having条件的。
> having子句的和where子句的用法类似都是用于限定条件。
>
> 对比:
1. where和having后面都是跟条件
2. where是对表中的数据的原始筛选
3. having是对group by的结果的二次筛选
4. having必须配合group by使用, 一般也会跟着聚合函数一起使用
5. 可以先有where, 后面跟着group by和having
>
```
区别和结论:
1.语法上在having中使用组函数(max,min,avg,count...),而where后不能用组函数。
2.执行上where是先过滤再分组。having是先分组再过滤。
```
例如把sex不是null的过滤出来.
例如把男或女的个数超过6的过滤出来
## 六、分页查询
Limit子句(方言)
> 方言的意思是limit是mysql特有的。
Limit用于限定查询结果的起始行以及总行数。
```
select * from 表名 limit start,count;
```
例如查询起始行为第5行一共查询3行
select * from stus limit 4, 3;
其中4表示从第5行开始其中2表是查询3行。即5,6,7行记录。
## 七、内置函数[扩展]
### 7.1 字符串函数
- 查看字符的ascii码值ascii(str)str是空串时返回0
```
select ascii('a');
```
- 查看ascii码值对应的字符char(数字)
```
select char(97);
```
- 拼接字符串concat(str1,str2...)
```
select concat(12,34,'ab');
```
- 包含字符个数length(str)
```
select length('abc');
```
- 截取字符串
- left(str,len)返回字符串str的左端len个字符
- right(str,len)返回字符串str的右端len个字符
- substring(str,pos,len)返回字符串str的位置pos起len个字符从1开始
```
select substring('abc123',2,3);
```
- 去除空格
- ltrim(str)返回删除了左空格的字符串str
- rtrim(str)返回删除了右空格的字符串str
- trim([方向 remstr from str)返回从某侧删除remstr后的字符串str方向词包括both、leading、trailing表示两侧、左、右
```
select trim(' bar ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');
```
- 返回由n个空格字符组成的一个字符串space(n)
```
select space(10);
```
- 替换字符串replace(str,from_str,to_str)
```
select replace('abc123','123','def');
```
- 大小写转换,函数如下
- lower(str)
- upper(str)
```
select lower('aBcD');
```
### 7.2 数学函数
- 求绝对值abs(n)
```
select abs(-32);
```
- 求m除以n的余数mod(m,n),同运算符%
```
select mod(10,3);
select 10%3;
```
- 地板floor(n)表示不大于n的最大整数
```
select floor(2.3);
```
- 天花板ceiling(n)表示不小于n的最大整数
```
select ceiling(2.3);
```
- 求四舍五入值round(n,d)n表示原数d表示小数位置默认为0
```
select round(1.6);
```
- 求x的y次幂pow(x,y)
```
select pow(2,3);
```
- 获取圆周率PI()
```
select PI();
```
- 随机数rand()值为0-1.0的浮点数
```
select rand();
```
- 还有其它很多三角函数,使用时可以查询文档
### 7.3 日期时间函数
- 获取子值,语法如下
- year(date)返回date的年份(范围在1000到9999)
- month(date)返回date中的月份数值
- day(date)返回date中的日期数值
- hour(time)返回time的小时数(范围是0到23)
- minute(time)返回time的分钟数(范围是0到59)
- second(time)返回time的秒数(范围是0到59)
```
select year('2016-12-21');
```
- 日期计算,使用+-运算符数字后面的关键字为year、month、day、hour、minute、second
```
select '2016-12-21'+interval 1 day;
select '2017-12-12' + interval 3 month;
select date_add('2017-12-12', interval 1 day);
```
- 日期格式化date_format(date,format)format参数可用的值如下
- 获取年%Y返回4位的整数
* 获取年%y返回2位的整数
* 获取月%m值为1-12的整数
- 获取日%d返回整数
* 获取时%H值为0-23的整数
* 获取时%h值为1-12的整数
* 获取分%i值为0-59的整数
* 获取秒%s值为0-59的整数
```
select date_format('2016-12-21','%Y %m %d');
select str_to_date('12/12/2017','%d/%m/%Y');
```
- 当前日期current_date()
```
select current_date();
```
- 当前时间current_time()
```
select current_time();
```
- 当前日期时间now()
```
select now();
```
## 七、多表查询
连接查询当需要对有关系的多张表进行查询时需要使用连接join
**合并结果集**
1. 要求被合并的表中,列的类型和列数相同
2. UNION,去除重复行
3. UNION ALL 不去除重复行
**分类**
```
1. 内连接
2. 外连接
A左外连接
B右外连接
C全外连接(Mysql不支持)
3. 自连接(术语一种简化方式)
```
### 7.1 笛卡尔积
如果两张表在连接查询时,如果没有连接条件,那么就会产生笛卡尔积。(冗余数据)。
### 7.1 内连接
内连接查询出的所有的记录都满足条件
```
方言select * from 表1 别名1, 表2 别名2 where 别名1.xx=别名2.xx
也叫等值链接
标准select * from 表1 别名1 inner join 表2 别名2 on 别名1.xx=别名2.xx
自然select * from 表1 别名1 natural join 表2 别名2
```
### 7.2 外连接
内连接所检索出来的结果,都是满足连接条件的。外链接是扩展内连接检索出来的结果集。外链接返回的结果,除了包含满足链接条件的记录,还包括不满足连接条件。
#### 7.2.1 左外连接
左表记录无论是否满足条件都会查询出来而右表只有满足条件才能查询出来。左表中不满足条件的记录右表部分都为NULL
语法格式:
```
左外:
select * from 表1 别名1 left outer join 表2 别名2 on 别名1.xx=别名2.xx
左外自然:
select * from 表1 别名1 natural left outer join 表2 别名2
```
#### 7.2.2 右外连接
右表记录无论是否满足条件都会查询出来而左表只有满足条件才能查询出来。右表中不满足条件的记录左表部分都为NULL
语法格式:
```
右外:
select * from 表1 别名1 right outer join 表2 别名2 on 别名1.xx=别名2.xx
右外自然:
select * from 表1 别名1 natural right outer join 表2 别名2
```
#### 7.2.3 全外连接
Mysql不支持全外连接(full outer join)但是可以使用union来合并左外连接以及右外连接的结果达到全外连接的效果。
```
左外连接
SELECT e.ename,e.sal, d.dname,e.deptno,d.deptno
FROM emp e LEFT OUTER JOIN dept d
ON e.deptno=d.deptno
UNION
右外连接
SELECT e.ename,e.sal, d.dname,e.deptno,d.deptno
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno=d.deptno
```
### 7.3 自连接
自连接(术语一种简化方式)。其实就是一张表连接字节。
查询员工的上级名称
```
SELECT e.empno,e.ename,e.mgr,m.empno,m.ename
FROM emp e LEFT OUTER JOIN emp m
ON e.mgr=m.empno
```
## 八、子查询
子查询是指sql语句中包含另一个select语句。内查询或者内select语句
> 一条sql语句中包含多个select关键字
>
> 外查询,内查询
子查询可以出现的位置:
from后作为表
where后作为条件
注意事项:
1.子查询必须在()里
2.在子查询中不能使用order by子句。
3.子查询可以再嵌套子查询最多不能超过255层。
子查询细分为:单行子查询,多行子查询,关联子查询。
1.单行子查询
子查询的结果是单行数据。
在where条件后需要配合单行运算符>,<,>=,<=,!=,=
2.多行子查询
子查询的结果是多行数据。
在where条件后需要配合inanyall运算符
in
any匹配上子查询的结果集中任意一个即可。
all匹配上子查询的所有的结果。
3.关联子查询
对于单行子查询和多行子查询,外查询和内查询是分开执行的。
如果外查询使用到内查询的结果,就使用关联子查询。
关联子查询,是指在内查询中需要借助于外查询,而外查询离不开内查询的执行。就叫关联子查询。
## 九、总结
完整的select语句书写
```
select distinct *
from 表名
where ....
group by ... having ...
order by ...
limit start,count
```
执行顺序:
```
from 表名
where ...
group by ...
having ...
select distinct*..
order by ...
limit start,count
```
实际使用中,只是使用语句中某些部分的组合,而不是全部。

View File

@ -1,49 +0,0 @@
MySQL运维
1、建立连接
首先客户端与 MYSQL 服务器建立连接这个就不用说,客户端发起请求经过三次握手之后与服务器建立 TCP 连接;服务器收到请求之后对输入的用户名密码做权限校验, 校验通过之后后续的通信就基于这个长连接进行传输。
```
mysql> show processlist;
+----+-----------------+-----------+-------+---------+------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+-------+---------+------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 152 | Waiting on empty queue | NULL |
| 8 | root | localhost | mysql | Query | 0 | init | show processlist |
+----+-----------------+-----------+-------+---------+------+------------------------+------------------+
TIME参数表示该连接已经多久没有发生过数据传输。默认如果超过 8 小时没有发生过数据传输服务端就会自动关闭该连接。可以通过 wait_timeout参数来设置超时时间。
```
2、查询缓存
MySQL 查询缓存是 MySQL 中比较独特的一个缓存区域,用来缓存特定 Query 的整个结果集信息,且共享给所有客户端。为了提高完全相同的 Query 语句的响应速度MySQL Server 会对查询语句进行 Hash 计算后,把得到的 hash 值与 Query 查询的结果集对应存放在Query Cache 中。当 MySQL Server 打开 Query Cache 之后MySQL Server 会对接收到的每一个 SELECT 语句通过特定的 Hash 算法计算该 Query 的 Hash 值,然后通过该 hash 值到 Query Cache 中去匹配。
```
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| have_query_cache | YES | --查询缓存是否可用
| query_cache_limit | 1048576 | --可缓存具体查询结果的最大值
| query_cache_min_res_unit | 4096 | --查询缓存分配的最小块的大小(字节)
| query_cache_size | 599040 | --查询缓存的大小
| query_cache_type | ON | --是否支持查询缓存
| query_cache_wlock_invalidate | OFF | --控制当有写锁加在表上的时候,是否先让该表相关的 Query Cache失效
+------------------------------+---------+
```
开启缓存
```sql
Copymysql> set global query_cache_size = 600000; --设置缓存内存大小
mysql> set global query_cache_type = ON; --开启查询缓存
```
关闭缓存
```sql
Copymysql> set global query_cache_size = 0; --设置缓存内存大小为0 即初始化是不分配缓存内存
mysql> set global query_cache_type = OFF; --关闭查询缓存
```

View File

@ -1,3 +0,0 @@
每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程来专门处理与这个客户端的交互,当该客户端退出时会与服务器断开连接,服务器并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来,在另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端,这样就起到了不频繁创建和销毁线程的效果,从而节省开销。
当连接建立后与该客户端关联的服务器线程会一直等待客户端发送过来的请求MySQL服务器接收到的请求只是一个文本消息该文本消息还要经过各种处理

View File

@ -1,15 +0,0 @@
## 查询缓存
MySQL服务器程序处理查询请求时会把刚刚处理过的查询请求和结果缓存起来如果下一次有一模一样的请求过来直接从缓存中查找结果
如果两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中。另外,如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql 、information_schema、 performance_schema 数据库中的表,那这个请求就不会被缓存。
MySQL的缓存系统会监测涉及到的每张表只要该表的结构或者数据被修改如对该表使用了INSERT、 UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE或 DROP DATABASE语句那使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除
虽然查询缓存有时可以提升系统性能但也不得不因维护这块缓存而造成一些开销比如每次都要去查询缓存中检索查询请求处理完需要更新查询缓存维护该查询缓存对应的内存区域。从MySQL 5.7.20开始不推荐使用查询缓存并在MySQL 8.0中删除。
## 语法解析
如果查询缓存没有命中接下来就需要进入正式的查询阶段了。因为客户端程序发送过来的请求只是一段文本而已所以MySQL服务器程序首先要对这段文本做分析判断请求的语法是否正确然后从文本中将要查询的表、各种查询条件都提取出来放到MySQL服务器内部使用的一些数据结构上来。
## 查询优化
因为我们写的MySQL语句执行起来效率可能并不是很高MySQL的优化程序会对我们的语句做一些优化如外连接转换为内连接、表达式简化、子查询转为连接等等的一堆东西。优化的结果就是生成一个执行计划这个执行计划表明了应该使用哪些索引进行查询表之间的连接顺序是什么样的。我们可以使用EXPLAIN语句来查看某个语句的执行计划

View File

@ -1,51 +0,0 @@
截止到服务器程序完成了查询优化为止还没有真正的去访问真实的数据表MySQL服务器把数据的存储和提取操作都封装到了一个叫存储引擎的模块里物理上如何表示记录怎么从表中读取数据怎么把数据写入具体的物理存储器上这都是存储引擎负责的事情我们可以为不同的表设置不同的存储引擎不同的表可以有不同的物理存储结构不同的提取和写入方式。
## 常用存储引擎
| **存储引擎** | **描述** |
| --- | --- |
| ARCHIVE | 用于数据存档(行被插入后不能再修改) |
| BLACKHOLE | 丢弃写操作,读操作会返回空内容 |
| CSV | 在存储数据时,以逗号分隔各个数据项 |
| FEDERATED | 用来访问远程表 |
| InnoDB | 具备外键支持功能的事务存储引擎 |
| MEMORY | 置于内存的表 |
| MERGE | 用来管理多个MyISAM表构成的表集合 |
| MyISAM | 主要的非事务处理存储引擎 |
| NDB | MySQL集群专用存储引擎 |
## 相关操作
##### 查看当前服务器程序支持的存储引擎
```shell
SHOW ENGINES;
```
回显(字段说明support[是否支持]Transactions[是否支持事务]XA[是否支持分布式事务]Savepoints[是否支持事务回滚])
```shell
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
```
##### 创建表时指定存储引擎
```shell
CREATE TABLE 表名(
建表语句;
) ENGINE = 存储引擎名称;
```
##### 修改表的存储引擎
```shell
ALTER TABLE 表名 ENGINE = 存储引擎名称;
```
##### 查看表结构
```shell
SHOW CREATE TABLE 表名\G
```

View File

@ -1,6 +0,0 @@
# 1、第一范式
无重复的列,每一列都是不可分割的基本数据项,同一列中不能有多个值,及实体中的某个属性不能有多个值或者不能有重复的属性,确保每一列的原子性
## 2、第二范式
第二范式必须先满足第一范式属性完全依赖于主键要求表中的每隔行必须可以被唯一的区分通常为表加上每行的唯一标识主键PK非PK的字段需要与整个PK有直接相关性即非PK的字段不能依赖于部分主键
## 3、第三范式
满足第三范式必须先满足第二范式的属性非主键属性不依赖于其它非主键属性。第三范式要求一个数据表中不包含已在其他表中已包含的非主关键字信息非PK的字段间不能有从属关系

View File

@ -1,2 +0,0 @@
![image.png](https://cdn.nlark.com/yuque/0/2023/png/35086385/1698742857745-de9983cb-0ca2-4282-a34f-c882cf85d80e.png#averageHue=%23fefefe&clientId=u40c92775-8480-4&from=paste&height=434&id=u7748da2e&originHeight=559&originWidth=842&originalType=url&ratio=2.5&rotation=0&showTitle=false&size=99737&status=done&style=none&taskId=ua589b4b0-f212-4dc5-ae07-b359ba3285f&title=&width=653)

View File

@ -1,7 +0,0 @@
计算机中只能存储二进制数据,那该怎么存储字符串呢?将一个字符映射成一个二进制数据的过程也叫做编码,将一个二进制数据映射到一个字符的过程叫做解码。人们抽象出一个字符集的概念来描述某个字符范围的编码规则。比如
```
'a' -> 00000001 (十六进制0x01)
'b' -> 00000010 (十六进制0x02)
'A' -> 00000011 (十六进制0x03)
'B' -> 00000100 (十六进制0x04)
```

View File

@ -1,34 +0,0 @@
每个系统变量都有一个默认值,我们可以使用命令行或者配置文件中的选项在启动服务器时改变一些系统变量的值。大多数的系统变量的值也可以在程序运行过程中修改,而无需停止并重新启动它。
## 查看系统变量
```
SHOW VARIABLES [LIKE 匹配的模式];
```
## 服务器程序运行过程中设置
系统变量比较牛逼的一点就是,对于大部分系统变量来说,它们的值可以在服务器程序运行过程中,进行动态修改而无需停止并重启服务器。不过系统变量有作用范围之分
#### 设置不同作用范围的系统变量
系统变量的作用范围的概念,具体来说作用范围分为这两种:
- GLOBAL全局变量影响服务器的整体操作。
- SESSION会话变量影响某个客户端连接的操作。SESSION有个别名叫LOCAL
通过启动选项设置的系统变量的作用范围都是GLOBAL的也就是对所有客户端都有效的因为在系统启动的时候还没有客户端程序连接进来
```
SET [GLOBAL|SESSION] 系统变量名 = 值;
```
#### 查看不同作用范围的系统变量
SHOW VARIABLES语句默认查看的是SESSION作用范围的系统变量
我们也可以在查看系统变量的语句上加上要查看哪个作用范围的系统变量
```
SHOW [GLOBAL|SESSION] VARIABLES [LIKE 匹配的模式];
```
- 并不是所有系统变量都具有GLOBAL和SESSION的作用范围。
- 有一些系统变量只具有GLOBAL作用范围比方说max_connections表示服务器程序支持同时最多有多少个客户端程序进行连接。
- 有一些系统变量只具有SESSION作用范围比如insert_id表示在对某个包含AUTO_INCREMENT列的表进行插入时该列初始的值。
- 有一些系统变量的值既具有GLOBAL作用范围也具有SESSION作用范围比如我们前面用到的default_storage_engine而且其实大部分的系统变量都是这样的
- 有些系统变量是只读的并不能设置值。比方说version表示当前MySQL的版本我们客户端是不能设置它的值的只能在SHOW VARIABLES语句里查看
## 状态变量
MySQL服务器程序中维护了很多关于程序运行状态的变量它们被称为状态变量。
```
SHOW [GLOBAL|SESSION] STATUS [LIKE 匹配的模式];
```

View File

@ -1,55 +0,0 @@
## 配置文件路径
| **路径名** | **备注** |
| --- | --- |
| /etc/my.cnf | |
| /etc/mysql/my.cnf | |
| SYSCONFDIR/my.cnf | |
| $MYSQL_HOME/my.cnf | 特定于服务器的选项(仅限服务器) |
| defaults-extra-file | 命令行指定的额外配置文件路径 |
| ~/.my.cnf | 用户特定选项 |
| ~/.mylogin.cnf | 用户特定的登录路径选项(仅限客户端 |
## 配置文件的内容
与在命令行中指定启动选项不同的是,配置文件中的启动选项被划分为若干个组,每个组有一个组名,用中括号[]扩起来,像这样:
```
[server]
(具体的启动选项...)
[mysqld]
(具体的启动选项...)
[mysqld_safe]
(具体的启动选项...)
[client]
(具体的启动选项...)
[mysql]
(具体的启动选项...)
[mysqladmin]
(具体的启动选项...)
```
像这个配置文件里就定义了许多个组组名分别是server、mysqld、mysqld_safe、client、mysql、mysqladmin。每个组下面可以定义若干个启动选项
配置文件中不同的选项组是给不同的启动命令使用的,如果选项组名称与程序名称相同,则组中的选项将专门应用于该程序。例如,[mysqld]和[mysql]组分别应用于mysqld服务器程序和mysql客户端程序。不过有两个选项组比较特别
- [server]组下面的启动选项将作用于所有的服务器程序。
- [client]组下面的启动选项将作用于所有的客户端程序。
| **启动命令** | **类别** | **能读取的组** |
| --- | --- | --- |
| mysqld | 启动服务器 | [mysqld]、[server] |
| mysqld_safe | 启动服务器 | [mysqld]、[server]、[mysqld_safe] |
| mysql.server | 启动服务器 | [mysqld]、[server]、[mysql.server] |
| mysql | 启动客户端 | [mysql]、[client] |
| mysqladmin | 启动客户端 | [mysqladmin]、[client] |
| mysqldump | 启动客户端 | [mysqldump]、[client] |
## 同一个配置文件中多个组的优先级
```
[server]
default-storage-engine=InnoDB
[mysqld]
default-storage-engine=MyISAM
```
那么,将以最后一个出现的组中的启动选项为准

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,907 @@
# 简介
# Redis 实战指南
Redis是一个开源的key-value存储系统它支持存储的value类型相对更多包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash哈希类型。为了保证效率数据都是缓存在内存中。Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。并且在此基础上实现了master-slave(主从)同步。通过破坏一定的业务逻辑来换取性能。
## 目录
Redis默认16个数据库默认为0库所有库同样的密码。Redis 使用的单线程+多路IO复制技术。
1. [Redis 介绍](#1-redis-介绍)
2. [Redis 部署](#2-redis-部署)
3. [Redis 使用](#3-redis-使用)
4. [Redis 数据类型](#4-redis-数据类型)
5. [Redis 主从复制](#5-redis-主从复制)
6. [Redis Sentinel](#6-redis-sentinel)
7. [Redis Cluster](#7-redis-cluster)
# NoSQL数据库概述
---
NoSQL(NoSQL = Not Only SQL )指非关系型的数据库。NoSQL不依赖业务逻辑方式存储而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。
## 1. Redis 介绍
- 不遵循SQL标准
- 不支持ACID。
- 远超于SQL的性能。
### 1.1 什么是 Redis
## NoSQL适用场景
RedisRemote Dictionary Server是一个开源的、基于内存的数据结构存储系统可用作**数据库、缓存和消息队列**。
- 对数据高并发的读写
- 海量数据的读写
- 对数据高可扩展性的
### 1.2 Redis 特点
## NoSQL不适用场景
| 特性 | 说明 |
|------|------|
| 内存存储 | 数据存储在内存中,读写速度极快 |
| 持久化 | 支持 RDB 和 AOF 两种持久化方式 |
| 数据结构丰富 | 支持 String、Hash、List、Set、ZSet 等 |
| 主从复制 | 支持 master-slave 复制架构 |
| 集群 | 支持 Redis Cluster 分布式集群 |
| 发布/订阅 | 支持消息发布和订阅 |
| 事务 | 支持简单的事务操作 |
| Lua 脚本 | 支持 Lua 脚本执行 |
| 高可用 | 支持 Sentinel 哨兵机制 |
- 需要事务支持
- 基于sql的结构化查询存储处理复杂的关系。
### 1.3 Redis 应用场景
## NoSQL产品介绍
| 场景 | 说明 |
|------|------|
| 缓存 | 热点数据缓存,减轻数据库压力 |
| 会话存储 | Session、Token 存储 |
| 实时排行 | ZSet 实现排行榜 |
| 消息队列 | List 实现消息队列 |
| 分布式锁 | SETNX 实现分布式锁 |
| 计数器 | 原子自增操作 |
| 限流 | 滑动窗口算法限流 |
**Memcache**
### 1.4 Redis 与其他数据库对比
- 很早出现的NoSQL数据库
- 数据都在内存中,一般不持久化
- 支持简单的key-value模式支持类型单一
- 一般是作为缓存数据库辅助持久化的数据库
| 特性 | Redis | MySQL | MongoDB |
|------|-------|-------|---------|
| 数据模型 | Key-Value | 关系型 | 文档型 |
| 存储介质 | 内存+磁盘 | 磁盘 | 磁盘 |
| 性能 | 极高 | 中等 | 中等 |
| 扩展性 | 集群 | 主从/分片 | 分片 |
| 事务 | 弱事务 | 强事务 | 弱事务 |
**Redis**
---
- 几乎覆盖了Memcached的绝大部分功能
- 数据都在内存中,支持持久化,主要用作备份恢复
- 除了支持简单的key-value模式还支持多种数据结构的存储比如 list、set、hash、zset等。
- 一般是作为缓存数据库辅助持久化的数据库
## 2. Redis 部署
**MongoDB**
### 2.1 环境要求
- 高性能、开源、模式自由(schema free)的**文档型数据库**
- 数据都在内存中, 如果内存不足,把不常用的数据保存到硬盘
- 虽然是key-value模式但是对value尤其是**json**)提供了丰富的查询功能
- 支持二进制数据及大型对象
- 可以根据数据的特点**替代RDBMS**(关系型数据库) 成为独立的数据库。或者配合RDBMS存储特定的数据
- 操作系统LinuxCentOS/Ubuntu/Debian
- 编译器GCC 4.8+
- 内存:至少 2GB生产环境建议 4GB+
### 2.2 编译安装
```bash
# 下载源码
wget https://download.redis.io/redis-7.2.4.tar.gz
tar -zxf redis-7.2.4.tar.gz
cd redis-7.2.4
# 编译
make -j4
# 安装
make install PREFIX=/usr/local/redis
# 创建配置目录
mkdir -p /usr/local/redis/{etc,logs,data,run}
```
### 2.3 RPM 包安装CentOS/RHEL
```bash
# 安装 EPEL 源
yum install epel-release -y
# 安装 Redis
yum install redis -y
# 启动 Redis
systemctl start redis
systemctl enable redis
```
### 2.4 Docker 安装
```bash
# 拉取镜像
docker pull redis:7.2
# 运行容器
docker run -d \
--name redis \
-p 6379:6379 \
-v /data/redis/data:/data \
redis:7.2 \
redis-server --appendonly yes
# 使用配置文件启动
docker run -d \
--name redis \
-p 6379:6379 \
-v /data/redis/redis.conf:/usr/local/etc/redis/redis.conf \
-v /data/redis/data:/data \
redis:7.2 \
redis-server /usr/local/etc/redis/redis.conf
```
### 2.5 基础配置
```bash
# /usr/local/redis/etc/redis.conf
# 绑定地址
bind 0.0.0.0
# 端口
port 6379
# 守护进程运行
daemonize yes
# PID 文件
pidfile /usr/local/redis/run/redis.pid
# 日志文件
logfile /usr/local/redis/logs/redis.log
# 数据目录
dir /usr/local/redis/data
# 持久化 - RDB
save 900 1
save 300 10
save 60 10000
# 持久化 - AOF
appendonly yes
appendfsync everysec
# 内存最大限制
maxmemory 2gb
# 内存淘汰策略
maxmemory-policy allkeys-lru
# 连接密码
requirepass your_password
# 最大客户端连接数
maxclients 10000
```
### 2.6 启动和停止
```bash
# 启动
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
# 停止
/usr/local/redis/bin/redis-cli shutdown
# 停止(强制)
/usr/local/redis/bin/redis-cli shutdown nosave
# 连接客户端
/usr/local/redis/bin/redis-cli -a your_password
# 测试连接
redis-cli ping
# 返回PONG
```
---
## 3. Redis 使用
### 3.1 Redis 客户端
```bash
# 命令行客户端
redis-cli
# 带密码连接
redis-cli -a password
# 连接远程主机
redis-cli -h 192.168.1.100 -p 6379
# 选择数据库0-15
redis-cli -n 1
# 交互模式
redis-cli
> SELECT 0
> KEYS *
```
### 3.2 Key 操作
```bash
# 查看所有 key
KEYS pattern
# 示例KEYS user:*
# 查看 key 类型
TYPE key
# 查看 key 存在性
EXISTS key
# 设置过期时间(秒)
EXPIRE key 3600
# 查看剩余过期时间
TTL key
# 移除过期时间
PERSIST key
# 删除 key
DEL key
# 重命名
RENAME key newkey
# 序列化
DUMP key
# 反序列化
RESTORE key 0 "serialized-value"
```
### 3.3 数据库操作
```bash
# 切换数据库
SELECT db
# 清空当前数据库
FLUSHDB
# 清空所有数据库
FLUSHALL
# 查看数据库 key 数量
DBSIZE
# 查看最后访问时间
LASTSAVE
```
### 3.4 慢查询日志
```bash
# 查看慢查询配置
SLOWLOG GET
# 设置慢查询阈值(毫秒)
CONFIG SET slowlog-log-slower-than 1000
# 保留慢查询条数
CONFIG SET slowlog-max-len 128
# 查看慢查询
SLOWLOG GET 10
```
### 3.5 服务器信息
```bash
# 服务器信息
INFO
# 内存信息
INFO memory
# CPU 信息
INFO cpu
# 复制信息
INFO replication
# 客户端信息
CLIENT LIST
CLIENT KILL ip:port
# 实时统计
MONITOR
```
---
## 4. Redis 数据类型
### 4.1 String字符串
最基本的数据类型,最大 512MB。
```bash
# 设置值
SET key value
SET key value EX 3600 # 设置过期时间(秒)
SET key value PX 3600000 # 设置过期时间(毫秒)
SETNX key value # key 不存在时设置
SETXX key value # key 存在时设置
MSET key1 value1 key2 value2 # 批量设置
# 获取值
GET key
MGET key1 key2 # 批量获取
# 数字操作
INCR key # 加 1
DECR key # 减 1
INCRBY key 10 # 加 10
DECRBY key 10 # 减 10
INCRBYFLOAT key 1.5 # 加浮点数
# 字符串操作
APPEND key "suffix" # 追加
STRLEN key # 长度
GETRANGE key 0 3 # 截取0-3
SETRANGE key 5 "xx" # 替换
# 位操作
SETBIT key 7 1 # 设置位
GETBIT key 7 # 获取位
BITCOUNT key # 统计 1 的个数
BITOP AND destkey key1 key2 # 位运算
```
### 4.2 Hash哈希
键值对集合,适合存储对象。
```bash
# 设置
HSET key field value
HSET key field1 value1 field2 value2
HSETNX key field value
# 获取
HGET key field
HMGET key field1 field2
HGETALL key
HKEYS key # 所有字段
HVALUES key # 所有值
HLEN key # 字段数量
# 判断
HEXISTS key field
# 删除
HDEL key field1 field2
# 数字操作
HINCRBY key field 10
HINCRBYFLOAT key field 1.5
```
### 4.3 List列表
有序字符串列表,支持两端操作。
```bash
# 插入
LPUSH key value1 value2 # 头部插入
RPUSH key value1 value2 # 尾部插入
LINSERT key BEFORE/AFTER pivot value # 插入
# 获取
LRANGE key 0 -1 # 获取所有
LINDEX key 0 # 按索引获取
LLEN key # 长度
# 修改
LSET key index value # 设置指定索引
LTRIM key 0 9 # 保留指定范围
# 删除
LPOP key # 头部弹出
RPOP key # 尾部弹出
LREM key count value # 删除指定元素
```
### 4.4 Set无序集合
无序且不重复的字符串集合。
```bash
# 添加
SADD key member1 member2
# 获取
SMEMBERS key # 所有成员
SCARD key # 成员数量
SISMEMBER key member # 是否存在
# 删除
SREM key member1 member2
SPOP key # 随机弹出
SRANDMEMBER key count # 随机获取
# 集合运算
SUNION key1 key2 # 并集
SINTER key1 key2 # 交集
SDIFF key1 key2 # 差集
SUNIONSTORE dest key1 key2 # 并集存储
SINTERSTORE dest key1 key2 # 交集存储
SDIFFSTORE dest key1 key2 # 差集存储
```
### 4.5 ZSet有序集合
有序且不重复的字符串集合,每个成员关联一个分数。
```bash
# 添加
ZADD key score1 member1 score2 member2
# 获取
ZRANGE key 0 -1 # 按索引获取
ZREVRANGE key 0 -1 # 倒序获取
ZRANGEBYSCORE key 0 100 # 按分数范围获取
ZSCORE key member # 获取分数
ZRANK key member # 排名(正序)
ZREVRANK key member # 排名(倒序)
# 数量
ZCARD key # 成员数量
ZCOUNT key min max # 分数范围内数量
# 删除
ZREM key member1 member2
ZREMRANGEBYSCORE key min max
ZREMRANGEBYRANK key start stop
```
### 4.6 HyperLogLog
用于基数统计,内存占用极低。
```bash
# 添加
PFADD key element1 element2
# 统计
PFCOUNT key1 key2
# 合并
PFMERGE destkey key1 key2
```
### 4.7 Geospatial
地理坐标存储和查询。
```bash
# 添加坐标
GEOADD key longitude latitude member
# 获取坐标
GEOPOS key member
# 计算距离
GEODIST key member1 member2 [km/m/ft/mi]
# 附近查询
GEORADIUS key longitude radius km
GEORADIUSBYMEMBER key member radius km
```
### 4.8 Stream
消息队列功能。
```bash
# 添加消息
XADD key * field1 value1 field2 value2
# 读取消息
XRANGE key - + COUNT 10
XREAD COUNT 10 STREAMS key 0
# 消费者组
XGROUP CREATE key group 0
XREADGROUP GROUP group consumer COUNT 10 STREAMS key >
# 消息确认
XACK key group message-id
```
---
## 5. Redis 主从复制
### 5.1 复制原理
Redis 主从复制采用**异步复制**模式,包含全量同步和增量同步。
```
全量同步流程:
1. 从库发送 PSYNC 命令
2. 主库执行 BGSAVE 生成 RDB 文件
3. 主库发送 RDB 文件给从库
4. 从库加载 RDB 文件
5. 主库发送缓冲区命令给从库
增量同步流程:
1. 主库将写命令发送给从库
2. 从库执行写命令
```
### 5.2 配置主从复制
```bash
# 从库配置 - redis.conf
replicaof 192.168.1.100 6379
# 或者运行时执行
REPLICAOF 192.168.1.100 6379
# 取消复制
REPLICAOF NO ONE
# 设置主库密码
masterauth your_password
# 只读模式(从库默认)
replica-read-only yes
```
### 5.3 一主多从配置
```bash
# 主库配置
bind 0.0.0.0
port 6379
requirepass master_password
appendonly yes
# 从库 1 配置
replicaof 192.168.1.100 6379
masterauth master_password
# 从库 2 配置
replicaof 192.168.1.100 6379
masterauth master_password
```
### 5.4 拓扑结构
```
├── 主库Master
│ ├── 从库 1Slave
│ ├── 从库 2Slave
│ └── 从库 3Slave
```
### 5.5 主从复制管理
```bash
# 查看复制状态
INFO replication
# 查看从库列表
CLIENT LIST
# 断开复制
REPLICAOF NO ONE
# 手动故障转移(从库执行)
CLUSTER FAILOVER
```
### 5.6 复制安全
```bash
# 主库设置密码
requirepass your_password
# 从库配置主库密码
masterauth your_password
# 加密复制流量
repl-diskless-sync yes
repl-diskless-sync-delay 5
```
---
## 6. Redis Sentinel
### 6.1 Sentinel 概述
Redis Sentinel 是Redis 的高可用解决方案,负责监控主从库、自动故障转移、通知客户端。
### 6.2 Sentinel 架构
```
┌─────────────┐
│ Client │
└──────┬──────┘
┌──────▼──────┐
│ Sentinel │
│ (Monitor) │
└──────┬──────┘
┌─────────────────┼─────────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ Master │ │ Slave 1 │ │ Slave 2 │
└─────────┘ └─────────┘ └─────────┘
```
### 6.3 Sentinel 配置
```bash
# sentinel.conf
# 端口
port 26379
# 守护进程
daemonize yes
# 日志
logfile /var/log/redis/sentinel.log
# 工作目录
dir /tmp
# 监控主库
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.1.100 6379 2
# 主库密码
sentinel auth-pass mymaster your_password
# 故障转移超时时间(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 并行同步数量
sentinel parallel-syncs mymaster 1
# 故障转移超时时间
sentinel failover-timeout mymaster 180000
```
### 6.4 启动 Sentinel
```bash
# 方式 1直接启动
redis-sentinel /etc/redis/sentinel.conf
# 方式 2redis-server 启动
redis-server /etc/redis/sentinel.conf --sentinel
```
### 6.5 Sentinel 管理命令
```bash
# 连接 Sentinel
redis-cli -p 26379
# 查看主库信息
SENTINEL get-master-addr-by-name mymaster
# 查看所有从库
SENTINEL slaves mymaster
# 查看 Sentinel 信息
SENTINEL sentinels mymaster
# 手动故障转移
SENTINEL failover mymaster
# 强制故障转移(主库宕机)
SENTINEL failover force mymaster
```
### 6.6 Java 客户端连接
```bash
# Jedis
JedisSentinelPool pool = new JedisSentinelPool(
"mymaster",
Set.of("192.168.1.101:26379", "192.168.1.102:26379"),
poolConfig,
timeout,
password
);
# Lettuce
RedisSentinelConfiguration config = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("192.168.1.101", 26379)
.sentinel("192.168.1.102", 26379);
```
---
## 7. Redis Cluster
### 7.1 Cluster 概述
Redis Cluster 是 Redis 的分布式解决方案,自动将数据分片到多个节点,支持高可用和水平扩展。
### 7.2 集群架构
```
┌─────────────────────────────────────────────────┐
│ Redis Cluster │
├──────────┬──────────┬──────────┬──────────┬────┤
│ Node 1 │ Node 2 │ Node 3 │ Node 4 │ .. │
│ (Master) │ (Master) │ (Master) │ (Master) │ │
│ Slot 0 │ Slot 5500│ Slot 1100│ Slot 5501│ │
│ 5461 │ 10922 │ 5462 │ 10923 │ │
├──────────┼──────────┼──────────┼──────────┼────┤
│ Slave │ Slave │ Slave │ Slave │ │
└──────────┴──────────┴──────────┴──────────┴────┘
```
### 7.3 槽Slot分配
- Redis Cluster 有 **16384 个槽**
- 每个节点负责一部分槽0-16383
- 数据根据 key 的 CRC16 哈希值分配到对应槽
```
槽号计算CRC16(key) % 16384
```
### 7.4 集群配置
```bash
# 节点配置 - redis.conf
# 集群模式
cluster-enabled yes
# 集群配置文件
cluster-config-file nodes-6379.conf
# 节点超时时间
cluster-node-timeout 15000
# 集群节点端口(客户端连接端口 + 10000
cluster-announce-port 6379
cluster-announce-bus-port 16379
# 集群节点 IP
cluster-announce-ip 192.168.1.100
```
### 7.5 创建集群
```bash
# 启动所有节点
redis-server /usr/local/redis/etc/redis-1.conf
redis-server /usr/local/redis/etc/redis-2.conf
redis-server /usr/local/redis/etc/redis-3.conf
redis-server /usr/local/redis/etc/redis-4.conf
redis-server /usr/local/redis/etc/redis-5.conf
redis-server /usr/local/redis/etc/redis-6.conf
# 创建集群6 节点3 主 3 从)
redis-cli --cluster create \
192.168.1.101:6379 \
192.168.1.102:6379 \
192.168.1.103:6379 \
192.168.1.104:6379 \
192.168.1.105:6379 \
192.168.1.106:6379 \
--cluster-replicas 1
# 参数说明:--cluster-replicas 1 表示每个主库有 1 个从库
```
### 7.6 集群管理
```bash
# 连接集群
redis-cli -c
# 查看集群信息
CLUSTER INFO
# 查看节点信息
CLUSTER NODES
# 查看槽分配
CLUSTER SLOTS
# 手动分配槽
CLUSTER ADDSLOTS 0 5460
# 槽迁移
CLUSTER SETSLOT 16383 MIGRATING node_id
CLUSTER SETSLOT 16384 IMPORTING node_id
# 重新分片
redis-cli --cluster reshard 192.168.1.101:6379
# 添加节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port
# 删除节点
redis-cli --cluster del-node host:port node_id
# 故障转移(从库执行)
CLUSTER FAILOVER
```
### 7.7 集群高可用
```bash
# 检查集群状态
redis-cli --cluster check 192.168.1.101:6379
# 手动故障转移
redis-cli -h 192.168.1.104 -p 6379 CLUSTER FAILOVER
# 修复集群
redis-cli --cluster fix 192.168.1.101:6379
```
### 7.8 Java 客户端连接
```bash
# Jedis
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.1.101", 6379));
nodes.add(new HostAndPort("192.168.1.102", 6379));
nodes.add(new HostAndPort("192.168.1.103", 6379));
JedisCluster cluster = new JedisCluster(
nodes,
3000,
10,
poolConfig
);
# Spring Boot
spring.data.redis.cluster.nodes=192.168.1.101:6379,192.168.1.102:6379,192.168.1.103:6379
```
---
## 附录
### 常用命令速查表
| 命令 | 说明 |
|------|------|
| `redis-cli ping` | 测试连接 |
| `redis-cli shutdown` | 关闭 Redis |
| `KEYS *` | 查看所有 key |
| `FLUSHDB` | 清空当前数据库 |
| `BGSAVE` | 后台保存 RDB |
| `LASTSAVE` | 上次保存时间 |
### 配置文件参数速查
| 参数 | 说明 |
|------|------|
| `bind` | 绑定地址 |
| `port` | 端口 |
| `daemonize` | 守护进程 |
| `requirepass` | 密码 |
| `maxmemory` | 最大内存 |
| `maxmemory-policy` | 内存淘汰策略 |
| `appendonly` | AOF 持久化 |
| `save` | RDB 持久化策略 |
### 内存淘汰策略
| 策略 | 说明 |
|------|------|
| `noeviction` | 不淘汰,返回错误 |
| `volatile-lru` | LRU 淘汰过期 key |
| `allkeys-lru` | LRU 淘汰所有 key |
| `volatile-random` | 随机淘汰过期 key |
| `allkeys-random` | 随机淘汰所有 key |
| `volatile-ttl` | 淘汰 TTL 最短的 key |
| `volatile-lfu` | LFU 淘汰过期 key |
| `allkeys-lfu` | LFU 淘汰所有 key |
---
*文档创建时间2024年*

View File

@ -1,21 +0,0 @@
# Redis高并发
虽然 Redis 是单线程的,但它通过多种方式来保证高并发性能:
1. 异步非阻塞 I/O 模型Redis 使用了一种非阻塞的 I/O 模型,即使用一个线程来处理多个连接。这个线程会监听多个客户端的连接,并在有数据可读时立即处理这些数据。这种方式可以大大提高 Redis 的并发性能,因为它可以同时处理多个客户端的请求。
2. 内存数据库Redis 将数据存储在内存中,而不是磁盘上,这使得 Redis 能够快速读写数据,从而提高了并发性能。
3. 单线程避免了线程切换的开销:线程切换是一种非常昂贵的操作,因为它需要保存和恢复线程的上下文。由于 Redis 是单线程的,所以它避免了线程切换的开销,从而提高了并发性能。
4. 多路复用技术Redis 使用了多路复用技术来处理多个客户端的请求。这种技术可以让 Redis 在一个线程中同时处理多个客户端的请求,从而提高了并发性能。
5. 基于事件驱动的编程模型Redis 使用了基于事件驱动的编程模型,即在事件发生时触发相应的回调函数。这种模型可以让 Redis 在处理请求时更加高效,从而提高了并发性能。
虽然它是单线程的,但它的性能表现非常出色。
## 一、多路复用技术
多路复用技术是一种用于处理多个 I/O 事件的技术,它可以让一个线程同时处理多个 I/O 事件,从而提高系统的并发性能。在 Linux 系统中多路复用技术主要有三种实现方式select、poll 和 epoll。
1. selectselect 是最早的多路复用技术之一它可以同时监听多个文件描述符当其中任何一个文件描述符上有事件发生时select 就会返回。select 的缺点是它的效率比较低,因为它需要遍历所有的文件描述符,而且每次调用 select 都需要将文件描述符集合从用户态复制到内核态。
2. pollpoll 是 select 的改进版,它也可以同时监听多个文件描述符,但它使用链表来存储文件描述符,避免了 select 的缺点。poll 的缺点是它需要遍历整个链表来查找有事件发生的文件描述符,因此效率也不是很高。
3. epollepoll 是 Linux 内核中最新的多路复用技术它可以同时监听多个文件描述符并且只返回有事件发生的文件描述符。epoll 的优点是它使用了红黑树来存储文件描述符,可以快速查找有事件发生的文件描述符,而且它还支持边缘触发和水平触发两种模式,可以更加灵活地处理事件。
在 Redis 中,多路复用技术被广泛应用于网络通信和文件 I/O 等方面。Redis 使用多路复用技术来处理多个客户端的请求,从而提高了系统的并发性能。当一个客户端连接到 Redis 服务器时Redis 会将这个客户端的文件描述符添加到 epoll 中,然后在 epoll 中监听这个文件描述符上的事件。当这个客户端有数据可读时epoll 就会通知 RedisRedis 就可以立即处理这个客户端的请求。这种方式可以让 Redis 在一个线程中同时处理多个客户端的请求,从而提高了系统的并发性能。

View File

@ -0,0 +1,575 @@
# OpenVPN 实战指南
> 企业级开源 VPN 解决方案,实现安全远程访问。
---
## 1. OpenVPN 简介
### 1.1 什么是 VPN
**VPN**Virtual Private Network虚拟专用网络
- 在公共网络上建立的安全加密通道
- 实现远程安全访问公司内网资源
- 保证数据传输的机密性和完整性
### 1.2 OpenVPN 特点
| 特点 | 说明 |
|------|------|
| 开源免费 | GPL 协议,源码开放 |
| 跨平台 | Windows/Linux/macOS/Android/iOS |
| 安全性高 | 支持 AES、BF-CBC 等加密算法 |
| 简单易用 | 配置简洁,客户端友好 |
| 协议优势 | 基于 TLS/SSL |
| 多种认证 | 支持证书、用户名密码、双因子 |
### 1.3 OpenVPN 与其他 VPN 对比
| VPN 方案 | 协议 | 安全性 | 复杂度 | 适用场景 |
|----------|------|--------|--------|----------|
| **OpenVPN** | SSL/TLS | 高 | 中 | 通用远程访问 |
| IPSec | IKEv2 | 高 | 高 | 企业级 |
| PPTP | PPP | 低 | 低 | 简单场景(已废弃) |
| L2TP/IPSec | L2TP | 高 | 中 | 兼容性好 |
| WireGuard | WireGuard | 高 | 低 | 现代方案 |
### 1.4 原理架构
```
┌──────────────────────────────────────────────┐
│ Internet │
│ (公网/不安全的网络) │
└──────────────────┬───────────────────────────┘
┌──────────────────▼───────────────────────────┐
│ OpenVPN Server │
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ TLS/SSL │ │ 虚拟网卡 tun/tap │ │
│ │ 加密通道 │ │ 10.8.0.0/24 │ │
│ └─────────────┘ └─────────────────────┘ │
└──────────────────┬───────────────────────────┘
┌──────────────────▼───────────────────────────┐
│ 内网(安全网络) │
│ 192.168.1.0/24 │
│ 文件服务器/数据库/内部系统 │
└──────────────────────────────────────────┘
```
### 1.5 工作流程
```
客户端 服务端
│ │
│ 发起连接请求 │
│ ─────────────────────>│
│ │
│ 返回证书 │
<─────────────────────│
│ │
│ 验证证书 + 配置IP │
│ ─────────────────────>│
│ │
│ 建立 TLS 通道 │
<─────────────────────│
│ │
│ 启用虚拟网卡 │
<─────────────────────│
│ │
│ 数据加密传输 │
│◄─────────────────────►│
```
---
## 2. OpenVPN 部署
### 2.1 环境准备
```bash
# 系统要求
CentOS 7/8 / Ubuntu 20.04+
内存512MB+
CPU1核+
# 关闭 SELinux如需要
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 关闭防火墙(或放行)
systemctl stop firewalld
systemctl disable firewalld
# 放行端口
firewall-cmd --permanent --add-port=1194/udp
firewall-cmd --reload
```
### 2.2 安装 OpenVPN
```bash
# CentOS/RHEL
yum install -y openvpn easy-rsa
# Ubuntu/Debian
apt update
apt install -y openvpn easy-rsa
# 检查版本
openvpn --version
```
### 2.3 配置证书环境
```bash
# 复制证书工具
cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
# 初始化 PKI
./easyrsa init-pki
# 创建 CA
./easyrsa build-ca nopass
# 创建服务端证书
./easyrsa build-server-full server nopass
# 创建客户端证书
./easyrsa build-client client1 nopass
# 生成 Diffie-Hellman 参数
./easyrsa gen-dh
# 生成 TLS Auth 密钥(防止 DoS 攻击)
openvpn --genkey secret /etc/openvpn/easy-rsa/ta.key
```
> 证书文件说明:
> - `pki/ca.crt`CA 证书(客户端和服务端都需要)
> - `pki/issued/server.crt`:服务端证书
> - `pki/private/server.key`:服务端私钥
> - `pki/issued/client1.crt`:客户端证书
> - `pki/private/client1.key`:客户端私钥
> - `pki/dh.pem`DH 参数
> - `ta.key`TLS Auth 密钥
### 2.4 服务端配置
```bash
# 创建配置文件
cat > /etc/openvpn/server.conf << 'EOF'
# 端口和协议
port 1194
proto udp
dev tun
# 证书和密钥
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
tls-auth /etc/openvpn/easy-rsa/ta.key 0
# 加密算法
cipher AES-256-GCM
auth SHA256
# 网络配置
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
# 客户端可以访问内网
client-config-dir /etc/openvpn/ccd
route 192.168.1.0 255.255.255.0
# 权限和日志
keepalive 10 120
persist-key
persist-tun
status /etc/openvpn/openvpn-status.log
log /etc/openvpn/openvpn.log
verb 3
# 压缩(可选,兼容老客户端)
compress lz4-v2
push "compress lz4-v2"
EOF
```
### 2.5 客户端配置(生成配置)
```bash
# 创建客户端配置目录
mkdir -p /etc/openvpn/ccd
# 创建客户端配置
cat > /etc/openvpn/ccd/client1 << 'EOF'
# 为客户端分配固定 IP
ifconfig-push 10.8.0.10 10.8.0.9
EOF
```
### 2.6 启动服务
```bash
# 启动服务
systemctl start openvpn@server
systemctl enable openvpn@server
# 检查状态
systemctl status openvpn@server
ip addr show tun0
```
### 2.7 路由和转发配置
```bash
# 开启 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
# 配置 NAT如果需要访问内网
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# 永久保存
iptables-save > /etc/sysconfig/iptables
```
### 2.8 客户端配置Linux
```bash
# 安装客户端
apt install -y openvpn
# 复制配置文件
# 方法1从服务端拉取
scp root@server:/etc/openvpn/easy-rsa/pki/issued/client1.crt /etc/openvpn/client.crt
scp root@server:/etc/openvpn/easy-rsa/pki/private/client1.key /etc/openvpn/client.key
scp root@server:/etc/openvpn/easy-rsa/pki/ca.crt /etc/openvpn/ca.crt
# 创建客户端配置
cat > /etc/openvpn/client.conf << 'EOF'
client
dev tun
proto udp
remote your-server-ip 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
# 证书
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client.crt
key /etc/openvpn/client.key
# TLS Auth
tls-auth /etc/openvpn/ta.key 1
verb 3
EOF
# 复制 TLS Auth
scp root@server:/etc/openvpn/easy-rsa/ta.key /etc/openvpn/ta.key
# 启动连接
openvpn --config /etc/openvpn/client.conf
# 或使用 systemd
systemctl start openvpn@client
```
### 2.9 客户端配置Windows
1. 从服务端下载证书文件:
- `ca.crt`
- `client1.crt`
- `client1.key`
- `ta.key`(可选)
2. 下载 OpenVPN 客户端:
- https://openvpn.net/community-downloads/
3. 创建客户端配置 `client.ovpn`
```ovpn
client
dev tun
proto udp
remote your-server-ip 1194
resolv-retry infinite
nobind
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
ca ca.crt
cert client1.crt
key client1.key
tls-auth ta.key 1
verb 3
```
4. 导入配置:
- 将证书和配置放入 `C:\Program Files\OpenVPN\config\`
- 右键托盘图标 → 连接
### 2.10 客户端配置macOS
```bash
# 使用 Homebrew 安装
brew install openvpn
# 或下载 Tunnelblickhttps://tunnelblick.net/
# 导入配置文件(.ovpn
open -a Tunnelblick client.ovpn
```
### 2.11 客户端配置iOS/Android
1. **iOS**:下载 OpenVPN Connect 应用,导入 `.ovpn` 配置
2. **Android**:下载 OpenVPN for Android 或 OpenVPN Connect
---
## 3. OpenVPN 管理
### 3.1 日常管理命令
```bash
# 查看连接状态
systemctl status openvpn@server
# 重启服务
systemctl restart openvpn@server
# 查看日志
tail -f /etc/openvpn/openvpn.log
# 查看连接的用户
cat /etc/openvpn/openvpn-status.log
```
### 3.2 查看连接用户
```bash
# 方法1查看状态文件
cat /etc/openvpn/openvpn-status.log
# 方法2通过管理接口
echo "status" | nc localhost 1194
# 方法3检查虚拟网卡
ip addr show tun0
```
### 3.3 日志分析
```bash
# 实时查看日志
tail -f /etc/openvpn/openvpn.log
# 查看错误日志
grep -i error /etc/openvpn/openvpn.log
# 查看连接日志
grep -i "client connect" /etc/openvpn/openvpn.log
```
### 3.4 添加新用户
```bash
cd /etc/openvpn/easy-rsa
# 生成新客户端证书
./easyrsa build-client newuser nopass
# 导出证书
# /etc/openvpn/easy-rsa/pki/issued/newuser.crt
# /etc/openvpn/easy-rsa/pki/private/newuser.key
# /etc/openvpn/easy-rsa/pki/ca.crt
```
### 3.5 撤销用户
```bash
cd /etc/openvpn/easy-rsa
# 撤销证书
./easyrsa revoke newuser
# 生成新的 CRL
./easyrsa gen-crl
# 重启服务
systemctl restart openvpn@server
```
### 3.6 配置文件优化
```bash
# 调整日志级别
verb 3 # 详细(生产环境建议 3
# 调整 MTU
tun-mtu 1500
# 调整 keepalive
keepalive 10 120 # 每 10 秒检测120 秒超时
# 压缩设置
compress lz4-v2 # 启用压缩
```
### 3.7 性能优化
```bash
# 调整缓冲区大小
sndbuf 393216
rcvbuf 393216
# 多线程(如果 CPU 多核)
multihome
# 连接数限制
max-clients 100
```
### 3.8 安全加固
```bash
# 限制客户端 IP
# 在 ccd 目录中配置
cat > /etc/openvpn/ccd/client1 << 'EOF'
ifconfig-push 10.8.0.10 10.8.0.9
# 绑定特定 IP
iroute 192.168.10.0 255.255.255.0
EOF
# 启用 LZO 压缩
compress lz4-v2
# 使用强加密算法
cipher AES-256-GCM
auth SHA256
# 定期更换证书
# 每年更换一次 CA 和服务端证书
```
### 3.9 常见问题处理
| 问题 | 原因 | 解决方案 |
|------|------|----------|
| 连接失败 | 端口被阻 | 检查防火墙/放行 1194 端口 |
| 连接成功但无法访问内网 | 未开启 IP 转发 | 开启 `net.ipv4.ip_forward` |
| 连接后无法解析 DNS | 未推送 DNS | 配置 `push "dhcp-option DNS"` |
| 证书过期 | 证书过期 | 重新签发证书 |
| 速度慢 | MTU 问题 | 调整 `tun-mtu` |
### 3.10 配置文件示例
```bash
# 生产环境配置
cat > /etc/openvpn/server.conf << 'EOF'
port 1194
proto udp
dev tun
dev-type tun
# 证书
ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-auth ta.key 0
# 加密
cipher AES-256-GCM
auth SHA256
# 网络
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 223.5.5.5"
push "dhcp-option DNS 119.29.29.29"
# 客户端配置目录
client-config-dir ccd
# 路由
route 192.168.1.0 255.255.255.0
# 权限
keepalive 10 120
persist-key
persist-tun
user nobody
group nobody
# 日志
status openvpn-status.log
log-append openvpn.log
verb 3
compress lz4-v2
push "compress lz4-v2"
EOF
```
---
## 4. 常用命令速查
### 4.1 服务端
| 场景 | 命令 |
|------|------|
| 启动 | `systemctl start openvpn@server` |
| 停止 | `systemctl stop openvpn@server` |
| 重启 | `systemctl restart openvpn@server` |
| 查看状态 | `systemctl status openvpn@server` |
| 查看日志 | `tail -f /etc/openvpn/openvpn.log` |
### 4.2 客户端
| 场景 | 命令 |
|------|------|
| 启动连接 | `openvpn --config client.conf` |
| 后台运行 | `openvpn --config client.conf --daemon` |
| 测试配置 | `openvpn --config client.conf --test-crypto` |
| 查看连接 | `cat /etc/openvpn/openvpn-status.log` |
### 4.3 证书操作
| 场景 | 命令 |
|------|------|
| 生成客户端证书 | `./easyrsa build-client name nopass` |
| 撤销证书 | `./easyrsa revoke name` |
| 生成 CRL | `./easyrsa gen-crl` |
| 查看证书 | `./easyrsa show cert name` |
---
## 5. 小结
| 类别 | 关键点 |
|------|--------|
| 协议 | UDP推荐/TCP |
| 端口 | 1194 |
| 加密 | AES-256-GCM + SHA256 |
| 网络 | 10.8.0.0/24 |
| 认证 | 证书 + TLS |
| 客户端 | Windows/macOS/Linux/Android/iOS |
> 生产环境建议:使用 UDP 协议、配置证书 + 密码双因子认证、定期更换证书。

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
## 环境简介
| hostname | ip | mark |
| --- | --- | --- |
| lvs-1 | 192.168.30.13 | 主lvs |
| lvs-2 | 192.168.30.14 | 备lvs |
| k8s-master-1 | 192.168.30.6 | rs-1 |
| k8s-master-2 | 192.168.30.7 | rs-2 |
| k8s-master-3 | 192.168.30.12 | rs-3 |
## 搭建主备LVS
```plain
apt install keepalived net-tools -y #安装keepalived 和 net-tools
```
配置keepalived 配置文件
```plain
global_defs {
no_email_faults
}
# VRRP 实例配置
vrrp_instance VI_1 {
state MASTER #如果使用主/备,另外一台机器需要设置为BACKUP
interface ens32 #检测网络端口
virtual_router_id 100 #主备的虚拟机路由ID必须一致
priority 100 #主备的优先级,主优先级要大于备
advert_int 1 #VRRP Multicast广播周期秒数
authentication {
auth_type PASS # VRRP认证方式
auth_pass zhanxiaoyao # VRRP口令字
}
virtual_ipaddress {
192.168.30.200 # 如果有多个VIP继续换行填写
}
}
# 虚拟服务器配置
virtual_server 192.168.30.200 6443 {
delay_loop 1 # 每隔1秒查询realserver状态
lb_algo wrr # lvs 算法
lb_kind DR # Direct Route
protocol TCP # 用TCP协议检查realserver状态
persistence_timeout 300 # 会话保持时间这段时间内同一ip发起的请求将被转发到同一个realserver
# 第一台realserver物理环境
real_server 192.168.30.6 6443 {
weight 1
TCP_CHECK {
connect_port 6443 #设置监控检查的端口
connect_timeout 3 #设置连接超时时间
nb_get_retry 3 #设置重连次数
delay_before_retry 2 #设置重连间隔
}
}
# 第二台realserver物理环境
real_server 192.168.30.7 6443 {
weight 1
TCP_CHECK {
connect_port 6443 #设置监控检查的端口
connect_timeout 3 #设置连接超时时间
nb_get_retry 3 #设置重连次数
delay_before_retry 2 #设置重连间隔
}
}
# 第三台realserver物理环境
real_server 192.168.30.12 6443 {
weight 1
TCP_CHECK {
connect_port 6443 #设置监控检查的端口
connect_timeout 3 #设置连接超时时间
nb_get_retry 3 #设置重连次数
delay_before_retry 2 #设置重连间隔
}
}
}
```
```plain
systemctl enable keepalived
systemctl start keepalived
ipvsadm
ip a
```
## 搭建rs
```plain
vim /etc/keepalived-rs.sh
#!/bin/bash
VIP=192.168.30.200
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
/sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up
/sbin/route add -host $VIP dev lo:0
chmod 777 /etc/keepalived-rs.sh
vim /lib/systemd/system/keepalived-lvs-rs.service
[Unit]
Description=My Script
After=network.target
[Service]
ExecStart=/etc/keepalived-rs.sh
[Install]
WantedBy=default.target
```
```plain
reboot
```

File diff suppressed because it is too large Load Diff