avatar

青青子衿的拾枝杂谈

A text-focused Halo theme

  • 首页
  • linux基础
  • Linux系统
  • Linux高级
  • nginx
  • k8s
  • 网络
Home 数据库与自动化运维
文章

数据库与自动化运维

Posted recently Updated recently
By 青青子衿
78~101 min read

第四篇:数据库与自动化运维

本篇从"为什么需要数据库"这个根本问题出发,逐步带你掌握 MySQL 关系型数据库、Redis 内存数据库,以及自动化运维的核心技能。每一个知识点都遵循"遇到问题 -> 分析原因 -> 动手解决"的思路。


目录

  • 第一部分:MySQL 数据库
      1. 数据库介绍 | 2. MySQL 安装 | 3. MySQL 架构 | 4. SQL 语句
      1. 存储引擎 | 6. 用户及权限 | 7. 备份与恢复 | 8. 主从复制
      1. Mycat 中间件 | 10. MHA 高可用 | 11. LAMP 架构
  • 第二部分:Redis 内存数据库
      1. Redis 介绍 | 2. Redis 部署 | 3. 主从复制 | 4. 哨兵集群 | 5. Cluster
  • 第三部分:自动化运维简介
      1. Ansible | 2. Ansible Python API | 3. PXE+Kickstart | 4. OpenStack

第一部分:MySQL 数据库

1. 数据库介绍:为什么不能只用文件存数据?

问题场景

想象你是一个班主任,手里有一份 Excel 表格记录全班同学的成绩。如果只有你一个人用,文件就够了。但如果年级组长、各科老师、家长都要同时查看和修改呢?

  • 文件无法多人同时操作(并发问题)
  • 文件格式五花八门(格式不统一)
  • 电脑坏了文件就没了(安全问题)
  • 想查"年级前50名"要手动筛选半天(查询效率低)

解决方案:数据库管理系统(DBMS)

生活类比:数据库就像一个超大型的"智能档案柜"。

传统文件管理数据库管理
一个 Excel 文件一张"表"(Table)
一个文件夹一个"数据库"(Database)
手动查找用 SQL 语句秒级查询
只能一个人编辑支持多人并发访问
没有权限控制精确控制谁能看、谁能改

关系型数据库 vs 非关系型数据库

类型代表产品类比适用场景
关系型数据库MySQL、Oracle、PostgreSQLExcel 多表关联结构化数据、事务处理
非关系型数据库Redis、MongoDB便签纸 / 便利贴缓存、实时数据、灵活结构

关系模型:由数学家 Edgar Codd 于 1970 年提出。核心思想是用"二维表格"来表示数据,表与表之间通过"关系"(外键)关联。

MySQL vs MariaDB

MySQL 最初由瑞典 MySQL AB 公司开发,2008 年被 Sun 收购,2009 年 Sun 又被 Oracle 收购。原作者 Michael Widenius 因担心 Oracle 限制开源性,于 2009 年创建了分支项目 MariaDB(以女儿 Maria 命名)。

对比项MySQLMariaDB
维护方Oracle 公司社区驱动
许可证GPL / 商业双许可GPL
默认引擎InnoDBInnoDB(也支持 Aria)
适用场景企业级生产环境社区和开源项目

小贴士:在 CentOS/RHEL 7+ 中,默认数据库已从 MySQL 换成 MariaDB,两者高度兼容。


2. MySQL 安装:从零搭建你的第一个数据库

安装方式优点缺点适合谁
yum/rpm快速简单路径固定初学者
源码编译完全自定义步骤多生产环境

方式一:YUM 安装(推荐入门)

wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpm -ivh mysql57-community-release-el7-11.noarch.rpm
yum install mysql-community-server -y
systemctl start mysqld && systemctl enable mysqld

# 获取临时密码
grep 'temporary password' /var/log/mysqld.log

# 登录并密码
mysql -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewPass123!';

关键路径:/etc/my.cnf(配置文件) | /var/lib/mysql/(数据) | /var/log/mysqld.log(日志)

方式二:源码编译

yum install cmake gcc gcc-c++ ncurses-devel openssl-devel -y
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-5.7.38.tar.gz
tar -xvf mysql-boost-5.7.38.tar.gz -C /usr/local/src/
cd /usr/local/src/mysql-5.7.38/

cmake \
  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
  -DMYSQL_DATADIR=/usr/local/mysql/data \
  -DDEFAULT_CHARSET=utf8 \
  -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/boost

make && make install
mkdir -p /usr/local/mysql/data
chown -R mysql.mysql /usr/local/mysql/
/usr/local/mysql/bin/mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data
/usr/local/mysql/bin/mysqld_safe --user=mysql &

常见错误:boost not found -> 加 -DDOWNLOAD_BOOST 参数;Curses not found -> yum install ncurses-devel;WITH_SSL -> yum install openssl-devel。

初始化后基本操作

SHOW DATABASES;
CREATE DATABASE mydb CHARACTER SET utf8;
USE mydb;
CREATE TABLE student (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(30) NOT NULL, age TINYINT UNSIGNED);
INSERT INTO student (name, age) VALUES ('张三', 18);
SELECT * FROM student;

互动问题:学校 2000 名学生,用 Excel 和数据库分别查"年龄>17且姓张的学生"各需要多久?(提示:数据库的索引就像书的目录,可以秒级定位。)


3. MySQL 架构:一条 SQL 语句的旅程

输入 SELECT * FROM student WHERE age > 17; 时,MySQL 内部经历三层处理:

客户端(顾客点菜)
    |
    v
+-------------------------------+
| 连接层 (Connection Layer)     |  |  服务员:验证身份、权限检查
+-------------------------------+
|  SQL 层 (Server Layer)         |  厨师长:解析 SQL、优化执行计划
|  - 查询解析器 - 查询优化器      |
+-------------------------------+
|  存储引擎层 (Storage Engine)   |  厨师:取食材、做菜
|  InnoDB / MyISAM / Memory      |
+-------------------------------+
    |
    v
磁盘 / 内存(食材仓库)

关键理解:存储引擎是"插件式"的,同一张表可以选不同引擎,就像餐厅可以换厨师。

4. SQL 语句:和数据库对话的语言

SQL 按功能分为四大类:

类别全称命令用途
DDL数据定义语言CREATE, ALTER, DROP建库建表
DML数据操作语言INSERT, UPDATE, DELETE增删改
DQL数据查询语言SELECT查询
DCL数据控制语言GRANT, REVOKE权限

4.1 DDL - 建库建表

CREATE DATABASE school CHARACTER SET utf8;
SHOW DATABASES;
ALTER DATABASE school CHARACTER SET utf8mb4;
DROP DATABASE school;

USE school;
CREATE TABLE class (
    class_id INT PRIMARY KEY AUTO_INCREMENT,
    class_name VARCHAR(30) NOT NULL, teacher VARCHAR(20)
);
CREATE TABLE student (
    sid INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(30) NOT NULL,
    age TINYINT UNSIGNED DEFAULT 18,
    gender ENUM('M','F') NOT NULL DEFAULT 'M',
    score FLOAT(5,2), class_id INT, email VARCHAR(50) UNIQUE,
    jointime DATETIME NOT NULL,
    FOREIGN KEY (class_id) REFERENCES class(class_id)
);

DESC student;
SHOW CREATE TABLE student\G

ALTER TABLE student ADD phone CHAR(11) AFTER email;
ALTER TABLE student DROP phone;
ALTER TABLE student MODIFY age SMALLINT UNSIGNED;

CREATE INDEX idx_name ON student(name);
CREATE UNIQUE INDEX idx_email ON student(email);
DROP INDEX idx_name ON student;

数据类型速查:

类型字节常用场景
TINYINT1年龄、状态码
INT4主键、ID
BIGINT8大表主键
FLOAT4一般数值(7位有效)
DECIMAL可变金额(无精度损失)
CHAR(n)固定 n身份证号
VARCHAR(n)可变姓名、地址
DATE/DATETIME3/8日期时间
ENUM-单选(性别)
SET-多选(爱好)

FLOAT 精度陷阱:FLOAT(10,2) 存 697302.68,取出可能变 697302.69!金额务必用 DECIMAL。

4.2 DML - 增删改

INSERT INTO student (name, age, gender, score, class_id, jointime) VALUES ('张三', 18, 'M', 95.5, 1, NOW());

INSERT INTO student (name, age, gender, score, class_id, jointime) VALUES
    ('李四', 17, 'F', 88.0, 1, NOW()),
    ('王五', 19, 'M', 92.3, 2, NOW());

UPDATE student SET score = 99.0 WHERE sid = 1;
DELETE FROM student WHERE sid = 4;
-- 警告:UPDATE/DELETE 不加 WHERE 会影响所有行!

4.3 SELECT 查询(重点)

SELECT * FROM student;
SELECT name, age, score FROM student;
SELECT DISTINCT class_id FROM student;
SELECT name FROM student LIMIT 5;        -- 前5条
SELECT name FROM student LIMIT 5, 5;     -- 第6~10条

SELECT * FROM student WHERE age > 18;
SELECT * FROM student WHERE age BETWEEN 17 AND 19;
SELECT * FROM student WHERE gender='M' AND score > 90;
SELECT * FROM student WHERE class_id IN (1, 2, 3);
SELECT * FROM student WHERE name LIKE '张%';   -- % 匹配多个字符
SELECT * FROM student WHERE name LIKE '_三%';  -- _ 匹配一个字符
SELECT * FROM student WHERE email IS NULL;

SELECT * FROM student ORDER BY score DESC;

-- 分组 + 聚合
SELECT class_id,
    MAX(score) max_score, MIN(score) min_score,
    AVG(score) avg_score, COUNT(*) cnt
FROM student GROUP BY class_id;

-- HAVING(分组后过滤)
SELECT class_id, AVG(score) avg_score
FROM student GROUP BY class_id HAVING avg_score > 90;

-- 子查询:找每个班最高分的同学
SELECT name, score, class_id FROM student
WHERE score IN (SELECT MAX(score) FROM student GROUP BY class_id);

4.4 多表联查(JOIN)

类比:通过"班级编号"把"成绩表"和"班级表"关联起来。

-- 内连接:只返回匹配的行
SELECT e.emp_name, d.dept_name
FROM employee e INNER JOIN department d ON e.dept_id = d.dept_id;

-- 左外连接:左表所有行 + 右表匹配(不匹配为 NULL)
SELECT e.emp_name, d.dept_name
FROM employee e LEFT JOIN department d ON e.dept_id = d.dept_id;

-- 右外连接:右表所有行 + 左表匹配
SELECT e.emp_name, d.dept_name
FROM employee e RIGHT JOIN department d ON e.dept_id = d.dept_id;

-- 综合:求各部门最高薪水员工
SELECT e.emp_name, e.salary, d.dept_name
FROM employee e INNER JOIN department d ON e.dept_id = d.dept_id
WHERE e.salary IN (SELECT MAX(salary) FROM employee GROUP BY dept_id);

注意:JOIN 本质是集合论中"笛卡尔积"再条件筛选。内连接=交集,左连接=左集合+交集补NULL。和数学集合运算一脉相承。


5. 存储引擎:InnoDB 与 MyISAM 该怎么选?

特性InnoDBMyISAM
事务支持(ACID)不支持
锁行级锁表级锁
外键支持不支持
崩溃恢复支持不支持
适用高并发、需要事务读多写少
SHOW ENGINES\G
CREATE TABLE t1 (id INT) ENGINE=InnoDB;
CREATE TABLE t2 (id INT) ENGINE=MyISAM;

事务详解

事务像"银行转账"——要么完整执行,要么完全不做。

START TRANSACTION;
UPDATE account SET balance = balance - 2000 WHERE name = '张三';
UPDATE account SET balance = balance + 2000 WHERE name = '李四';
COMMIT;    -- 正常则提交
ROLLBACK;  -- 出错则回滚

-- 保存点
SAVEPOINT sp1;
ROLLBACK TO sp1;    -- 只回滚到保存点

ACID 特性:

特性含义类比
Atomicity(原子性)全做或全不做考试卷:交或不交
Consistency(一致性)数据始终一致转账前后总额不变
Isolation(隔离性)事务互不干扰考场里各做各的
Durability(持久性)提交后永久保存交了卷不能改

外键

CREATE TABLE dept (did INT PRIMARY KEY, dname VARCHAR(20)) ENGINE=InnoDB;
CREATE TABLE emp (
    id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), did INT,
    FOREIGN KEY (did) REFERENCES dept(did)
        ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

ALTER TABLE emp DROP FOREIGN KEY emp_ibfk_1;

6. 用户及权限管理:谁能看?谁能改?

-- 创建用户
CREATE USER 'teacher'@'localhost' IDENTIFIED BY 'Teach2024!';
CREATE USER 'student'@'192.168.1.%' IDENTIFIED BY 'Stu2024!';
CREATE USER 'admin'@'%' IDENTIFIED BY 'Admin2024!';

-- 授权
GRANT SELECT ON school.* TO 'teacher'@'localhost';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%';
GRANT SELECT(name, age) ON school.student TO 'user1'@'localhost';

-- 撤销
REVOKE INSERT ON school.* FROM 'teacher'@'localhost';
FLUSH PRIVILEGES;

-- 查看权限
SHOW GRANTS FOR 'teacher'@'localhost'\G

权限存储:全局 mysql.user | 库级 mysql.db | 表级 mysql.tables_priv | 列级 mysql.columns_priv

忘记密码

systemctl stop mysqld
mysqld_safe --skip-grant-tables --user=mysql &
mysql -u root
UPDATE mysql.user SET authentication_string=PASSWORD('NewPass!') WHERE User='root';
FLUSH PRIVILEGES;
systemctl restart mysqld

7. 备份与恢复:数据丢了怎么办?

对比项逻辑备份(mysqldump)物理备份(XtraBackup)
备份内容SQL 语句数据文件
速度慢快
跨平台可以不行
恢复速度慢快

mysqldump

# 全库
mysqldump -u root -p --all-databases > /backup/all_$(date +%F).sql
# 单库
mysqldump -u root -p --databases school > /backup/school.sql
# 指定表
mysqldump -u root -p school student class > /backup/tables.sql

# 生产推荐
mysqldump -u root -p \
  --single-transaction --master-data=2 --flush-logs \
  --all-databases > /backup/full_$(date +%F).sql

恢复:mysql -u root -p < /backup/all.sql

binlog 增量恢复

[mysqld]
server-id = 1
log-bin = /mysql-log/master
binlog-format = row
mysqlbinlog -v /mysql-log/master.00001                  # 查看
mysqlbinlog --start-position=154 --stop-position=1024 \
    /mysql-log/master.0001 | mysql -u root -p        # 按位置恢复
mysqlbinlog --start-datetime="2024-01-15 10:00:00" \
    /mysql-log/master.0001 | mysql -u root -p        # 按时间恢复

完整恢复流程(误删数据后):

  1. 先恢复全量备份:mysql -u root -p < /backup/full.sql
  2. 用 binlog 恢复从备份到误操作之间的增量
  3. 跳过误操作,继续恢复后续 binlog

备份脚本

#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%F)
mkdir -p $BACKUP_DIR
mysqldump -u root -p'YourPass' \
  --single-transaction --master-data=2 --flush-logs \
  --all-databases > ${BACKUP_DIR}/full_${DATE}.sql
find $BACKUP_DIR -name "*.sql" -mtime +30 -delete
echo "[$DATE] Done." >> /var/log/mysql_backup.log

8. 主从复制(AB复制):让数据自动抄写

原理

Master                              Slave
binlog --- IO Thread ---> relay-log --> SQL Thread(执行SQL)
  1. Master 的 IO 线程把 binlog 发给 Slave
  2. Slave 的 IO 线程写入 relay-log(中继日志)
  3. Slave 的 SQL 线程读取 relay-log 并执行

配置

Master (/etc/my.cnf):

[mysqld]
server-id = 1
log-bin = master
binlog-format = row
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.2' IDENTIFIED BY 'Repl2024!';
SHOW MASTER STATUS\G    -- 记下 File 和 Position

Slave (/etc/my.cnf):

[mysqld]
server-id = 2
STOP SLAVE;
CHANGE MASTER TO
    MASTER_HOST='192.168.10.1', MASTER_USER='repl',
    MASTER_PASSWORD='Repl2024!',
    MASTER_LOG_FILE='master.0001', MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS\G
-- 必须确认:Slave_IO_Running: Yes && Slave_SQL_Running: Yes

半同步复制

Master 提交事务后至少等一个 Slave 确认收到 binlog:

-- Master
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
SET GLOBAL rpl_semi_sync_master_timeout = 1000;  -- 超时降级为异步

-- Slave
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

GTID 复制

GTID = server_uuid:transaction_id,自动追踪事务:

[mysqld]
gtid_mode = on
enforce_gtid_consistency = on
log-slave-updates = 1
CHANGE MASTER TO MASTER_HOST='192.168.10.1', MASTER_USER='repl',
    MASTER_PASSWORD='Repl2024!', MASTER_AUTO_POSITION = 1;

9. Mycat 中间件:一台数据库扛不住怎么办?

Mycat 是应用和多个 MySQL 之间的"智能路由器":

功能说明
读写分离写发给主库,读发给从库
垂直切分不同业务表放不同库
水平切分同表数据按规则分散

部署

# 安装 JDK
tar -xvf jdk-8u131-linux-x64.tar.gz -C /usr/lib/
# 配置 JAVA_HOME
tar -zxvf Mycat-server-1.6-RELEASE-*.tar.gz -C /usr/local/
/usr/local/mycat/bin/mycat start   # 默认端口 8066

schema.xml 核心配置

<schema name="TESTDB" dataNode="dn1">
    <table name="orders" primaryKey="id" dataNode="dn1,dn2" rule="rule1" />
    <table name="employees" primaryKey="id" type="global" dataNode="dn1" />
</schema>
<dataNode name="dn1" dataHost="host1" database="mydb" />
<dataNode name="dn2" dataHost="host2" database="mydb" />
<dataHost name="host1" balance="1" writeType="0" dbType="mysql" dbDriver="native">
    <heartbeat>select user()</heartbeat>
    <writeHost host="master1" url="192.168.0.12:3306" user="mycat" password="pass">
        <readHost host="slave1" url="192.168.0.13:3306" user="mycat" password="pass" />
    </writeHost>
</dataHost>

balance 参数:0=不分离 | 1=读负载均衡(推荐) | 2=随机 | 3=只读从库


10. MHA 高可用:主库宕机了谁来接班?

问题

主从复制中主库宕机需手动切换——太慢!MHA 能在 0~30秒 内自动完成故障切换。

工作原理

  1. Manager 持续监控 Master 心跳
  2. Master 宕机后,MHA 尝试抢救 binlog
  3. 选择数据最新的 Slave 提升为新 Master
  4. 其他 Slave 自动指向新 Master

关键配置 (/etc/masterha/app1.cnf)

[server default]
manager_log=/var/log/masterha/app1/manager.log
manager_workdir=/var/log/masterha/app1
user=root
password=YourPass
repl_user=repl
repl_password=ReplPass
ssh_user=root
ping_interval=1

[server1]
candidate_master=1
hostname=192.168.0.202
master_binlog_dir=/var/lib/mysql

[server2]
candidate_master=1
hostname=192.168.0.203
master_binlog_dir=/var/lib/mysql

部署步骤

# 所有节点安装依赖和 MHA Node
yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch -y
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

# Manager 节点安装 MHA Manager
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm

# 配置 SSH 免密
ssh-keygen -t rsa && ssh-copy-id root@各节点

# 检查
masterha_check_ssh --conf=/etc/masterha/app1.cnf
masterha_check_repl --conf=/etc/masterha/app1.cnf

# 启动
masterha_manager --conf=/etc/masterha/app1.cnf &

11. LAMP 架构:把数据库接入 Web 应用

LAMP = Linux + Apache + MySQL + PHP

用户浏览器 -> Apache(httpd) -> PHP -> MySQL
yum install httpd php php-mysql mariadb mariadb-server -y
systemctl start httpd && systemctl start mariadb

# 测试 PHP
echo '<?php phpinfo(); ?>' > /var/www/html/test.php

# 创建应用数据库
mysql -u root -p -e "CREATE DATABASE owncloud;"
mysql -u root -p -e "GRANT ALL ON owncloud.* TO own@'localhost' IDENTIFIED BY 'Pass';"

第二部分:Redis 内存数据库

1. Redis 介绍:为什么需要便签纸式的数据库?

问题场景

假设你的成绩查询系统火了——每秒 1000 个家长同时查成绩。每次都去 MySQL 查,数据库扛不住。

类比:MySQL 像"笔记本"——内容全但翻找慢。Redis 像"便签纸"——贴在显示器旁,一眼看到。

Redis vs MySQL vs Memcached

对比项MySQLRedisMemcached
存储位置磁盘内存(可持久化)内存
数据结构二维表String/List/Hash/Set/ZSet只有 String
持久化天然支持RDB / AOF不支持
主从复制支持支持不支持
集群需中间件原生支持(3.0+)不支持
速度毫秒级微秒级微秒级

Redis 应用场景

  • 缓存:热点数据(成绩查询结果、商品详情)
  • 排行榜:ZSet 有序集合
  • 计数器:网站访问量、在线人数
  • Session 共享:分布式系统中的用户登录状态
  • 消息队列:List 结构实现简单队列

2. Redis 部署:安装配置与持久化

安装

wget http://download.redis.io/releases/redis-5.0.7.tar.gz
tar xvf redis-5.0.7.tar.gz && cd redis-5.0.7
make && make install PREFIX=/usr/local/redis
cp redis.conf /usr/local/redis/bin/

启动与连接

# 修改为后台运行
sed -i 's/^daemonize no/daemonize yes/' /usr/local/redis/bin/redis.conf

# 启动
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf

# 连接
/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379

# 关闭(正常关闭会先持久化)
/usr/local/redis/bin/redis-cli shutdown

基本操作

SET name "张三"           # 设置
GET name                  # 获取
MSET k1 v1 k2 v2 k3 v3   # 批量设置
MGET k1 k2 k3             # 批量获取
DEL name                  # 删除
INCR counter              # 自增(适合计数器)
SET session_id "abc" EX 3600   # 1小时后过期
TTL session_id                  # 查看剩余时间
SELECT 1                        # 切换到库1(默认0~15共16个库)

关键配置 (redis.conf)

bind 192.168.0.12         # 绑定地址
port 6379
daemonize yes
requirepass YourRedisPass2024!  # 密码(强烈建议!)
maxmemory 2gb
maxmemory-policy allkeys-lru    # 内存淘汰策略

持久化:RDB vs AOF

对比RDB(快照)AOF(追加日志)
原理定时生成快照记录每条写命令
文件大小小大
恢复速度快慢
数据安全可能丢最近数据最多丢1秒数据
推荐灾备数据安全要求高

RDB:

save 900 1       # 900秒内1次写入则快照
save 300 10      # 300秒内10次
save 60 10000    # 60秒内10000次
dbfilename dump.rdb

AOF:

appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec    # 每秒刷盘(推荐)

3. Redis 主从复制:数据自动同步

问题

单台 Redis 有单点故障风险,内存有限(一般不超 20G)。主从复制实现数据冗余和读负载分担。

配置

Master:无需特殊配置即可。

Slave (redis.conf):

port 6380
slaveof 192.168.0.12 6379
masterauth YourRedisPass2024!
rm -f appendonly.aof dump.rdb   # 清除旧持久化文件
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf

验证:

# Master
redis-cli -p 6379
> SET test_key "hello"
> INFO replication

# Slave
redis-cli -p 6380
> GET test_key     # "hello"
> SET foo bar       # 报错:READONLY(从机只读,不能写)

4. Redis 哨兵集群:自动故障切换

问题

主从模式中 Master 挂了需手动切换。Sentinel(哨兵) 自动监控 Master,故障时自动将 Slave 提升为新 Master。

Sentinel 三大功能

  1. 监控:检查 Master 和 Slave 是否存活
  2. 提醒:节点出问题时通知管理员
  3. 自动切换:Master 故障时自动提升 Slave 为新 Master

工作流程

Sentinel1 ─┐
Sentinel2 ─┤── 监控 ──→ Master
Sentinel3 ─┘              │
                          ├──→ Slave1
                          └──→ Slave2
  • SDOWN(主观下线):单个 Sentinel 认为某节点不可达
  • ODOWN(客观下线):多数 Sentinel 认为 Master 不可达 -> 触发故障转移

配置 (sentinel.conf)

port 26379
daemonize yes
sentinel monitor mymaster 192.168.0.12 6379 2    # 至少2个Sent才认为下线
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster YourRedisPass2024!
/usr/local/redis/bin/redis-sentinel /usr/local/redis/bin/sentinel.conf

# 验证
redis-cli -p 26379> SENTINEL masters
redis-cli -p 26379> SENTINEL slaves mymaster

5. Redis Cluster:真正的分布式集群

问题

主从和哨兵都不能水平扩容——数据量受限于单台内存。Redis Cluster 通过哈希槽将数据分散到多个节点。

核心概念:16384 个哈希槽

客户端写入 key="user:1001"
    |
    v
CRC16("user:1001") % 16384 = 7365
    |
    v
哈希 7365 -> 节点 B(槽 5461~10922)
    |
    v
数据存入节点 B
  • 16384 个哈希槽,通过 CRC16 算法平均分配给各 Master
  • 每个 Master 负责一部分槽,每个 Master 可以有 Slave
  • 最少 3 Master + 3 Slave = 6 节点

配置(每个节点 redis.conf)

daemonize yes
port 7000
bind 192.168.1.11            # 对外 IP(不能写127.0.0.1)
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes

创建集群

/usr/local/redis/bin/redis-cli --cluster create \
    192.168.1.11:7000 192.168.1.12:7000 \
    192.168.1.21:7000 192.168.1.22:7000 \
    192.168.1.31:7000 192.168.1.32:7000 \
    --cluster-replicas 1   

### 使用

```bash
# 必须加 -c
redis-cli -h 192.168.1.11 -p 7000 -c

192.168.1.11:7000> SET a 123
-> Redirected to slot [15495] located at 192.168.1.31:7000
OK

CLUSTER NODES         # 查看集群信息

节点管理

# 添加新节点
redis-cli --cluster add-node 192.168.1.41:7000 192.168.1.11:7000

# 重新分配槽
redis-cli --cluster reshard 192.168.1.41:7000

第三部分:自动化运维简介

1. Ansible 部署与使用

什么是 Ansible?

基于 Python 的自动化运维工具:

特性说明
无 Agent被控机不需装软件
无 Server直接运行命令
基于 SSH利用 SSH 连接
YAML 剧本用 YAML 描述操作

安装

yum install ansible -y
# 或 pip install ansible

Inventory(主机清单)

# /etc/ansible/hosts
[webservers]
192.168.1.10
192.168.1.11

[dbservers]
192.168.1.20 ansible_ssh_user=root ansible_ssh_pass=123

Ad-hoc 命令

ansible all -m ping                                    # 测试连通
ansible webservers -m shell -a "systemctl status httpd"  # 执行命令
ansible webservers -m copy -a "src=/tmp/a dest=/opt/"  # 拷贝文件
ansible webservers -m yum -a "name=httpd state=present"  # 安装
ansible webservers -m service -a "name=httpd state=started"  # 管理服务

常用模块:

模块用途
ping测试连通性
shell执行命令
copy拷贝文件
yum安装软件
service管理服务
file文件操作
user用户管理
template模板渲染

Playbook(剧本)

# deploy_web.yml
---
- name: Deploy Web Server
  hosts: webservers
  become: yes
  tasks:
    - name: Install Apache
      yum:
        name: httpd
        state: present

    - name: Start Apache
      service:
        name: httpd
        state: started
        enabled: yes

    - name: Deploy Content
      copy:
        src: index.html
        dest: /var/www/html/index.html

  handlers:
    - name: Restart Apache
      service:
        name: httpd
        state: restarted
ansible-playbook deploy_web.yml            # 执行
ansible-playbook deploy_web.yml --syntax-check  # 语法检查
ansible-playbook deploy_web.yml --check     # 模拟执行

2. Ansible Python API

通过 Python 脚本调用 Ansible:

#!/usr/bin/env python3
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase

class ResultCallback(CallbackBase):
    def v2_runner_on_ok(self, result):
        print(f"[OK] {result._host}: {result._result}")
    def v2_runner_on_failed(self, result):
        print(f"[FAIL] {result._host}: {result._result}")

loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['/etc/ansible/hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)

play_source = dict(
    name="Python API Demo",
    hosts='webservers',
    gather_facts='no',
    tasks=[
        dict(action=dict(module='shell', args='uptime')),
        dict(action=dict(module='yum', args='name=vim state=present')),
    ]
)

play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
tqm = TaskQueueManager(
    inventory=inventory, variable_manager=variable_manager,
    loader=loader, passwords=dict(), stdout_callback=ResultCallback()
)
try:
    tqm.run(play)
finally:
    tqm.cleanup()

3. PXE + Kickstart 批量装机

问题

给 100 台新电脑装系统,一台一台插 U 盘?太慢了。PXE 通过网络自动安装系统。

工作流程

新电脑开机(PXE 网卡启动)
    |
    v
DHCP 服务器 -> 分配 IP + 告知 TFTP 地址
    |
    v
TFTP 服务器 -> 下载启动内核和引导文件
    |
    v
Kickstart 应答文件 -> 自动完成分区、装包、设置密码
    |
    v
系统安装完成

DHCP 配置

# /etc/dhcp/dhcpd.conf
subnet 10.10.10.0 netmask 255.255.255.0 {
    range 10.10.10.10 10.10.10.100;
    option routers 10.10.10.1;
    option domain-name-servers 10.10.10.1;
    default-lease-time 600;
    max-lease-time 7200;
    next-server 10.10.10.1;          # TFTP 服务器地址
    filename "pxelinux.0";           # 引导文件
}

Kickstart 应答文件

# /var/ftp/ks.cfg
install
url --url=ftp://10.10.10.1/centos7
lang zh_CN.UTF-8
keyboard us
timezone Asia/Shanghai
rootpw --plaintext Admin2024!

clearpart --all
part /boot --fstype=xfs --size=500
part swap --fstype=swap --size=2048
part / --fstype=xfs --size=1 --grow

%packages
@base
@core
%end

%post
systemctl enable sshd
%end

PXE 引导菜单指向 ks 文件:

label linux
  kernel vmlinuz
  append initrd=initrd.img ks=ftp://10.10.10.1/ks.cfg

4. OpenStack 云计算简介

什么是云计算?

通过互联网按需提供计算资源(服务器、存储、网络)的服务模式。

类比:传统 IT 像自己打井取水,云计算像用自来水——按需使用,按量付费。

云的分类

类型说明例子
公有云第三方提供阿里云、AWS
私有云企业自建OpenStack
混合云公有 + 私有结合-

云的分层

层次全称提供什么用户需要做什么
IaaS基础设施即服务虚拟机自己装系统、部署应用
PaaS平台即服务运行环境只关注代码
SaaS软件即服务完整应用直接使用

OpenStack 核心组件

组件功能类比
Keystone身份认证门卫
Nova计算(虚拟机)房间管理
Glance镜像管理模板仓库
Neutron网络管理水电管线
Cinder块存储外接硬盘
Swift对象存储网盘
HorizonWeb 管理界面前台大厅
Placement资源调度调度员

工作流程

用户登录 Horizon (Web界面)
    |
    v
Keystone 验证身份 -> 选择镜像(Glance) + 配置(Nova)
    |
    v
Placement 调度 -> Nova 创建虚拟机 -> Neutron 分配网络
    |
    v
Cinder 挂载存储 -> 虚拟机启动完成

小结:OpenStack 是"云上操作系统",把服务器、存储、网络等硬件资源虚拟化,让用户通过 Web 界面申请和使用虚拟机。


总结与学习路径

知识体系

MySQL(持久化存储)
  ├── 基础:安装、SQL、存储引擎
  ├── 进阶:主从复制、备份恢复
  └── 高级:Mycat 分库分表、MHA 高可用

Redis(内存缓存)
  ├── 基础:安装、数据类型、持久化
  ├── 进阶:主从复制、哨兵
  └── 高级:Cluster 集群

自动化运维
  ├── Ansible:批量管理
  ├── PXE+Kickstart:批量装机
  └── OpenStack:云计算平台

推荐运维新人学习顺序

  1. 先装 MySQL,练习 SQL 语句(第 1~4 节)
  2. 理解存储引擎和权限(第 5~6 节)
  3. 搭建主从复制(第 8 节)
  4. 部署 Redis(第 1~2 节)
  5. Redis 主从和哨兵(第 3~4 节)
  6. 用 Ansible 批量管理(第三部分)
默认分类
mysql 自动化
License:  CC BY 4.0
Share

Further Reading

Jul 4, 2026

Nginx与Tomcat

Nginx 与 Tomcat 完全指南 目录 第一部分:Nginx 篇 1. Nginx 介绍 -- 你的网站为什么需要一位"前台接待员"?

Jul 4, 2026

网络协议与安全

网络协议与安全 -- 从入门到实战 目录 IP地址 -- 网络世界的门牌号 TCP/IP协议 -- 数据快递的工作流程 iptables防火墙

Jul 4, 2026

数据库与自动化运维

第四篇:数据库与自动化运维 本篇从"为什么需要数据库"这个根本问题出发,逐步带你掌握 MySQL 关系型数据库、Redis 内存数据库,以及自动化运维的核心技能。每一个知识点都遵循"遇到问题 -> 分析原因 -> 动手解决"的思路。 目录 第一部分:MySQL 数据库 数据库介绍 | 2. MySQ

OLDER

网络协议与安全

NEWER

Python编程

Recently Updated

  • 监控虚拟化与集群
  • Docker与Kubernetes
  • Nginx与Tomcat
  • 网络协议与安全
  • 数据库与自动化运维

Trending Tags

安全 Linux系统 nginx 日志管理 Linux服务 网络 Linux高级 pxe 中间件 python

Contents

©2026 青青子衿的拾枝杂谈 . Some rights reserved.

Using the Halo theme Chirpy