Linux

Linux服务

[TOC]

 

# mysql

**关系型数据库**

关系:就是一个一个的二维表 其中:表中的行,列次序并不重要

行(record): 表中的每一行,又称为一条记录

列(column):表中的每一列,称为属性,字段

主键(primary key):是一个属性,特性 用于确定一个记录的字段没有重复 主键在一张表中只有一个主键 但可以关联到多个字段 如图所示 两列合起来唯一即可 这叫复合主键

- - 主键可以避免出现冗余数据

域(domain): 属性的取值范围,如:性别只能是 男 和 女两个值

唯一键; 一张表上可以有好几个唯一键 允许为空

外键

 

 

 

增删改查 insert delete update select

 

 

### SQL概念

是结构化查询语言

​ SQL解释器: 数据存储协议: 应用层协议,c/s

S:server 监听于套尖子,接受并处理客户端的应用请求

C:client

​ 客户端程序接口: CLI(字符界面的) CUI(图形界面的)

​ 应用编程接口:ODBC JDBC

关系运算:

- 选择: 挑选出符合条件的行
- 投影: 挑选出需要的字段
- 连接: 表间字段的关联

 

**数据抽象:**

- 物理层: 数据存储格式,即
- 逻辑层:DBA角度,描述存储什么数据,以及数据间存在什么样的关系
- 视图层:用户角度,描述DB中的部分数据

关系模型的分类:

- 关系模型
- 基于对象的关系模型
- 半结构化的

mysql官方文档地址 [mariadb.com](http://mariadb.com/)

 

 

MYSQL特性 端口号是3306

- 插件是存储引擎:也称为"表类型" mysql5.5.5版本开始的默认存储引擎是innoDB 之前的版本是myisam
- 单进程 多线程
- 诸多扩展和新特性
- 注意有自己独立的用户 默认只有一个root用户 注意这不是Linux的账户

安装mysql

- Mariadb安装方式

- - 源代码:编译安装
- 二进制格式的程序包:展开至特定路径,并经过简单配置后即可使用
- 安装包 yum

- 注意6上的mysql的配置文件在(同时充当服务器端和客户端的配置文件) /etc/my.conf

- - service mysqld start 启动mysql
- /var/lib/mysql 是
- 登陆账户 mysql -u(指定以谁的身份连接 默认不输入是root) -p(后面跟口令)

- 7上安装yum install

- - .var/lib/mysql 是存放

 

 

#### 安全加固:

运行此脚本 mysql_secure_installation mysql安全脚本

 

 

连接至远程mysql服务器

 

 

 

**客户端程序:**

- mysql 交互式工具
- mysqldump 备份工具

 

 

**用户账号:**

- 两部分组成 用户名和允许登陆的主机名 username@主机名
- 注意 支持通配符写法 但由%代替* %匹配任意长度的任意字符 _ 匹配任意单个字符
-

 

**mysql****客户端** mysql的脚本后缀一般写成 .sql

使用模式:

交互式模式:

- 可运行命令有两类

- - 客户端命令 命令结尾可以不加 ;

- - \h, help

- 服务器端命令 命令结尾必须加 ;

非交互式模式 mysql -e '命令'

 

 

#### mysql客户端可用选项:

- -A, --no-auto-rehash 禁止补全
- **-u, --user=** **用户名,****默认为root**
- **-h, --host=** **服务器主机,****默认为localhost**
- **-p, --passowrd=** **用户密码,****建议使用-p,****默认为空密码**
- **-P, --port=** **服务器端口**
- -S, --socket= 指定连接socket文件路径
- -D, --database= 指定默认数据库
- -C, --compress 启用压缩
- **-e** **“SQL****“** **执行SQL****命令**
- -V, --version 显示版本
- -v --verbose 显示详细信息
- --print-defaults 获取程序默认使用的配置

 

### Mairadb配置

vim /etc/my.cnf

datadir=数据库数据存放路径

 

 

partprobe 同步一下

pvcreate /dev/sda6

vgcreate vg0 /devsda6

lvcreate vg0 /dev/sda6

lvcreate -n mysql -l 100%FREE vg0

lvdisplay

创建文件系统

- mkfs.xfs /dev/vg0/mesql
- blkid

挂载

- mkdir /data/mysql
- mount /dev/vg0/mysql /data/mysql

迁移数据

- vim /etc/my.cnf
- 将datadir=后面的路径更改为自己刚刚改的

 

 

 

#### 配置文件:

后面覆盖前面的配置文件,下面的优先级更高顺序如下

- /etc/my.cnf Global选项
- /etc/mysql/my.cnf Global选项
- SYSCONFDIR/my.cnf Global选项
- $MYSQL_HOME/my.cnf Server-specific 选项
- --defaults-extra-file=path
- ~/.my.cnf User-specific 选项

 

 

 

 

#### 通用二进制格式安装过程 以mysql10.2.19版本为例

1. 拷贝mariadb

2. 解包至指定文件夹 tar xf mar -C /usr/local

3. 进到此目录

4. 1. ​

5. 创建软连接 /usr/local/mysql

6. 1. ​

7. chown -R root.root /usr/local/mysql 修正所有者所属组,因为此时的所属组与所属者是不存在的

8. 此时没有数据库的用户账号

9. 1. 创建 useradd -r -s /sbin/nologin -d /data/mysql -c'描述' mysql

10. 存放数据库的文件的目录现在不存在

11. 1. 创建:mkdir /data/mysql或者
2. 创建文件夹并将所有者所属组等属性一次性设置好install -d /data/mysql -o 所有者 -g 所属组

12. 进到此目录 cd /usr/local/mysql

13. 创建

14. 1. ​

15. 准备mysql的配置文件

16. 1. mkdir /etc/mysql

2. cp support-files/my-large.cnf /etc/mysql/my.cnf

3. vim 刚拷过来的文件 在[mysqld]下面添加选项

4. 1. datadir=/data/mysql
2. 将socket的路径改为/data/mysql/mysql.sock[注意是两处socket]
3. ​

17. 将服务脚本拷贝 cp support-files/mysql.server /etx/init.d/ 并改名为mysqld 不改也可以

18. 执行chkconfig --add mysqld

19. 完成 启动

20. echo 'PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh

21. . /etc/profile.d/mysqld

22. 1. ​

23. 更改执行安全的脚本的socket路径 mysql_secure_installation

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#### 源码编译安装mariadb

- 安装包:yum install bison bison-devel zlib-devel libcurl-devel libarchive-devel boost-devel gcc gcc-c++ cmake ncurses-devel gnutls-devel libxml2-devel openssl-devel libevent-devel libaio-devel

- 做准备用户和数据目录

- - useradd –r –s /sbin/nologin –d /data/mysql/ mysql 创建用户
- mkdir /data/mysql 创建目录

chown mysql.mysql /data/mysql

tar xvf mariadb-10.2.18.tar.gz 解压缩

 

- cmake编译安装

cd mariadb-10.2.18/

cmake . \

-DCMAKE_INSTALL_PREFIX=/app/mysql \

-DMYSQL_DATADIR=/data/mysql/ \

-DSYSCONFDIR=/etc \

-DMYSQL_USER=mysql \

-DWITH_INNOBASE_STORAGE_ENGINE=1 \

-DWITH_ARCHIVE_STORAGE_ENGINE=1 \

-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \

-DWITH_PARTITION_STORAGE_ENGINE=1 \

-DWITHOUT_MROONGA_STORAGE_ENGINE=1 \

-DWITH_DEBUG=0 \

-DWITH_READLINE=1 \

-DWITH_SSL=system \

-DWITH_ZLIB=system \

-DWITH_LIBWRAP=0 \

-DENABLED_LOCAL_INFILE=1 \

-DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock \

-DDEFAULT_CHARSET=utf8 \

-DDEFAULT_COLLATION=utf8_general_ci

make -j

make install

- 提示:如果出错,执行rm -f CMakeCache.txt

 

cd /app/mysql

scripts/my

- 准备环境变量

echo 'PATH=/app/mysql/bin:$PATH' > /etc/profile.d/mysql.sh

. /etc/profile.d/mysql.sh

- 生成数据库文件

cd /app/mysql/

scripts/mysql_install_db --datadir=/data/mysql/ --user=mysql

- 准备配置文件

cp /app/mysql/support-files/my-huge.cnf /etc/my.cnf

- 准备启动脚本

cp /app/mysql/support-files/mysql.server /etc/init.d/mysqld

- 加载启动服务脚本

chkconfig --add mysqld ;service mysqld start

- 执行安全脚本

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


#### 实现mysql多实例: 基于源码编译的

- 多实例是一个软件运行好几个 有多个进程 每个实例在运行的时候互相之间是毫不相干的

- 在测试环境中使用

- 各个实例有各自的数据库目录 查看数据库目录

- - ​

-

 

搭载步骤: 此处是同一个程序开三个实例

1. 建立三个目录

mkdir /mysql/{3306,3307,3308} -pv

1. 建立目录存放各自的配置 此步骤不做也可以mkdir {3306,3307,3308}/{data,etc,socket,log,pid,log}

2. 更改所有者 chown -R mysql.mysql *

3. 生成数据库数据文件 用mysql自带的程序生成 重复操作/app/mysql/scripts/mysql_install_db --user=mysql --satadir=/mysql/3306/

4. 1. 进到/app/mysql/执行

\2. ./scripts/mysql_install_db --user=mysql --datadir=/mysql/3306/data

\3. 重复执行3307和3308

1. 准备配置文件 复制配置文件 到各自个实例下面 并更改 cp /app/mysql/etc/my.cnf /mysql3306

\1. 这另一种方法 能够简单快速完成 将另一台用rpm安装的最新版的mysql的配置文件拷贝过来并进行修改

\1. vim /mysql/3306/etc/my.cnf datadir=是数据库文件的存放路径

\2.

 

1. 准备服务启动脚本 每个实例应该有各自的启动脚本

2. 1. 修改启动脚本 需注意每个实例都有各自的端口号

2. 1. ​
2. cmd_path=是二进制路径

3. 将此文件拷贝至3307,3308的实例文件中 并更改端口号

4. 1. 赋予权限chmod +x /mysql/3306/mysqld

5. 运行安全脚本为当前实例加口令:

6. 1. 运行安全脚本方式 注意一定要指明路径在/app/mysql/ 下执行 ./scripts/mysql_instal_db –user=mysql –datadir=路径(数据库文件的存放路径)

2. 1. 注意不要在存放数据库文件的目录下存放隐藏文件

3. 下图是给3308实例运行安全脚本

4. ​

7. 启动程序./mysqld start ss -ntl查看端口号

8. 链接时要指明端口号 :连接mysql多实例

9. 1. mysql –uroot –p –S /mysql/3308/socket/mysql.sock
2. **或**mysql –uroot –h127.0.0.1(IP地址) –p 3308

10. 停止一个实例3308为例

11. 1. 进入到3308的目录下 执行 ./mysqld stop

12. 可以将各自示例的启动服务拷贝至init.d下 下面示范的是3308 需在3308目录下执行

13. 1. cp mysqld /etc/init.d/mysqld3308

2. 执行完后则可以用service 命令控制启动停止

3. 执行完后就是一个服务脚本了可以设置为开机启动 可以在启动脚本内添加

4. 1. ​

14. 创建用户:创建用户不要让他自动生成数据库家目录否则会自动拷贝配置文件要用mkdir手动创建

15. 1. useradd mysql –r –d /data/mysql

 

专门实现多实例的程序 但有局限性,适合于电脑上只有一个mysql版本mysqld_multi

​ 只能实现一个版本

 

 

 

 

 

 

 

 

 

 

 

 

 

## 数据库操作:

数据库说白了是文件夹 真正存数据的是文件 文件对应的是表

**mysqld_multi**

· 查看数据库文件列表的命令: 查看数据库列表:show databases;

· information_schema是个特殊的数据库 在内存中

#### 用户的数据库创建

l create database|schema [if ont exists] db_name

o database和schema都是创建数据库选一个就好

o [if ]目标不存在则创建,目标存在则不创建

o [db_name]数据库名字

· 查看数据库 show databases

· 创建数据库:create database testdb

· 指定字符集:character set =‘字符集名称’例如: create database db_name CHARACTER SET=utf8mb;

o 修改字符集:alter table student CHARACTER SET =utf8mb4;

o 设定整个服务器所有是使用的字符集:vim /etc/my.cnf

o

o 然后修改客户端配置文件 vim /etc/my.cnf.d/mysql-clients.cnf 也可以写入到my.cnf中 但写到此处更有条理

o

· 指定排序规则:collate ‘collate name’

l 删除数据库: drop database|schema [if exists] ‘db_name’

l 查看本机支持的所有字符集: show collation;

l 查看数据库列表mysql > show databases

l 字符集:

n 查看数据库用的什么字符集: cat /var/lib/mysql/db_name/db.opt

u 第一排是字符集 第二排是排序规则

u

n shou create database db_name

 

 

 

#### 数据库的表

 

###### 创建表

表示真正存数据的

l 创建表: 帮助:help create table;

n 语法: create table [if not esists] ‘tbl_name’ (列的名称 类型 修饰符,列的名称2 类型2 修饰符,…)

u 举例:create table

n create [temporary] table [if not esists] tbl_name (create_definition…)

u [temporary] 临时表 是可选项

u [if not esists] 如果存在则不创建

u tbl_name表名称

u (create_definition…) 创建表时的定义

n 第二种创建表的方式: 将输出内容作为表的此表的内容 create table 新表 select * from 旧表;

n 第三种创建表的方式: 复制表结构:create table custom like 旧表; 注意此方法如跨库使用则标明

u 如:carete table 新表名称 like 库名称.表名称

l 字段的名称 字段的数据类型 修饰符

n 修饰符:NULL 数据列可包含空值(默认的可以不写) NOT NULL DEFAULT默认值 PRIMARY KRY主键 UNIQUE KEY 唯一键 CHARACTER SET name 指定一个字符集(注意这是给字段单独指定一个字符集 最好别用)

u 数值型: AUTO_INCREMENT 自动递增,适用于整数类型 只适用于数字 UNSIGEND 无符号

n 数据类型:分为三大类 数值型(分为整数型和小数型) 字符型 时间\日期型

n

u 整数型: tinyint(m) 1个字节 范围(-128~127) smallint(m) 2个字节 范围(-32768~32767) mediumint(m) 3个字节 范围(-8388608~8388607) int(m) 4个字节 范围(-2147483648~2147483647) bigint(m) 8个字节 范围(+-9.22*10的18次方)

l 加了unsigned,则最大值翻倍,如:tinyint unsigned的取值范围为(0~255) int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围

n 举例:创建一个存放学员信息的数据库和表:

\1. create database studentdb; 创建数据库

\2. use stubentdb;使用这个数据库

\3. create table student (id int unsigned auto_increment primary, name varchar (10), sex enum(‘f’,’m’) default ‘m’, phone char(11), address varchar(50))

l id,name,sex,phone,address 是字段名称

l unsigned 是只允许为整数 auto_increment是数值自动排序 primary添加主键(主键默认不允许为空) enum 是眉举 只能在特定的字符或字符串中选一个 default ’m’ 默认是m

l 创建完成之后查看表结构:desc student; 和show columns from stundent; student是表名称

###### 表操作

 

 

n 注意:在老版本的数据库中,没有ibd文件(存放表的数据的位置) 而是将所有库的所有表的数据都放在了/var/lib/mysql/ibdata1文件中 但可以设置为有ibd文件

u 可以通过此命令查看是否开启ON是开启show variables like ‘%per_table%’;

u 可以在配置文件内加一行 innodb_file_per_table=ON

n 如果查看表时现实的太乱可在其结尾加上\G

n 查看所有的引擎:SHOW ENGINES

n 查看表:SHOW TABLES [FROM db_name]

n 查看表结构:DESC [db_name.]tb_name

u SHOW COLUMNS FROM [db_name.]tb_name

n 删除表:DROP TABLE [IF EXISTS] tb_name

n 查看表创建命令:SHOW CREATE TABLE tbl_name

n 查看表状态:SHOW TABLE STATUS LIKE 'tbl_name’

n 查看库中所有表状态:SHOW TABLE STATUS FROM db_name

n 查看当初是怎么定义表的: show create table 表名称;

 

 

l 表表现为横行纵列

n 列称为字段:字段名,字段数据类型(比如:数字,字符串,整数,小数),修饰符(是约束,限定.例如:是否允许字段为空)

u 数据类型

u 决定了此字段在磁盘上保存上占的空间多大

u

n 行称为记录

 

l DROP TABLE [IF EXISTS] 'tbl_name';

l ALTER TABLE 'tbl_name'

n 字段:

u 添加字段:add

u ADD col1 data_type [FIRST|AFTER col_name] first是将新添加的字段设为整个表的第一个字段 AFTER col_name 是在特定的字段后面添加一个新字段

u 删除字段:drop

u 修改字段:

u alter(默认值), change(字段名), modify(字段属性)

n 索引:

u 添加索引:add index

u 删除索引:drop index

n 表选项

u 修改:

l 查看表上的索引:SHOW INDEXES FROM [db_name.]tbl_name;

l 查看帮助:Help ALTER TABLE

l 通表结构能修改但很少去修改

 

 

 

###### 数据类型

 

[点这里查看详细的](#数据类型)

l 数据类型:数据类型:数据类型:

n 数据长什么样

n 数据需要多少空间来存放

l 系统内置数据类型和用户定义数据类型

l MySql支持多种列类型:

n 数值类型

n 日期/时间类型

n 字符串(字符)类型

n https://dev.mysql.com/doc/refman/5.5/en/data-types.html

l 选择正确的数据类型对于获得高性能至关重要,三大原则:

n 更小的通常更好,尽量使用可正确存储数据的最小数据类型

n 简单就好,简单数据类型的操作通常需要更少的CPU周期

n 尽量避免NULL,包含为NULL的列,对MySQL更难优化

 

**一、** **整型**

a) tinyint(m) 1个字节 范围(-128~127)

b) smallint(m) 2个字节 范围(-32768~32767)

c) mediumint(m) 3个字节 范围(-8388608~8388607)

d) int(m) 4个字节 范围(-2147483648~2147483647)

e) bigint(m) 8个字节 范围(+-9.22*10的18次方)

f) 加了unsigned,则最大值翻倍,如:tinyint unsigned的取值范围为(0~255)int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,Int(1)和Int(20)是相同的

g) BOOL,BOOLEAN:布尔型,是TINYINT(1)的同义词。zero值被视为假,非zero值视为真

**二、** **浮点型(float****和double)****,近似值**

a) float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位

b) double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位

c) 设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位

**三、** **定点数**

a) 在数据库中存放的是精确值,存为十进制

b) decimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位

c) MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。例如,decimal(18,9)小数点两边将各存储9个数字,一共使用9个字节:小数点前的数字用4个字节,小数点后的数字用4个字节,小数点本身占1个字节

d) 浮点类型在存储同样范围的值时,通常比decimal使用更少的空间。float使用4个字节存储。double占用8个字节

e) 因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用decimal——例如存储财务数据。但在数据量比较大的时候,可以考虑使用bigint代替decimal

四、 字符串(char,varchar,_text)

a) char(n) 固定长度,最多255个字符

b) varchar(n) 可变长度,最多65535个字符

c) tinytext 可变长度,最多255个字符

d) text 可变长度,最多65535个字符

e) mediumtext 可变长度,最多2的24次方-1个字符

f) longtext 可变长度,最多2的32次方-1个字符

g) BINARY(M) 固定长度,可存二进制或字符,长度为0-M字节

h) VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节

i) 内建类型:ENUM枚举, SET集合

**五、** **char****和varchar****:**

a) char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉,所以char类型存储的字符串末尾不能有空格,varchar不限于此

b) char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节

c) char类型的字符串检索速度要比varchar类型的快

**六、** **varchar****和text****:**

a) varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n< n>255),text是实际字符数+2个字节。

b) .text类型不能有默认值

c) varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text

**七、** **.****二进制数据:BLOB**

a) BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob是以二进制方式存储,不分大小写

b) BLOB存储的数据只能整体读出

c) TEXT可以指定字符集,BLOB不用指定字符集

**八、** **日期时间类型**

a) date 日期 '2008-12-2'

b) time 时间 '12:25:36'

c) datetime 日期时间 '2008-12-2 22:06:44'

d) timestamp 自动存储记录修改时间

e) YEAR(2), YEAR(4):年份

f) timestamp字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间

**九、** **修饰符**

所有类型:

a) NULL 数据列可包含NULL值

b) NOT NULL 数据列不允许包含NULL值

c) DEFAULT 默认值

d) PRIMARY KEY 主键

e) UNIQUE KEY 唯一键

f) CHARACTER SET name 指定一个字符集

数值型

g) AUTO_INCREMENT 自动递增,适用于整数类型

h) UNSIGNED 无符号

 

 

 

##### DML语句

l DML: insert,delete,uptate 增 删 改

n insert: 增

u 一次插入一行或多行数据

u 语法:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)]

{VALUES | VALUE} ({expr | DEFAULT},...),(...),...

[ ON DUPLICATE KEY UPDATE 如果重复更新之

col_name=expr

[ , col_name=expr] ... ]

u 简化写法:

l INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)

u 举例: 对记录赋值

l insert student set name=’wang’ , age=18,address=’北京’; 此方法用的较少

l insert 新表 select * from 旧表; 将旧表的内容批量的添加到新表中. 注意 新表与旧表格式必须相同

l insert into student (name,age,mobile,address) values (‘mage’ , 30 , 手机号, ‘北京’), (‘zhangsir’ ,28,手机号,’郑州’) 值和字段的顺序必须一一对应

l

 

 

n delete删除

u 删除数据库:drop database

u 删除表drop table

u 删除表:truncate table student; 注意这个速度较快但不会记录到日志 非常危险

u 删除表中记录:delete from 表名称 where 位置

l 例如:删除id大于5的记录 delete from student where id >= 5;

n update改

u update 表名称 set name

 

 

 

**select****语句**

 

#### 日志

##### 事务日志

事务日志默认存放位置是存放数据库文件的路径

 

vim /etc/my.cnf

在mysqld下输入

 

事务日志优化 innodb_flush_log_at_trx_commit 2性能最好 最常用 1最安全

说明:设置为1,同时sync_binlog = 1表示最高级别的容错 innodb_use_global_flush_log_at_trx_commit的值确定是否可以使用SET语句重置此变量

1默认情况下,日志缓冲区将写入日志文件,并在每次事务后执行刷新到磁盘。 这是完全遵守ACID特性

0提交时没有任何操作; 而是每秒执行一次日志缓冲区写入和刷新。 这样可以提供更好的性能,但服务器崩溃可以清除最后一秒的事务

2每次提交后都会写入日志缓冲区,但每秒都会进行一次刷新。 性能比0略好一些,但操作系统或停电可能导致最后一秒的交易丢失

3模拟MariaDB 5.5组提交(每组提交3个同步),此项MariaDB 10.0支持

 

 

 

##### 错误日志

错误日志路径log-error=

重启服务也会记录到错误日志

 

##### 通用日志

记录对数据库的通用操作,包括错误的sql语句

没有性能负担时不需启用 是分析的

通用日志相关设置

general_log=ON|OFF 是否启用(默认是OFF) set goobal general_log=ON(临时开启)

general_log_file=HOSTNAME.log 通用日志存放路径

log_output=TABLE|FILE|NONE 将通用日志存放在数据库文件中

​ file是默认的,存放在文件内 table是存放为数据库文件

 

##### 慢查询日志

记录什么命令执行的时间过长

**slow_query_log=ON/OFF** **是否启用**

默认的名称是HOSTNAME-slow.log

show_query_log_filter=HOSTNAME-slow.log 慢查询的日志文件

**select @@long_query_time;** **查询慢查询的阈值** **单位是秒**

long_query_time=几秒钟 默认是十秒 需要更改为更小,十秒太长

**log_queries_not_using_indexes=ON** 不使用索引或使用全索引扫描,不论是否达到慢查询阀值的语句是否记录日志,默认OFF,即不记录 不利用索引即记入慢查询日志

log_slow_rate_limit = 1 多少次查询才记录,mariadb特有

log_slow_verbosity= Query_plan,explain 记录内容

log_slow_queries = OFF 同slow_query_log 新版已废弃

profiling=ON/OFF 是查询慢查询记录慢在了哪里

n show profiles;

n

n show profile fur query 5; 查询第5条记录

 

 

##### 二进制日志

非常重要! 生产中要启用,设置为行格式

二进制特型:

1) 默认是不启用的,但需要启用 需定期清理

2) 利用二进制日志能恢复数据的操作 mysql > 二进制日志里面的命令

3) 记录整个数据库的所有增删改操作 不记录读操作 人为不删除会一直存在

4) 记录已提交的日志

5) 不依赖存储引擎类型

6) 功能:通过 “重放”日志文件中的事件来生成数据副本

注意:建议二进制日志和数据文件分开存放默认是在一起的 需分离

 

二进制记录格式:

· 有三种记录格式

o 基于“语句”记录:statement ,记录语句,默认模式

o 基于 “行”记录:row ,记录数据,日志量较大 建议更改为此记录格式

o 混合模式:mixed, 让系统自行判定该基于哪种方式进行

· 格式配置

o show variables like ‘binlog_format’;

· 二进制日志文件的构成

o 有两类文件

§ 日志文件:mysql|mariadb-bin.文件名后缀,二进制格式 如: mariadb-bin.000001 二进制日志本身

§ 索引文件:mysql|mariadb-bin.index,文本格式

二进制日志相关的服务器变量/选项:

o sql_log_bin=ON|OFF:是否记录二进制日志,默认ON 此项启用并不代表真正启用二进制日志,需与下一项配合

o log_bin=/PATH/BIN_LOG_FILE:指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可

§ 注意 写进配置文件不能写log_bin=ON此写法表示的是指二进制文件名的前缀,应写为log-bin是默认,

§ 建议不仅仅写log_bin 应写为log_bin=/路径/路径/名称前缀

§ set sql_log_bin=ON|OFF 临时启用二进制日志 临时禁用二进制日志

o binlog_format=STATEMENT|ROW|MIXED:二进制日志记录的格式,默认STATEMENT 建议更改为行级别的:即ROW select

o set @@binlog_format 查看二进制日志记录格式

o max_binlog_size=1073741824:单个二进制日志文件的最大体积,到达最大值会自动生成新的二进制日志文件,默认为1G 数据库重启也会生成新的二进制日志文件 flush logs也可以生成新的二进制日志文件

§ 说明:文件达到上限时的大小未必为指定的精确值

o sync_binlog=1|0:设定是否启动二进制日志即时同步磁盘功能,默认0,由操作系统负责同步日志到磁盘,1代表只要有二进制日志文件生成就会同步至磁盘 1安全 0高性能

o expire_logs_days=N:二进制日志可以自动删除的天数。 默认为0,即不自动删除 单位是天数 时间最好设长一点

二进制日志相关配置

o 查看mariadb自行管理使用中的二进制日志文件列表,及大小

§ SHOW {BINARY | MASTER} LOGS

o 查看使用中的二进制日志文件

§ SHOW MASTER STATUS

o 查看二进制文件中的指定内容

§ SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]

§ show binlog events in ‘mysql-bin.000001' from 6516 limit 2,3

§ from从哪开始看 limit 跳过几个看几个

· flush logs刷新二进制日志文件 生成新的二进制日志文件 切换二进制日志文件

 

 

日志

o mysqlbinlog:二进制日志的客户端命令工具 执行的命令默认是用base64编码加密过 加-v可显示

o 命令格式

§ mysqlbinlog [OPTIONS] log_file…

§ --start-position=# 指定开始位置

§ --stop-position=# 指定结束位置

§ --start-datetime= 指定开始时间

§ --stop-datetime= 指定结束时间 不写即是从指定开始时间到最后的所有内容全部显示

§ 时间格式:YYYY-MM-DD hh:mm:ss

§ --base64-output[=name]

§ -v -vvv

 

二进制日志事件的格式

o # at 328

o #151105 16:31:40 server id 1 end_log_pos 431 Query thread_id=1 exec_time=0 error_code=0

o use `mydb`/*!*/;

o SET TIMESTAMP=1446712300/*!*/;

o CREATE TABLE tb1 (id int, name char(30))

o /*!*/;

o 事件发生的日期和时间:151105 16:31:40

o 事件发生的服务器标识:server id 1

o 事件的结束位置:end_log_pos 431

o 事件的类型:Query

o 事件发生时所在服务器执行此事件的线程的ID:thread_id=1

o 语句的时间戳与将其写入二进制文件中的时间差:exec_time=0

o 错误代码:error_code=0

o 事件内容:

o GTID:Global Transaction ID,mysql5.6以mariadb10以上版本专属属性:GTID

 

清除指定二进制日志

注意清除二进制文件之前要做好备份

清除指定二进制文件

PURGE { BINARY | MASTER } LOGS

{ TO 'log_name' | BEFORE datetime_expr }

示例:

PURGE BINARY LOGS TO ‘mariadb-bin.000003’;删除3之前的日志

PURGE BINARY LOGS BEFORE '2017-01-23';

PURGE BINARY LOGS BEFORE '2017-03-22 09:25:30';

删除所有二进制日志,index文件重新记数

RESET MASTER [TO #]; 删除所有二进制日志文件,并重新生成日志文件,文件名从#开始记数,默认从1开始,一般是master主机第一次启动时执行,MariaDB10.1.6开始支持TO #

 

 

恢复数据库2018-12-3 16:18:40

导出二进制日志文件:

 

 

 

 

 

 

 

 

## 数据库备份恢复

l 备份类型:

n 完全备份,部分备份

u 完全备份:整个数据集

u 部分备份:只备份数据子集,如部分库或表

n 完全备份、增量备份、差异备份

u 增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂

u 差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单

l 注意:二进制日志文件不应该与数据文件放在同一磁盘

 

l 冷、温、热备份

n 冷备:读写操作均不可进行

n 温备:读操作可执行;但写操作不可执行,需手动加锁

n 热备:读写操作均可执行

u MyISAM:温备,不支持热备

u InnoDB:都支持

l 物理和逻辑备份

n 物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快

n 逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度

 

### 备份和恢复

备份工具

\1. cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份

\2. LVM的快照:先加锁,做快照后解锁,几乎热备;借助文件系统工具进行备份

a) 基于LVM的备份 不影响用户访问 但会影响用户访问的性能

b) (1) 请求锁定所有表

​ i. mysql> FLUSH TABLES WITH READ LOCK;

c) (2) 记录二进制日志文件及事件位置

​ i. 1. mysql> FLUSH LOGS;

​ ii. 2. mysql> SHOW MASTER STATUS;

​ iii. 3. mysql -e 'SHOW MASTER STATUS' > /PATH/TO/SOMEFILE

d) (3) 创建快照

​ i. 1. lvcreate -L # -s -p r -n NAME /DEV/VG_NAME/LV_NAME

e) (4) 释放锁

​ i. 1. mysql> UNLOCK TABLES;

f) (5) 挂载快照卷,执行数据备份

g) (6) 备份完成后,删除快照卷

h) (7) 制定好策略,通过原卷备份二进制日志

\3. mysqldump:逻辑备份工具,适用所有存储引擎,温备;支持完全或部分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份

a) **逻辑备份工具:mysqldump,** mydumper, **phpMyAdmin(****这是web****界面的)**

b) Schema和数据存储在一起、巨大的SQL语句、单个巨大的备份文件

​ i. Schema

c) mysqldump工具:客户端命令,通过mysql协议连接至mysql服务器进行备份

​ **i.** **注意此工具只是将数据库内容打印到屏幕上,****需配合重定向来存储** **而且还原时需手动创建数据库,****因为此方法备份的数据会非常巨大,****需打包压缩**

​ ii. mysqldump [OPTIONS] database [tables] **此语法不建议使用**(因为此命令不会备份数据库结构)

1. database是数据库名称 此命令是备份整个数据库

2. 注意:只能同时对一个数据库进行备份

​ iii. mysqldump [OPTIONS] --database DB1 [DB2 DB3...]

1. 此命令是指定数据库进行备份 DB是代表数据库内的表的

2. --database可以缩写为-B

3. 注意此方法不会备份函数,存储过程,触发器等

a) 举例:用此方法备份数据库 mysqldump –B备份数据库

​ i.

​ ii.

b) 此方法是将备份与压缩和并到一起mysqldump –B hellp | xz > hello_bak.sql.xz

​ i. 注意hello_bak.sql是备份后的名称 xz是备份方式

​ iv. mysqldump [OPTIONS] –A [OPTIONS]此方法是备份整个数据库 此方法会同时备份mysql 生产中一般都用-A选项

1. –A是 --alldatabase的缩写

2. 会将所有内容与设置全部保存 如函数.存储过程,函数.触发器等

​ v. mysqldump常见选项:

1. -A, --all-databases 备份所有数据库,含create database

2. -B , --databases db_name… 指定备份的数据库,包括create database语句

3. -E, --events:备份相关的所有event scheduler

4. -R, --routines:备份所有存储过程和自定义函数

5. --triggers:备份表相关触发器,默认启用,用--skip-triggers,不备份触发器

6. --default-character-set=utf8 指定字符集

7. --master-data[=#]****:** **此选项须启用二进制日志**

a) 1:所备份的数据之前加一条记录为CHANGE MASTER TO语句,非注释,不指定#,默认为1

b) 2:记录为注释的CHANGE MASTER TO语句 CHANGE MASTER TO是命令主从复制的

c) 此选项会自动关闭--lock-tables功能,自动打开-x | --lock-all-tables功能(除非开启--single-transaction)

d) -1是配合主从复制用的 如不需要可更改为2

8. **-F, --flush-logs** **:备份前滚动日志**,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A 或 -B 选项时,会导致刷新多次数据库。建议在同一时刻执行转储和日志刷新,可通过和--single-transaction或-x,--master-data 一起使用实现,此时只刷新一次日志

9. --compact 去掉注释,适合调试,生产不使用 不存储注释的内容

10. -d, --no-data 只备份表结构

11. -t, --no-create-info 只备份数据,不备份create table

12. -n,--no-create-db 不备份create database,可被-A或-B覆盖

13. --flush-privileges 备份mysql或相关时需要使用

14. -f, --force 忽略SQL错误,继续执行

15. --hex-blob 使用十六进制符号转储二进制列,当有包括BINARY, VARBINARY,BLOB,BIT的数据类型的列时使用,避免乱码

16. -q, --quick 不缓存查询,直接输出,加快备份速度

d) mysqldump参考: <https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html>

\4. xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份

\5. MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现

\6. mysqlbackup:热备份, MySQL Enterprise Edition组件

\7. mysqlhotcopy:PERL 语言实现,几乎冷备,仅适用于MyISAM存储引擎,使用LOCK TABLES、FLUSH TABLES和cp或scp来快速备份数据库

 

 

如何实现分库备份:2018年12月5日10:53:44

for db in `mysql –e ‘show database’ | grep –Eiv ‘^(database|infomantion_schema|performance)$’`;do mysqldump –B $db |gzip > $db `date + %F` .sql.gz;done

或者mysql –e ‘show database’ |grep –EV ‘^(database|infomantion_schema|performance)$’|sed –r ‘s/(.*)/mysqldump –B \1 |gzip > \/data\/1.sql.gz/’ |bash

 

 

 

 

innodb和myisam的区别

 

 

**MyISAM****备份选项:**

l 支持温备;不支持热备,所以必须先锁定要备份的库,而后启动备份操作

l 锁定方法如下:

n -x,--lock-all-tables:加全局读锁,锁定所有库的所有表,同时加--single-transaction或--lock-tables选项会关闭此选项功能 强烈建议加-x MySAM推荐加-x

n 注意:数据量大时,可能会导致长时间无法并发访问数据库

n -l,--lock-tables:对于需要备份的每个数据库,在启动备份之前分别锁定其所有表,默认为on,--skip-lock-tables选项可禁用,对备份MyISAM的多个库,可能会造成数据不一致

注:以上选项对InnoDB表一样生效,实现温备,但不推荐使用

 

**InnoDB****备份选项:**

l 支持热备,可用温备但不建议用

n --single-transaction 加此选项才开启事务 强烈推荐使用!

u 注意可以隔离DML语句 但不可以隔离DCL语句

n 此选项Innodb中推荐使用,不适用MyISAM,此选项会开始备份前,先执行START TRANSACTION指令开启事务

n 此选项通过在单个事务中转储所有表来创建一致的快照。 仅适用于存储在支持多版本控制的存储引擎中的表(目前只有InnoDB可以); 转储不保证与其他存储引擎保持一致。 在进行单事务转储时,要确保有效的转储文件(正确的表内容和二进制日志位置),没有其他连接应该使用以下语句:ALTER TABLE,DROP TABLE,RENAME TABLE,TRUNCATE TABLE

n 此选项和--lock-tables(此选项隐含提交挂起的事务)选项是相互排斥

n 备份大型表时,建议将--single-transaction选项和--quick结合一起使用

 

**InnoDB****建议备份策略**

mysqldump –uroot –A –F –E –R --single-transaction --master-data=1 --flush-privileges --triggers --default-character-set=utf8 --hex-blob >$BACKUP/fullbak_$BACKUP_TIME.sql

**MyISAM****建议备份策略**

mysqldump –uroot –A –F –E –R –x --master-data=1 --flush-privileges --triggers --default-character-set=utf8 --hex-blob >$BACKUP/fullbak_$BACKUP_TIME.sql

 

 

实验:删除数据库还原至最新状态

1. 备份

a) 数据库和二进制文件分离存放

b) 确认字符集和存储引擎

c) 做完全备份命令

d) 对数据库修改

e) 破坏数据库: rm –rf /var/lib/mysql*

2. 还原

a) 禁止用户访问

b)

 

 

 

生产中一般都是人为删除造成的数据库损坏:人为损坏数据库恢复方法:恢复误操作

\1. 禁止用户访问

\2. 关闭二进制日志: set sql_log_bin=off; 查看是成功关闭: select @@sql_log_bin;

\3. 还原完全备份 mysql> source /路径/完全备份文件

\4. 查看二进制日志 找出完全备份的时间 确定二进制日志的位置

\5. mysqlbinlog mysql-bin.000011 > /路径/文件

\6. 打开此文件 找到DROP命令并删除

\7. mysql > source /路径/文件

\8. 开放二进制日志

 

 

 

 

 

 

 

 

 

 

### xtrabackup进行备份的工具

是进行备份的工具

l **特点:**

n 备份还原过程快速、可靠

n 备份过程不会打断正在执行的事务

n 能够基于压缩等功能节约磁盘空间和流量

n 自动实现备份检验

n 开源,免费

Xtrabackup的新版变化:

l xtrabackup版本升级到2.4后,相比之前的2.1有了比较大的变化:innobackupex 功能全部集成到 xtrabackup 里面,只有一个 binary程序,另外为了兼容考虑,innobackupex作为 xtrabackup 的软链接,即xtrabackup现在支持非Innodb表备份,并且 Innobackupex 在下一版本中移除,建议通过xtrabackup替换innobackupex

l xtrabackup安装:

u yum install percona-xtrabackup 在EPEL源中

n 最新版本下载安装:

u https://www.percona.com/downloads/XtraBackup/LATEST/

 

 

 

Xtrabackup2.2版之前包括4个可执行文件:

n innobackupex: Perl 脚本

n xtrabackup: C/C++ 编译的二进制

n xbcrypt: 加解密

n xbstream: 支持并发写的流文件格式

n xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 MySQL Server 没有交互

l innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 MySQL Server 发送命令进行交互,如加全局读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。即innobackupex是在 xtrabackup 之上做了一层封装实现的

l 虽然目前一般不用 MyISAM 表,只是 MySQL 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行

 

 

#### xtrabackup用法

备份:innobackupex [option] BACKUP-ROOT-DIR

选项说明:https://www.percona.com/doc/percona-xtrabackup/LATEST/genindex.html

l

n --user:该选项表示备份账号

n --password:该选项表示备份的密码

n --host:该选项表示备份数据库的地址

n --databases:该选项接受的参数为数据库名,如果要指定多个数据库,彼此间需要以空格隔开;如:"xtra_test dba_test",同时,在指定某数据库时,也可以只指定其中的某张表。如:"mydatabase.mytable"。该选项对innodb引擎表无效,还是会备份所有innodb表

n --defaults-file:该选项指定从哪个文件读取MySQL配置,必须放在命令行第一个选项位置

n --incremental:该选项表示创建一个增量备份,需要指定--incremental-basedir

n --incremental-basedir:该选项指定为前一次全备份或增量备份的目录,与--incremental同时使用

n --incremental-dir:该选项表示还原时增量备份的目录

n --include=name:指定表名,格式:databasename.tablename

l Prepare:innobackupex --apply-log [option] BACKUP-DIR

n 选项说明:

n --apply-log:一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。此选项作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态

n --use-memory:和--apply-log选项一起使用,当prepare 备份时,做crash recovery分配的内存大小,单位字节,也可1MB,1M,1G,1GB等,推荐1G

n --export:表示开启可导出单独的表之后再导入其他Mysql中

n --redo-only:此选项在prepare base full backup,往其中合并增量备份时候使用,但不包括对最后一个增量备份的合并 只要不是最后一个完全备份就需加上此项

l **还原:innobackupex --copy-back [****选项] BACKUP-DIR**

n innobackupex --move-back [选项] [--defaults-group=GROUP-NAME] BACKUP-DIR

n 选项说明:

n --copy-back:做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir

n --move-back:这个选项与--copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同事保留数据文件和Backup副本

n **还原注意事项:**

n 1.datadir 目录必须为空。除非指定innobackupex --force-non-empty-directorires选项指定,否则--copy-backup选项不会覆盖

n 2.在restore之前,必须shutdown MySQL实例,不能将一个运行中的实例restore到datadir目录中

n 3.由于文件属性会被保留,大部分情况下需要在启动实例之前将文件的属主改为mysql,这些文件将属于创建备份的用户

n chown -R mysql:mysql /data/mysql

n 以上需要在用户调用innobackupex之前完成

n --force-non-empty-directories:指定该参数时候,使得innobackupex --copy-back或--move-back选项转移文件到非空目录,已存在的文件不会被覆盖。如果--copy-back和--move-back文件需要从备份目录拷贝一个在datadir已经存在的文件,会报错失败

l **备份生成的相关文件**

n 使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中,在备份时,innobackupex还会在备份目录中创建如下文件:

n (1)xtrabackup_info:innobackupex工具执行时的相关信息,包括版本,备份选项,备份时长,备份LSN(log sequence number日志序列号),BINLOG的位置

n (2)xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的

n (3)xtrabackup_binlog_info:MySQL服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置,可利用实现基于binlog的恢复

n (4)backup-my.cnf:备份命令用到的配置选项信息

n (5)xtrabackup_logfile:备份生成的日志文件

 

 

**Xtrabackup****备份过程**

 

 

 

**示例**:**新版Xtrabackup****完全备份及还原**

l 1 在原主机做完全备份到/data/backups

n xtrabackup --backup --target-dir=/backups/ 指定备份到哪 注意是完全备份

n scp -r /backups/* 目标主机:/backups

l 2 在目标主机上

n 预准备:确保数据一致,提交完成的事务,回滚未完成的事务 xtrabackup --prepare --target-dir=/backups/

n 复制到数据库目录 注意:数据库目录必须为空,MySQL服务不能启动 xtrabackup --copy-back –target-dir=/backups/

n 还原属性chown -R mysql:mysql /var/lib/mysql

n 启动服务 systemctl start mariadb

 

 

**示例:新版xtrabackup****完全,增量备份及还原**

l **1)** **备份过程**

a) 完全备份:xtrabackup --backup --target-dir=/backups/base

b) 第一次修改数据

c) 第一次增量备份 xtrabackup --backup --target-dir=/backups/inc1 --incremental-basedir=/backups/base

d) 第二次修改数据

e) 第二次增量备份 xtrabackup --backup --target-dir=/backups/inc2 --incremental-basedir=/backups/inc1

f) scp -r /backups/* 目标主机:/backups/

2) 备份过程生成三个备份目录 /backups/{base,inc1,inc2}

l **2****还原过程**

1) 预准备完成备份,此选项--apply-log-only 阻止回滚未完成的事务

a) xtrabackup --prepare --apply-log-only --target-dir=/backups/base

2) 合并第1次增量备份到完全备份,

a) xtrabackup --prepare **--apply-log-only** --target-dir=/backups/base **--incremental-dir=/backups/inc1**

3) 合并第2次增量备份到完全备份:最后一次还原不需要加选项--apply-log-only

a) xtrabackup --prepare --target-dir=/backups/base --incremental-dir=/backups/inc2

4) 复制到数据库目录,注意数据库目录必须为空,MySQL服务不能启动

a) xtrabackup **--copy-back** --target-dir=/data/backups/base

5) 还原属性:chown -R mysql:mysql /var/lib/mysql

6) 启动服务:systemctl start mariadb

 

 

 

**示例: xtrabackup****单表导出和导入**

1 单表备份 innobackupex --include='hellodb.students' /backups

2备份表结构 mysql -e 'show create table hellodb.students' > student.sql

3删除表mysql -e 'drop table hellodb.students‘

4 innobackupex --apply-log --export /backups/2018-02-23_15-03-23/

5 创建表

mysql>CREATE TABLE `students` ( `StuID` int(10) unsigned NOT NULL AUTO_INCREMENT, `Name` varchar(50) NOT NULL, `Age` tinyint(3) unsigned NOT NULL, `Gender` enum('F','M') NOT NULL, `ClassID` tinyint(3) unsigned DEFAULT NULL, `TeacherID` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`StuID`) ) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8

 

6 删除表空间 alter table students discard tablespace; 此命令是删除表数据

7 cp /backups/2018-02-23_15-03-23/hellodb/students.{cfg,exp,ibd} /var/lib/mysql/hellodb/

8 chown -R mysql.mysql /var/lib/mysql/hellodb/

9 mysql>alter table students import tablespace;

 

 

 

 

 

 

 

 

 

 

 

## MySQL复制

主从复制不能代替备份

l 扩展方式: Scale Up 向上扩展(升级设备), Scale Out横向扩展 生产中一般选择此方式

l MySQL的扩展

1) 读写分离

2) 复制: 每个节点都有相同的数据集

向外扩展

二进制日志

单向

l 复制的功用:

数据分布

负载均衡读

备份

高可用和故障切换

MySQL升级测试

 

 

 

**主从复制线程:**

1 主节点:

1.1 dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events

2 从节点:

2.1 I/O Thread:向Master请求二进制日志事件,并保存于中继日志中

2.2 SQL Thread:从中继日志中读取日志事件,在本地完成重放

3 跟复制功能相关的文件:

3.1 master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等

3.2 relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地replay log日志的对应关系

4 主从复制特点:

4.1 异步复制

4.2 主从数据不一致比较常见

5 复制架构:

5.1 Master/Slave, Master/Master, 环状复制

5.2 一主多从

5.3 从服务器还可以再有从服务器

5.4 一从多主:适用于多个不同数据库

6 复制需要考虑二进制日志事件记录格式

6.1 STATEMENT(5.0之前)

6.2 ROW(5.1之后,推荐)

6.3 MIXED

 

 

 

 

**主从复制原理:**

\1. 首先主服务器收到用户的写操作

\2. 把数据库的更新写入二进制日志 在主服务器有一个专门的线程 dump 线程 利用dump线程通过网络发送到从服务器

\3. 从服务器用 io thread接收

\4. 然后写入到Relay Log(就是二进制日志) 此处是临时存储

\5. 利用SQL Thread更新

\6.

 

 

 

**主服务器配置:** **主节点配置**

(1) 启用二进制日志

[mysqld]

log_bin

(2) 为当前节点设置一个全局惟一的ID号

[mysqld]

server_id=#

log-basename=master 可选项,设置datadir中日志名称,确保不依赖主机名

(3) 创建有复制权限的用户账号

GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'HOST' IDENTIFIED BY 'replpass';

 

**从节点配置:从服务器配置**

(1) 启动中继日志

[mysqld]

read-only 设为普通用户只读 可以不加但建议加上

server_id=# 为当前节点设置一个全局惟的ID号

relay_log=relay-log relay log的文件路径,默认值hostname-relay-bin

relay_log_index=relay-log.index 默认值hostname-relay-bin.index

(2) 使用有复制权限的用户账号连接至主服务器,并启动复制线程

mysql> CHANGE MASTER TO MASTER_HOST='host', MASTER_USER='repluser', MASTER_PASSWORD='replpass', MASTER_LOG_FILE='mysql-bin.xxxxx', MASTER_LOG_POS=#;

mysql> START SLAVE [IO_THREAD|SQL_THREAD];

 

 

 

**如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave****节点**

Ø 通过备份恢复数据至从服务器

Ø 复制起始位置为备份时,二进制日志文件及其POS

**如果要启用级联复制,****需要在从服务器启用以下配置**

Ø [mysqld]

Ø log_bin

Ø log_slave_updates

**复制架构中应该注意的问题:**

1、限制从服务器为只读

Ø 在从服务器上设置read_only=ON

注意:此限制对拥有SUPER权限的用户均无效

Ø 阻止所有用户, 包括主服务器复制的更新 mysql> FLUSH TABLES WITH READ LOCK;

2、RESET SLAVE

在从服务器清除master.info ,relay-log.info, relay log ,开始新的relay log ,注意:需要先STOP SLAVE

RESET SLAVE ALL 清除所有从服务器上设置的主服务器同步信息如:PORT, HOST, USER和 PASSWORD 等

3、sql_slave_skip_counter = N 从服务器忽略几个主服务器的复制事件,global变量 (忽略错误)

set global sql_slave_skip_counter=1 忽略主从复制过程中的错误 数量为1

​ 注意需先将服务停止

4、如何保证主从复制的事务安全

参看https://mariadb.com/kb/en/library/server-system-variables/

Ø 在master节点启用参数:

sync_binlog=1 每次写后立即同步二进制日志到磁盘,性能差 可以考虑变为0

如果用到的为InnoDB存储引擎:

innodb_flush_log_at_trx_commit=1 每次事务提交立即同步日志写磁盘

innodb_support_xa=ON 默认值,分布式事务MariaDB10.3.0废除

sync_master_info=# #次事件后master.info同步到磁盘

master_info是存储复制信息的

Ø 在slave节点启用服务器选项: skip_slave_start=ON 不自动启动slave

此项默认为ON

Ø 在slave节点启用参数:

sync_relay_log=# #次写后同步relay log到磁盘

sync_relay_log_info=# #次事务后同步relay-log.info到磁盘

 

 

 

## 主主复制

l 主主复制:互为主从

1) 容易产生的问题:数据不一致;因此慎用

2) 考虑要点:自动增长id

a) 配置一个节点使用奇数id

b) auto_increment_offset=1 开始点

c) auto_increment_increment=2 增长幅度

d) 另一个节点使用偶数id

e) auto_increment_offset=2

f) auto_increment_increment=2

 

主主复制的配置步骤:

(1) 各节点使用一个惟一server_id

(2) 都启动binary log和relay log

(3) 创建拥有复制权限的用户账号

(4) 定义自动增长id字段的数值范围各为奇偶

(5) 均把对方指定为主节点,并启动复制线程

 

 

 

 

 

 

 

 

 

 

 

 

### 半同步复制

半同步不确保所有从服务器都同步 只有一个服务器同步成功则会成功

会有一个超时时长,当超过这时长也会返回成功值

主从复制配合半同步复制

需安装插件,在所有的节点内都需安装此插件 主服务器安装:‘semisync_master’ 从服务器安装’semisync_slave’

主服务器:创建账号

 

从服务器:开始复制

 

#### 实现半同步:主服务器上配置

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; 安装插件

mysql>SET GLOBAL rpl_semi_sync_master_enabled=1; 启用插件 0表示不启用 如想要一直启用需写入到配置文件内

mysql>SET GLOBAL rpl_semi_sync_master_timeout = 1000;设置超时长为1s 设置超时时长 毫秒为单位 默认是10秒最好写入到配置文件内

mysql>SHOW GLOBAL VARIABLES LIKE '%semi%'; 查看配置

mysql>SHOW GLOBAL STATUS LIKE '%semi% ‘; 查看目前的状态

 

**从服务器配置** **重此操作在所有的从节点上**

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; 安装插件

mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1; 启用插件 永久保存需写入配置文件内

mysql> select @@rpl_semi_sync_slave_enabled; 查看插件是否启用

从节点配置查看 show slave status

 

 

 

 

 

 

### mysql复制过滤器

**从服务器上的复制过滤器相关变量**

replicate_do_db= 指定复制库的白名单

replicate_ignore_db= 指定复制库黑名单

replicate_do_table= 指定复制表的白名单

replicate_ignore_table= 指定复制表的黑名单

replicate_wild_do_table= foo%.bar% 支持通配符

replicate_wild_ignore_table=

 

 

 

 

### 基于SSL复制:

l 在默认的主从复制过程或远程连接到MySQL/MariaDB所有的链接通信中的数据都是明文的,外网里访问数据或则复制,存在安全隐患。通过SSL/TLS加密的方式进行复制的方法,来进一步提高数据的安全性

l 配置实现:

1) 参看:https://mariadb.com/kb/en/library/replication-with-secure-connections/

l 主服务器开启SSL:[mysqld] 加一行ssl

l 主服务器配置证书和私钥;并且创建一个要求必须使用SSL连接的复制账号

l 从服务器使用CHANGER MASTER TO 命令时指明ssl相关选项

 

**Master****服务器配置**

[mysqld] log-bin server_id=1 ssl ssl-ca=/etc/my.cnf.d/ssl/cacert.pem ssl-cert=/etc/my.cnf.d/ssl/master.crt ssl-key=/etc/my.cnf.d/ssl/master.key

 

 

**Slave****服务器配置**

mysql> CHANGE MASTER TO MASTER_HOST='MASTERIP', MASTER_USER='rep', MASTER_PASSWORD='centos', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=245, MASTER_SSL=1, **MASTER_SSL_CA = '/etc/my.cnf.d/ssl/cacert.pem',** **MASTER_SSL_CERT = '/etc/my.cnf.d/ssl/slave.crt',** **MASTER_SSL_KEY = '/etc/my.cnf.d/ssl/slave.key';** **注意:加粗字体可以写到my.cnf里面**

 

 

## 复制的监控和维护

一、 清理日志

1) PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr } 清理二进制日志到哪个位置之前

2) RESET MASTER

3) RESET SLAVE

二、 复制监控

1) SHOW MASTER STATUS

2) SHOW BINLOG EVENTS

3) SHOW BINARY LOGS

4) SHOW SLAVE STATUS

5) SHOW PROCESSLIST

三、从服务器是否落后于主服务

1) Seconds_Behind_Master: 0

四、如何确定主从节点数据是否一致

2) percona-tools

五、 数据不一致如何修复

3) 删除从数据库,重新复制

 

 

 

 

### MySQL读写分离

读写分离应用:

mysql-proxy:Oracle,https://downloads.mysql.com/archives/proxy/ Atlas:Qihoo,https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md dbproxy:美团,https://github.com/Meituan-Dianping/DBProxy Cetus:网易乐得,https://github.com/Lede-Inc/cetus Amoeba:https://sourceforge.net/projects/amoeba/ Cobar:阿里巴巴,Amoeba的升级版 Mycat:基于Cobar, http://www.mycat.io/ ProxySQL:https://proxysql.com/

**ProxySQL**

注意用这个的话从服务器必须要加read-only

准备:实现读写分离前,先实现主从复制

注意:slave节点需设置read-only

启动proxysql:service proxysql start

启动后会监听两个默认端口

6032:proxysql的管理端口

6033:proxysql对外提供服务的端口

使用mysql客户端连接到proxysql的管理接口6032,默认管理员和密码都是admin

mysql –uadmin –padmin –P6032 –h127.0.0.1

说明:在main和monitor数据库中的表,runtime_开头的是运行时的配置,不能修改,只能修改非runtime_表,修改后必须执行load…to runtime才能加载到runtime生效,执行save…to disk降配置持久化保存到磁盘

 

proxysql实现读写分离

 

# ansible自动化运维

术语:本地部署:on-premises 基础设施即服务:laas 平台即服务paas 软件即服务:saas

灰度发布又称为金丝雀发布:先上线一部分

蓝绿发布:主 备 两套环境

- 主:活动,绿色 v1.0 --> 备
- 备:非活动,蓝色 v2.0 --> 主

Ansible 适用于中小应用环境

 

**注意默认以key验证方式连接**

脚本在这里被称为剧本(playbook) 好多个剧本放在一起叫角色

 

## ansible特性

1. 模块化:调用特定的模块,完成特定任务1800多个模块 可以将每个模块理解为命令

2. 有Paramiko,PyYAML(剧本),Jinja2(模板语言)三个关键模块

3. 支持自定义模块

4. 基于Python语言实现

5. 部署简单,基于python和SSH(默认已安装),基于agentless(无代理 不必安装代理软件)

6. 安全,基于OpenSSH

7. 支持playbook编排任务

8. 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况

9. 无需代理不依赖PKI(无需ssl)

10. 可使用任何编程语言写模块

11. YAML格式,编排任务,支持丰富的数据结构

12. 较强大的多层解决方案

 

剧本的集合是角色Ansible Roles

实现的是集中管理而不是对外服务

实现集中管理: 1对多 不是基于c/s结构的

安装ansibler的称为控制端 被管理的称为被控制端[基于无代理方式实现被控制:agentless.需基于key验证]

 

## ansible安装

1. 安装yum install ansible 基于epel源的

### 编译安装:

1. yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto

2. tar xf ansible-1.5.4.tar.gz

3. cd ansible-1.5.4

4. python setup.py build

5. python setup.py install

6. mkdir /etc/ansible

7. cp -r examples/* /etc/ansible

查看版本: ansible --version

 

## ansible相关文件

### 配置文件

- /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性 一般保持默认.此文件内是默认值,但剧本执行的东西可能会覆盖此时的设置. 日志建议启用和host_key_checking取消注释后则登陆每个主机不需要输入yes 取消ssh key的检查
- ![1545705812530](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545705812530.png)
- ![1545705819975](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545705819975.png)
- /etc/ansible/hosts 主机清单 是文本文件 在这存储了要管理的主机的IP地址 可分组,可在主机后加端口号,可写成[a:f]表示a到f
- /etc/ansible/roles/ 存放角色的目录

### 程序

- /usr/bin/ansible 主程序,临时命令执行工具 可执行命令

- /usr/bin/ansible-doc 查看配置文档,帮助文档 可以理解为man帮助

- /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台

- /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具/usr/bin/ansible-pull 远程执行命令的工具

- /usr/bin/ansible-vault 文件加密工具

- /usr/bin/ansible-console 基于Console界面与用户交互的执行工具

 

## ansible系列命令

ansible; ansible-doc; ansible-playbook; ansible-vault; ansible-console; ansible-galaxy; ansible-pull

 

- **ansible-doc:显示模块帮助**
- `ansible-doc [options][module]`
- -a 显示所有模块的文档
- -l,--list 列出可用模块 前面显示的是模块名 后面显示的是此模块是做什么的
- -s,--snippet 显式指定模块的playbook片段

- 示例:
- ansible-doc –l 列出所有模块
- ansible-doc ping模块 查看指定ping模块帮助用法
- ansible-doc –s ping 查看指定模块帮助用法 以片段方式查看

 

- **ansible-galaxy管理角色的**
- **Ansible-pull 推送命令至远程,效率无限提升**
- **Ansible-playbook(剧本) 执行playbook的**
- 示例:ansible-playbook hello.yml
- **Ansible-vault 管理加密yml文件**
- 直接创建加密yml文件Ansible-vault create hello2.yml
- 加密:ansible-vault encrypt hello.yml
- 不解密查看加密文件内容ansible-vault view hello.yml
- 不解密编辑加密文件
- 更改口令ansible-vault rekey hello.yml
- 解密ansible-vault decrypt hello.yml
- **Ansible-console交互式执行ansible命令**
- 更改命令并发数为10个 forks 10
- List列出当前管理的主机
- 远程创建文件:file

 

### ansible语法

`ansible <host-pattern> [-m module_name][-a args]`

- <host-pattern>主机清单里面的分组名或是主机 -m是模块 -a是模块带的参数

- --version 显示版本
- -m module 指定模块,默认为command
- -v 详细过程 –vv -vvv更详细 执行过程
- --list-hosts 显示主机列表,可简写 --list
- -k, --ask-pass 提示输入ssh连接密码,默认Key验证
- -K, --ask-become-pass 提示输入sudo时的口令;在sudo配置文件里添加NOPASSWD 则不需要每次输入口令
- ![1545706673592](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545706673592.png)
- -C, --check 检查,并不执行
- -T, --timeout=TIMEOUT 执行命令的超时时间,默认10s
- -u, --user=REMOTE_USER 执行远程执行的用户
- -b, --become 代替旧版的sudo 切换
- --become-user=USERNAME 指定sudo的runas用户,默认为root

- **ansible的Host-pattern**

- ALL:表示所有inventory中的左右主机
- ansible -all -m ping

* :通配符
* ansible “*”-m ping

* ansible 192.168.1.* -m ping

* ansible “*srvs”-m ping

- 或关系
- ansible “websrvs:&dbsrvs” –m ping
- n ansible “192.168.1.10:192.168.1.20” -m ping

- 逻辑与
- ansible “websrvs:&dbsrvs” –m ping
- 在websrvs组并且在dbsrvs组中的主机

- 逻辑非
- ansible ‘websrvs:!dbsrvs’ –m ping
- 在websrvs组,但不在dbsrvs组中的主机
- 注意:此处为单引号
- 综合逻辑
- ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' -m ping
- 正则表达式
- ansible “websrvs:&dbsrvs” –m ping
- ansible “~(web|db).*\.magedu\.com” –m ping

## ansible常用模块

使用哪个模块需标明 ansible 管理主机 -m shell/copy/file/yum

- command模块:在远程值机执行命令,默认模块,可忽略-m选项
- ![1545707178954](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707178954.png)
- ![1545707188373](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707188373.png)
- 此模块不支持$VARNAME < > | ; & 等,可用shell模块实现
- shell: 与command命令大致相同 支持 < > | ; & 等符号 可以将此模块设为默认模块
- ![1545707231960](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707231960.png)
- 将shell模块设为默认模块 vim /etc/ansible/ansible.cfg 将注释去掉 并将command替换为shell 设置默认模块
- ![1545707252192](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707252192.png)
- script:将ansible控制端的脚本在远程主机上执行
- ![1545707272564](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707272564.png)
- 注意:shell模块与script模块有两个相同的参数 removes和 creates creates 如果已经存在则此步骤不执行 removes是如果此文件存在则执行 如果此文件不存在则不执行
- ![1545707319469](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707319469.png)
- copy模块,复制模块 将控制端文件拷贝至被控制端 要指定文件的源文件 还要指定目标路径
- 重要的参数 backup是如果目标主机已经存在要拷贝的文件此参数会将目标主机的文件做备份
- content后面加文本内容 可以将文本的内容拷贝至远程
- dest指定目标路径
- owner是所有者
- mode是权限
- backup是如果目标存在则备份
- ![1545707391604](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707391604.png)
- Fetch模块,从客户端抓取文件至控制端.抓取模块 现在只能抓取文件不能抓目录 目录可先压缩 `ansible srv -m fetch -a ‘src=/root/a.sh dest=/data/scripts’`
- Hostname管理主机名 ansible常用模块
- Cron模块 计划任务
- Yum模块 安装包,管理包
- Setup模块查看系统信息

### Playbook核心元素

- Hosts 是执行的目标主机
- 示例:- hosts: websrvs(应用在哪个主机上)
- remote_user: root以什么身份执行
- 示例: - hosts websrvs
- remote_user: root
- task列表里面要执行命令的列表
- 两种格式:1)action: module arguments 2)module

#### Playbook中变量使用
变量名:仅能由字母,数字和下划线组成,且只能以字母开头

 

 

模板template
只能用于ansible-playbook中
Template文件必须存放在templates目录下,且命名为.j2结尾
迭代:with_items
迭代:当有需要重复性执行的任务时,可以使用迭代机制

 

### role角色

用playbook实现 playbook必须放在和角色(roles)同级的目录下

实现简单的角色

![1545707661773](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545707661773.png)

 

 

 

 

 

# KVM

### 基础知识:

1. xml文件可以理解为配置文件
2. img文件可以理解为磁盘映像文件即ISO

 

 

* kvm是一种虚拟化技术;主机级虚拟化技术

1. 目前仅支持X86_64位的

2. HVM 仅支持借助于硬件辅助虚拟化做完全虚拟化;硬件必须支持虚拟化如CPU

3. 在内核中实现的

* kvm仅仅是内核中的一个内核模块

1. 底层依赖于adm或intel的虚拟化技术

2. 来构建内核的虚拟化软件'/dev/kvm';(任何一个如果软件只在内核中有,想要在用户空间使用必须要有用户空间工具进行交互)

3. 通过系统调用ioctl接口向用户控件输出

4. 在用户空间要想创建或启动一个虚拟机必须要有一个对应的软件qemu-kvm

- 用户空间的管理KVM工具

1. qemu-kvm命令行工具;不能做快照需用qemu-img
2. qemu-img管理磁盘镜像文件;管理磁盘映像文件;命令行工具
3. **libvirt** 配合**virt-manager**图形化管理工具
1. libvirt和libvirtd
2. virt-manager虚拟机管理软件
3. virt-viewer如果只需运行则使用这个
4. virtinst安装虚拟机;命令行工具
5. virsh 命令行管理虚拟机

## 安装KVM

判断当前CPU是否支持支持kvm

```shell
grep -I -E '(vxm|svm|lm)' /proc/cpuinfo
vxm和svm二者有其一
lm必须有 才可以安装kvm
```

启用KVM;启用KVM;KVM无需下载只要启用即可

```shell
modprobe kvm
```

判断启用失败成功

```shell
lsmod | grep kvm
```

使用virt-manager管理KVM;一定要注意yum源的地址与自己系统版本绝对匹配

```shell
yum install qeum-kvm libvirt-daemon-kvm libvirt virt-manager
modprobe kvm
systemctl start libvirtd.service 启动libvirtd守护进程 注意libvirtd的d
启动:virt-manager
注意要有桌面系统
```

 

libvirt网卡是默认NAT模式的;更改为桥接; NAT模式网卡更改为桥接;libvirt网卡更改为桥接模式

桥接网络就是将物理网卡当交换机使用;将软交换机当做物理网卡使用

```shell
cd /etc/sysconfig/network-scripts/
cp ifcfg-ens32 ifcfg-br0 拷贝一份网卡配置文件
设置拷贝过来的将br0当作网卡用;而ens32当作交换机来用
```

编辑原来的网卡的配置文件

`vim ifcfg-ens32`

添加一行BRIDGE=br0

![1545711954193](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545711954193.png)

- 示例:

```
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
NAME=ens33
DEVICE=ens33
ONBOOT=yes
BRIDGE=br0
```


编辑ifcfg-br0

![1545711973254](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545711973254.png)

示例:

```

```

 

 

远程链接是**加上** **-X**选项;打开图形转发

在桌面系统上: ssh -X root@IP地址

在xshell上:virt-manager

 

 

如果键盘不好用则在虚拟机上的虚拟机中的设置立案更改Display 中的type类型为vnc

 

 

## KVM管理工具

1. virt-manager
1. 使用virt-manager工具创建虚拟机;然后再用其他命令行工具进行管理
2. virsh
1. virsh不仅仅能够创建虚拟机而且还能全方位的管理虚拟机
3. qeum-kvm

 

 

- virsh家族或libvirt家族创建的虚拟机都会生成一个.xml的配置文件;存放在`/etc/libvirt/qemu`目录下

 

 

![1545713226207](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545713226207.png)

 

每个使用virsh创建的虚拟机都表现为宿主机上的一个进程

 

 

### 使用virsh管理创建虚拟机

- 手动创建虚拟机;使用命令来管理
- virsh能够对虚拟机进行全生命周期管理的;但不推荐用于创建虚拟机;建议使用virt-manager创建完成虚拟机之后将虚拟机配置文件当作模板使用
- virsh的各种功能都通过子命令来实现
- 查看帮助:virsh help
- 查看特定的组的帮助:virsh help 组名;例如:virsh help domain(只显示和域相关的命令)
- virsh可以进入交互式接口:输入`virsh`

#### virsh dumpxml

显示虚拟机详情;创建虚拟机

- 使用帮助:`virsh help dumpxml`
- 使用格式:virsh dumpxml 虚拟机名称

` virsh dump 虚拟机1` 查看虚拟机1的xml配置文件 可以将此配置文件保存下来稍作修改即可创建虚拟机;但需注意要有.img文件

示例:

使用virt-manager创建出的虚拟机当作模板 virsh dumpxml 虚拟机名称 > 将要创建的虚拟机名称

**需注意路径在/etc/libvirt/qemu/下;此时是相对路径**

```shell
[root@centos7 qemu]# virsh dumpxml centos7.0 > centos7.1.xml
# 注意模板不加.xml 此时是将centos7当作模板文件
[root@centos7 qemu]# vim centos7.1.xml
# 编辑刚刚拷贝过来的.xml格式的配置文件
```

编辑拷贝过来的配置文件

```
<name>centos7.1</name>
# 将名字更改掉
<uuid>
#uuid删掉;会自动生成
<memory unit='KiB'>2048000</memory>
# 内存大小;如果有必要则更改
<vcpu placement='static'>1</vcpu>
#使用几颗虚拟CPU;注意不能超过宿主机的线程
<disk type='file' device='disk'>
# 磁盘映像文件 disk是磁盘
<driver name='qemu' type='qcow2'/>
名称是qemu 类型是qcow2
<source file='/VMs/vm2/vm2.img>
磁盘映像文件路径以及名称
```

 

#### virsh list

- 使用帮助:virsh list --help
- 使用格式:`virsh list --选项`
- list选项:

```
--inactive 列出不活跃的域
--all 不活跃和活跃的域列表
--transient 列出临时域
--persistent 列出持久域
--with-snapshot 列出现有快照的域
--without-snapshot 列出没有快照的域
--state-running 运行状态的域列表
--state-paused 列出暂停状态的域
--state-shutoff 列出关闭状态的域
--state-other 列出其他状态的域
--autostart 列出启用 autostart 的域
--no-autostart 列出禁用 autostart 的域
--with-managed-save 列出有管理的保存状态的域
--without-managed-save 列出没有管理的保存状态的域
--uuid 只列出 uuid
--name 只列出域名
--table 列出表格(默认)
--managed-save 标记有管理的保存状态的域
--title show domain title
```

 

### 使用qemu-kvm管理vms:

1. Qemu:
​ 处理器模拟器
​ 仿真各种IO设备
​ 将仿真设备连接至主机的物理设备
​ 提供用户接口

2. ​ qemu-kvm命令语法:

1. `qemu-kvm [options][disk_image]`
2. 选项有很多类别:
1. 标准选项、块设备相关选项、显示选项、网络选项、...
2. 标准选项:
1. -machine [type=]name:-machine help来获取列表,用于指定模拟的主机类型;
2. -cpu cpu:-cpu help来获取列表;用于指定要模拟的CPU型号;
1. 可以写`-cpu host` 读取物理机的cpu
3. `-smp n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]`:指明虚拟机上vcpu的数量及拓扑;
1. n是总的cpu核心数;maxcpus最大cpu核心数;cores表示每个cpu有几核;threads表示每核有几线程;sockets表示有几颗CPU;
4. `-boot [order=drives][,once=drives][,menu=on|off][,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time][,strict=on|off]`
​ order:各设备的引导次序:c表示第一块硬盘,d表示第一个光驱设备;-boot order=dc,once=d
1. once是单次;
5. -m megs:以M虚拟机的内存大小;
6. -name NAME:当前虚拟机的名称,要唯一;
3. 块设备相关的选项:
1. -cdrom file:指定要使用光盘映像文件;
2. `-drive [file=file][,if=type][,media=d][,index=i] [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]`:

```shell
file=/PATH/TO/SOME_IMAGE_FILE:映像文件路径;
if=TYPE:块设备总线类型,ide, scsi, sd, floppy, virtio,...
media=TYPE:介质类型;设备类型,cdrom和disk;
index=i:设定同一类型设备多个设备的编号;自定义索引序号/索引顺序
cache=writethrough(通写)|writeback(回写)|none(不启用)|directsync(直接同步)|unsafe(非安全机制)[,format=f]:缓存方式;缓存会提升性能但也会带来数据丢失的可能性 [format=f]磁盘映像文件的格式;例如:qcow2
CentOS磁盘镜像文件下载:https://cloud.centos.org/centos/7/images/
```

1. 显示选项:

1. -display type:显示的类型,sdl, curses, none, spice和vnc;

1. spice是本地显示;大多数使用vnc

2. -nographic:不使用图形接口;表示没有显卡;但注意没有显卡也能显示字符

3. -vga [std|cirrus|vmware|qxl|xenfb|none]:模拟出的显卡的型号;

4. -vnc display[,option[,option[,...]]]]:启动一个vnc server来显示虚拟机接口; 让qemu进程监听一个vnc接口;

1. vnc:桌面号:5900+N

2. display:

1. HOST:N

在HOST主机的第N个桌面号输出vnc;
5900+N

2. unix:/PATH/TO/SOCK_FILE

3. none

3. options:
​ ​ password:连接此服务所需要的密码;

​ 还可以使用系统认证

 

​ 5. -monitor stdio:在标准输出上显示monitor界面;qemu自己内置的监控界面

​ Ctrl-a, c:在console和monitor之间切换;
​ Ctrl-a, h

1. 网络选项:
1. -nat选项在创建虚拟机时可能会指定多次:正常情况下当我们虚拟一个网卡设备时要虚拟两个;一个在宿主机上,一个在虚拟机上 -nat nic是为虚拟创建;-nat tap是在宿主机上创建
2. `-net nic[,vlan=n][,macaddr=mac] [,model=type][,name=str] [,addr=str][,vectors=v]`

```shell
为虚拟机创建一个网络接口,并将其添加至指定的VLAN;
model=type:指明模拟出的网卡的型号,ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio;建议使用半虚拟化virtio
-net nic,model=?
macaddr=mac:指明mac地址;52:54:00:00:00 一定要更改mac地址
```

1. `-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile]:`
​ 通过物理的TAP网络接口连接至vlan n;
​ script=file:启动虚拟机时要执行的脚本,默认为/etc/qemu-ifup 脚本用于实现将这个接口添加到桥上
​ downscript=dfile:关闭虚拟机时要执行的脚本,/etc/qemu-ifdown
​ ifname=NAME:自定义接口名称;如果不指定则自动生成随机名称

​ 其他选项:`-daeminize `以守护进程运行

2. 脚本实例:

```shell
#/etc/qemu-ifup
#!/bin/bash
#

bridge=br0
if [ -n "$1" ];then
ip link set $1 up
sleep 1
brctl addif $bridge $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error: no interface specified."
exit 2
fi
```

​ 示例:

自己创建一个桥`brctl addbr mybr0`

启动 `brctl stp mybr0 on`

```shell
[root@node01 VMs]# qemu-kvm -cpu host -smp 4,sockets=2,cores=2,threads=1 -m 64 -name c1 -boot order=dc -drive file=/VMs/vm4/vm4.img,media=disk,if=virtion,cache=writeback,format=qcow2 -vnc :0 -net nic,macaddr=52:54:00:00:00:01,model=vittio -net tap,script=//etc/qeum-ifup
```

按回车之前要先写完启动脚本的;
连接:

 

1. 启动连接:

yum install tigervnc

ssh -X root@IP地址

vncviewer :0

 

 

 

 

 

## 控制KVM虚拟机

对KVM来讲每个虚拟机的CPU(VCPU)都表现为一个线程而已;不推荐单个虚拟机的CPU数量超过物理机的总线程;但多个虚拟机之和可以超过(超配)

 

 

 

1. 重启:
a) virsh help reboot热重启
b) virsh help reset 冷重启;如同使用电源按钮
2. virsh help undefined取消定义一个域
3. virsh help monitor
a) ![1545712277512](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545712277512.png)
4. 管理虚拟机磁盘

1. qemu-img command [command iptions]
2. check 创建磁盘映像文件 建议使用qcow2的类型;还可以检查
5. -f 指定磁盘镜像文件 -o ? 获取帮助
6. qemu-img create -f qcow2 -o ? /VMs/vm2/mydisk.img
7. 使用稀疏格式: `qemu-img create -f qcow2 -o preallocation=metadata,size=10G /VMs/vm2/mydisk.img`
8. 磁盘文件格式转换

1. convert
9. 快照

1. snapshot
10. 改变磁盘映像文件大小resize
11. 将磁盘热插入到KVM虚拟机上
1. virsh help arrach-disk
2. 举例:virsh attach-dish KVM虚拟机名称 /VMs/vm2/mydish.img vda
3. 连接至KVM虚拟机查看:fdisk -l
12. 拆除KVM虚拟机上的硬盘;注意一定是未被使用的硬盘
1. virsh help datach-disk
2. 示例:virsh detach-disk c2 vda
13. 网卡热插拔:
1. 注意一个虚拟网卡是两部分组成;
2. 显示有几个网络virsh net-list
3. 显示有几个网络接口virsh iface -list

![1545712523339](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545712523339.png)

 

 

 

## 预处理磁盘镜像模板:libguestfs-tools

virt-sysprep:

​ --install

​ --enable

​ --list-operations

​ --operations

在一个纯净系统上实现

```shell
yum install qemu-kvm libvirt-daemon-kvm libvirt virt-manager libguestfs-tools -y
modprobe kvm
systemctl start libvirtd
```

​ 最后一步可能报错是本地仓库和远程仓库不匹配导致的解决办法:

```shell
cd /etc/yum.repos.d/
vim CentOS-Base.repo
basrurl=找到与自己相匹配的yum源例如阿里云
```

 

图形管理工具

```shell
kimchi:基于H5研发web GUI; virt-king;推荐
OpenStack: IaaS
oVirt:配置很麻烦
proxmox:小型企业不错的选择
图形管理工具栈https://www.linux-kvm.org/page/Management_Tools
```


### OpenStack

非常吃资源

 

## kimchi

基于wok这个插件运行的需先安装wok

下载好komchi和wok之后

必须启动并且设置好epel仓库

yum install 刚刚下载的两个包;解决依赖关系

启动wok;会监听8001端口

```shell
systemctl daemon-reload
systemctl start wokd
```

连接wok;在浏览器输入ip地址:8001

 

 

 

# Redis

安装高版本的要安装源码包

 

## buffer与cache

buffer:缓冲也叫写缓冲,一般用于写操作,可以将数据先写入内存在写入磁盘,buffer 一般用于写缓冲,用于解决不同介质的速度不一致的缓冲,先将数据临时写入到里自己最近的地方,以提高写入速度,CPU会把数据线写到内存的磁盘缓冲区,然后就认为数据已经写入完成看,然后内核的线程在后面的时间在写入磁盘,所以服务器突然断电会丢失内存中的部分数据。

cache:缓存也叫读缓存,一般用于读操作,CPU读文件从内存读,如果内存没有就先从硬盘读到内存再读到CPU,将需要频繁读取的数据放在里自己最近的缓存区域,下次读取的时候即可快速读取。

**cache才是真正的缓存**

##### cache的保存位置

1. 客户端:浏览器
2. 内存:本地服务器、远程服务器(集群)
3. 硬盘:本机硬盘、远程服务器硬盘
4. 速度对比:客户端浏览器-内存-远程内存-硬盘-远程硬盘。

cache的特性

1. 过期时间
2. 强制过期,源网站更新图片后CDN是不会更新的,需要强制是图片缓存过期
3. 命中率,即缓存的读取命中率

 

 

## CDN

##### 什么是CDN?

- 内容分发网络(Content Delivery Network),通过将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服务可用性,
- CDN 第一降低机房的使用带宽,因为很多资源通过CDN就直接返回用户了,
- 第二解决不同运营商之间的互联,因为可以让联通的网络访问联通让电信的网络访问电信,起到加速用户访问的目的;
- 第三:解决用户访问的地域问题,就近返回

 

##### CDN优势

提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不通而进行不通级别的缓存,例如访问量最高的资源访问CDN 边缘节点的内存,其次的放在SSD或者SATA,再其次的放在云存储,这样兼顾了速度与成本。缓存-缓存到最快的地方如内存,缓存的数据准确命中率高,访问速度就快

调度准确-将用户调度到最近的边缘节点

性能优化-CDN 专门用于缓存响应速度快

安全相关-抵御攻击

节省带宽:由于用户请求由边缘节点响应,因此大幅降低到源站带宽。

 

## Redis部署与使用

#### Redis基础

Redis和Memcached是非关系型数据库也成为NoSQL,

MySQL、Mariadb、SQL Server、PostgreSQL、Oracle 数据库属于关系型数据(RDBMS,
Relational Database Management System)

 

#### Redis对比memcached

- 支持数据的持久化:可以将内存中的数据保持在磁盘中,重启redis服务或者服务器之后可以从备份文件中恢复数据到内存继续使用。
- 支持更多的数据类型:支持string(字符串)、hash(哈希数据)、list(列表)、set(集合)、zet(有序集合)
- 支持数据的备份:可以实现类似于数据的master-slave模式的数据备份,另外也支持使用快照+AOF。
- 支持更大的value数据:memcache单个key value最大只支持1MB,而redis最大支持512MB。
- Redis 是单线程,而memcache是多线程,所以单机情况下没有memcache并发高,但redis 支持分布式集群以实现更高的并发,单Redis实例可以实现数万并发。
- 支持集群横向扩展:基于redis cluster的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性。
- 都是基于C语言开发。

 

#### redis典型应用场景

Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享

消息队列:ELK的日志缓存、部分业务的订阅发布系统

计数器:访问排行榜、商品浏览数等和次数相关的场景

缓存:数据查询、电商网站商品信息、新闻内容

微博/微信社交场合:共同好友、点赞评论等

 

## 编译安装redis

需安装gcc 和 gcc-devel

```shell
tar xf redis-5.0.3.tar.gz
cd redis-5.0.3
make PREFIX=/usr/local/redis install 指定安装到什么位置;
ll /usr/local/redis/
# total 0
# drwxr-xr-x 2 root root 134 Dec 13 09:21 bin

mkdir /usr/local/redis/etc
cp redis.conf /usr/local/redis/etc/
```

 

### 前台启动redis

```shell
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
二进制启动服务 配置文件地址
```

 

### 解决redis启动时的报错

1. **tcp-backlog**

The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.

backlog参数控制的是三次握手的时候server端收到client ack确认号之后的队列值。

net.core.somaxconn = 512

 

2. **vm.overcommit_memory**

0、表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

1、表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

2、表示内核允许分配超过所有物理内存和交换空间总和的内存

vm.overcommit_memory = 1

 

3. **transparent hugepage**

开启大页内存动态分配,需要关闭让redis 负责内存管理。

echo never > /sys/kernel/mm/transparent_hugepage/enabled

 

 

 

 

 

### 编辑redis服务启动脚本

```shell
# cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf --supervised systemd
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis 可以注释掉;更改连接redis的用户
Group=redis 如果不更改则需创建此用户
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

创建用户redis用户:useradd redis -s /sbin/noligin
```

 

 

 

## 连接Redis

主要分为运维人员的连接和程序的连接

#### 本机非密码连接

```shell
redis-cli
```

#### 跨主机非密码连接

```shell
redis-cli -h HOSTNAME/IP -p PORT
```

#### 跨主机密码连接

```shell
redis-cli -h HOSTNAME/IP -p PORT -a PASSWORD
```

#### python连接方式

```python
#!/bin/env python
#Author:
import redis
import time
pool = redis.ConnectionPool(host="192.168.7.101",port=6379,password="")
r = redis,Redis(connection_pool=pool)
for i in range(100)
r.set("k%d" % i,"v%d % i")
time.sleep(1)
data=r.get("k%d" % i)
print(data)
```

## redis配置文件

```shell
bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听IP

protected-mode yes #redis3.2 之后加入的新特性,在没有设置bind IP和密码的时候只允许访问127.0.0.1:6379

port 6379 #监听端口

tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值。

timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时。

tcp-keepalive 300 #tcp 会话保持时间;秒为单位

daemonize no #认情况下 redis 不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成 yes,当redis作为守护进程运行的时候,它会自动写一个 pid 到 /var/run/redis.pid 文件里面
注意要有权限! redis的权限

supervised no #和操作系统相关参数,可以设置通过upstart和systemd管理Redis守护进程,centos 7以后都使用systemd

pidfile /var/run/redis_6379.pid #pid文件路径
注意与7相同要有权限;

loglevel notice #日志级别

logfile "" #日志路径

databases 16 #设置db 库数量,默认16个库
0开始;到15

always-show-logo yes #在启动redis 时是否显示log

save 900 1 #在900秒内有一个键内容发生更改就出就快照机制

save 300 10

save 60 10000

stop-writes-on-bgsave-error yes #快照出错时是否禁止redis 写入操作

rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之

rdbchecksum yes #是否开启RC64校验,默认是开启

dbfilename dump.rdb #快照文件名

dir ./ #快照文件保存路径一般会更改为绝对路径


###########################################################################
replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:1) 如果replica-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 如果replica-serve-stale-data设置为no,除去指定的命令之外的任何请求都会返回一个错误"SYNC with master in progress"

replica-read-only yes #是否设置从库只读;一定要是只读

repl-diskless-sync no #是否使用socket方式复制数据,目前redis复制提供两种方式,disk和socket,如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件,有2种方式:disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave,socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave,disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件,socket的方式就是一个个slave顺序复制,只有在磁盘速度缓慢但是网络相对较快的情况下才使用socket方式,否则使用默认的disk方式


repl-diskless-sync-delay 5 #diskless复制的延迟时间,设置0为关闭,一旦复制开始还没有结束之前,master节点不会再接收新slave的复制请求,直到下一次开始

repl-ping-slave-period 10 #slave根据master指定的时间进行周期性的PING 监测

repl-timeout 60 #复制链接超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no #在socket模式下是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,

如果你选择“yes”Redis将使用更少的TCP包和带宽来向slaves发送数据。但是这将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果你选择了 "no" 数据传输到salve的延迟将会减少但要使用更多的带宽

repl-backlog-size 1mb #复制缓冲区大小,只有在slave连接之后才分配内存。

repl-backlog-ttl 3600 #多次时间master没有slave连接,就清空backlog缓冲区。

replica-priority 100 #当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。

requirepass foobared #设置redis 连接密码

rename-command #重命名一些高危命令

maxclients 10000 #最大连接客户端

maxmemory #最大内存,单位为bytes字节,8G内存的计算方式8(G)*1024(MB)*1024(KB)*1024(Kbyte),需要注意的是slave的输出缓冲区是不计算在maxmemory内。

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。

appendfilename "appendonly.aof" #AOF文件名

appendfsync everysec #aof持久化策略的配置,no表示不执行fsync,由操作系统保证数据同步到磁盘,always表示每次写入都执行fsync,以保证数据同步到磁盘,everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。

no-appendfsync-on-rewrite no在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。默认为no,表示"不暂缓",新的aof记录仍然会被立即同步,Linux的默认fsync策略是30秒,如果为yes 可能丢失30秒数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐。

auto-aof-rewrite-percentage 100 # 当Aof log增长超过指定比例时,重写log file, 设置为0表示不自动重写Aof 日志,重写是为了使aof体积保持最小,而确保保存最完整的数据。

auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件尺寸

aof-load-truncated yes #是否加载由于其他原因导致的末尾异常的AOF文件(主进程被kill/断电等)

aof-use-rdb-preamble yes #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内存则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据)。


lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒

cluster-enabled yes #是否开启集群模式,默认是单机模式

cluster-config-file nodes-6379.conf #由node节点自动生成和的集群配置文件

cluster-node-timeout 15000 #集群中node节点连接超时时间

cluster-replica-validity-factor 10 #在执行故障转移的时候可能有些节点和master断开一段时间数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移

cluster-migration-barrier 1 #一个主节点拥有的至少正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。

cluster-require-full-coverage yes #集群槽位覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes情况下redis集群槽位验证不全就不再对外提供服务,而no则可以继续使用但是会出现查询数据查不到的情况(因为有数据丢失)。

cluster-replica-no-failover no

#Slow log 是 Redis 用来记录查询执行时间的日志系统,slow log 保存在内存里面,读写速度非常快,因此你可以放心地使用它,不必担心因为开启 slow log 而损害 Redis 的速度。

slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。

slowlog-max-len 128 #记录多少条慢日志保存在队列,超出后会删除最早的,以此滚动删除

127.0.0.1:6379> slowlog len

(integer) 14

127.0.0.1:6379> slowlog get

1) 1) (integer) 14

2) (integer) 1544690617

3) (integer) 4

4) 1) "slowlog"

127.0.0.1:6379> SLOWLOG reset

OK
```

 

### redis 高可用与集群

虽然Redis可以实现单机的数据持久化,但无论是RDB也好或者AOF也好,都解决不了单点宕机问题,即一旦redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失,因此需要使用另外的技术来解决单点问题。

## 配置reids

主备模式,可以实现Redis数据的跨主机备份。

程序端连接到高可用负载的VIP,然后连接到负载服务器设置的Redis后端real server,此模式不需要在程序里面配置Redis服务器的真实IP地址,当后期Redis服务器IP地址发生变更只需要更改redis 相应的后端real server即可,可避免更改程序中的IP地址设置。

![1545808564292](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545808564292.png)

### Slave 主要配置

Redis Slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,Slave端切换master同步后会丢失之前的所有数据。

一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是断开同步关系后不会删除当前已经同步过的数据。

#### 命令行配置

当前状态为master,需要转换为slave角色并指向master服务器的IP+PORT+Password

```shell
192.168.7.104:6379> REPLICAOF 192.168.7.103 6379
OK
192.168.7.104:6379> CONFIG SET masterauth 123456
OK
```

 

 

 

 

##### Redis cluster 主从架构

Redis cluster的架构虽然解决了并发的问题,但是又引入了一个新问题,每个Redis master的高可用如何解决?

![1545817241194](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1545817241194.png)

 

 

 

 

# Docker容器

- 容器:一台计算机的主要目标不是为了运行操作系统而是运行某一特定的程序;将用户空间隔离开,让彼此间不互相干扰称为容器
- 容器是为了隔离运行进程
- 容器是动态化的
- 容器只是进程而已;但是与当前系统中的其他进程隔离开来
- 用户空间:程序运行时所处的位置
- 空间名称:名称空间用来封装一个全局资源在一个抽象层上从而使得能够进行切分

```shell
IPC;同一主机上的进程间通讯的隔离
Network;网络的空间名称机制;主要用于隔离网络设备;网络协议栈;网络接口,端口
Mount;根文件系统;
PID;进程
User;模拟用户的;将宿主机中的普通用户虚拟成为一个用户空间的root用户
UTS;虚拟主机名;使得每个用户空间都有自己的主机名称
Cgroup;把CPU;内存;IO 划分为块 有效的分配给每一个用户控件
```

 

docker在组织容器时一个用户空间(一个容器)只用来运行一个进程及其子进程

启动一个程序就相当于启动一个容器;每一个进程都有自己单独的用户空间;

程序及其程序所依赖的东西都在同一容器内

 

### Docker的架构

C/S架构;

- C端**docker Client** : docker build docker pull docker run

- S端**docker Daemon** : 容器运行时环境(containers)和镜像存储环境(images)

- 远程仓库**docker Registry**:在docker daemon在本地仓库找不到合适的镜像时,则上远程仓库找对应的镜像文件

- 默认指向官方仓库:docker Hub

- docker客户端和服务端通过HTTP/HTTPS协议通讯

- 基于共享内存通讯;默认C/S端都在同一主机上

- 基于RESTful风格的API提供服务 因此docker 内部将其所有管理的组件视为对象

- 同一个对象被抽象成资源的概念 Resource Type
- Object:
- docker images
- docker Container
- docker network
- docker Volume

 

 

 

 

## docker安装

1. 有两种方式安装

1.1

```shell
cd /etc/yum.repos.d/
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce
```

 

安装时可能会报错:yum仓库有问题,yum仓库问题解决办法

```
解决办法1:
yum install http://vault.centos.org/centos/7.3.1611/extras/x86_64/Packages/container-selinux-2.9-4.el7.noarch.rpm

解决办法2:阿里yum仓库
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

注意:在/etc/yum.repos.d目录下执行
```

### docker加速

国内使用docker建议使用镜像加速:阿里为例

```
打开 dev.aliyun.com网站
登陆,进入控制台
搜索容器镜像服务,进入之后点击镜像加速器
复制加速地址
mkdir /etc/docker
vim /etc/docker/daemon.json

{
"registry-mirrors": ["https://0z1c5swq.mirror.aliyuncs.com"]
}

systemctl daemon-reload
systemctl start docker
```

 

查看docker详细信息:docker version

 

 

## docker常用操作

在容器外部停止/删除一个容器:docker stop/rm 容器名称

启动容器:dcoker start 容器名称

停止容器:docker stop

删除容器:docker rm

创建容器:docker run 创建完立即启动

​ docker create 创建完不启动

镜像相关:docker images

​ 获取镜像:docker images pull 镜像名称:版本号(无需特意下载;安装镜像时没有会自动下载)

容器相关:docker

 

 

 

 

两类资源container(容器;运行进程的);images(镜像资源)

1. 有两种操作方式
1. 传统方式 所有的命令混杂在一起;
2. 新方式:各自有各自的子命令
1. 如:容器相关的使用docker container 镜像相关的使用docker images

### docker images

```
images:

docker images --help
docker image pull 从远程下载一个镜像
docker image push 将本地镜像推送到远程
docker image rm = docker rmi 删除镜像
docker image tag 为镜像打标签
docker image inspect 镜像:版本号 查看镜像详细信息
可查看容器默认运行的程序;在"Cmd":{ 栏里面
```

### docker container

```
container

docker container -h 帮助
docker container create 创建容器
docker container start/stop/restart 启动/停止/重启容器
docker container rm 删除容器
docker container rename 重命名
docker container pause/unpause 暂停/继续
docker container ps 查看已经启动的容器信息/查看容器状态
-a/--al查看所有容器信息
```

 

### 容器状态

running;运行态

stopped;停止态

paused;暂停态

created;创建态:刚创建好但还没有启动

deleted;删除态:曾经有但现在被删除了

![1546745376291](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1546745376291.png)

 

## 容器创建和选项:

```
创建镜像时本地如果没有镜像会自动在Registry上获取;但也可以手动获取
注意将防火墙停掉!!!
此处以redis为例!!!

搜索镜像:doceker search redis
下载镜像:docker pull redis (不加任何标签默认是latest最新版)
可以在dockerhub.com里搜索 带alpine的是精简版的
docker pull redis:4-alpine
查看本地镜像:docker image ls
删除本地镜像:docker image rm 镜像名称
查看镜像详细信息:docker image inspect redis:4-alpine
查看容器详细信息:docker container inspect

可以不用下载;默认本地没有此镜像则默认去网上下载

创建容器:docker create 创建不启动 docker run 创建完立即启动
基于此镜象创建容器:docker run = docker container run
docker container run -it --name c1 centos:7 /bin/bash
-i 表示交互式模式 -t表示附加一个终端 -c1是此容器的名称 centos:7是指定的镜像 /bin/bash 指定默认运行的程序
默认运行此进程的话用exit退出 则容器关闭

查看所有处于运行状态的容器信息/查看容器状态:docker container ps
(加上--all选项查看是所有容器)

只有终止ID为1的进程容器才会停止 ps aux查看
```

#### docker run 选项

```
创建docker选项:
docker run --help 注意:所有选项必须写在指定的镜像前面

docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
[COMMAND]不运行镜像内部默认要运行的程序
[ARG..]是传递给命令的参数
[OPTIONS]
-t,--tty 为容器附加一个伪终端
-i, --interactive 进入交互式接口模式
默认命令运行shell时才有必要加-it
--name 如果指定名称则容器一定不可同名
-h/--hostname 指定主机名
--network 指定网络接口;指定网络模式
宿主机上执行docker network ls 查看网络名称接口
容器网络地址默认放在了docker0桥身上 172.17网段
--rm 容器停止则自动删除与-d选项互相抵触
-d,--detach 后台运行容器
```

 

#### docker exec

docker nontainer exec = docker exec

在宿主机上执行后台容器的命令/

```shell
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
CONTAINER 指定容器名字或id
COMMAND 指定运行的命令
[ARG...] 指定命令参数
[OPTIONS]选项(如果使用shell命令行则需加-it)
-d 后台执行
-e 设置环境变量
-t 为容器附加一个伪终端
-i 进入交互式接口模式
-u 用户名或UID(格式:< nameluid>[:<grouplgid>1)
-w 容器内的工作目录
示例:docker container exec -it redis /bin/sh
注意此时用exit退出容器不会终止容器;只有终止ID为1的进程容器才会停止
ps aux查看(在容器内部运行)
示例二:docker container exec redis netstat -tnl
直接返回命令结果 不进入到交互式接口
```

注意:守护进程运行在某一个容器中而且作为此容器中id号为1的进程时;此进程必须要运行在前台;否则容器启动不起来

 

#### docker logs

```shell
docker container logs --help
docker container logs [OPTIONS] CONTAINER

获取容器日志
docker 日志默认没有计入到文件中

```

#### docker stats

```
docker container stats --help
显示容器运行时对资源的占用情况
```

#### docker top

```shell
docker container top --help
docker container top CONTAINER [ps OPTIONS]
显示对应容器内运行的所有进程的相关信息
```

#### docker attach

```
docker attach [OPTIONS] CONTAINER
适用在被剥离终端的容器;如有一个默认进程是/bin/bash的 用[CTRL+P再加Q]剥离终端而后用docker attach 容器名称附加一个终端
--detach-keys string Override the key sequence for detaching a container
--no-stdin Do not attach STDIN
--sig-proxy Proxy all received signals to the process (default true)

```

 

#### 总结常用操作

```
docker search: 在dockerHub中搜索镜像
docker pull: 在dockerhub中下载镜像
docker images: 列出本地镜像
docker create: 创建一个新的容器
docker start: 启动一个或多个停止的容器
docker run: 在新容器中运行一个命令
docker attach: 附加到正在运行的容器上
docker ps: 列出容器
docker logs: 获取容器的日志
docker restart: 重启一个容器
docker stop: 停止一个或多个正在运行的容器
docker kill: 杀死一个或多个正在运行的容器
docker rm: 删除一个或多个容器
```

 

#### 快捷键

```
CTRL + ] 剥离终端
CTRL + p 然后 CTRL +q 剥离终端
docker attach [OPTIONS] CONTAINER 恢复终端
```

 

## Docker images

1. Docker镜像含有**启动容器**所需要的**文件系统**及其内容.因此,其用于**创建并启动docker容器**
2. 采用分层构建机制,最底层为bootfs,其之位rootfs
3. bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以 节约内存资源;
4. rootfs:位于bootfs之上,表现为docker容器的根文件系统;
1. 传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为“只读”模式,完整性自检完成 后将其重新挂载为读写模式;
2. docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载 ”技术额外挂载一个“可写”层

 

- 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image)
- 最上层为“可读写”层,其下的均为“只读”层

 

### Docker Registry
- 启动容器时,docker daemon会试图从本地获取相关的镜像;本地镜像 不存在时,其将从Registry中下载该镜像并保存到本地;
- The Registry is a stateless, highly scalable server side application that stores and lets you distribute Docker images.

 

 

### Docker Hub特性

- Image Repositories **镜像仓库**
- 从社区和官方库中查找和提取图像,并管理、推送和提取您可以访问的私有图像库。
- Automated Builds **自动构建功能**
- 当您更改源代码存储库时,自动创建新映像。
- Webhooks **基于web的触发器;基于web的钩子**
- 作为自动构建的一个特性,webhook允许您在成功地推送到存储库之后触发操作。
- Organizations
- 创建工作组来管理对映像存储库的访问。
- GitHub and Bitbucket Integration
- 将Hub和Docker images添加到当前工作流中。

 

## 在dockerhub上创建自己的镜像仓库

利用以有的镜像启动一个容器;在容器可写层里面做一些简单的修改;而后将修改结果保存为单独的一个层

```
先在docker hub上创建好账户然后创建仓库

docker container commit -h
docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
选项:-p 制作镜像时暂停容器
-a 制作镜像时指明作者
-c 重新指定容器运行时默认运行的程序
```
```
制作镜像:docker container commit c1 zhangqiang3715/zq:v0.1
c1是本地容器 基于本地容器创建的镜像层 zhangqiang3715是项目名/zq是仓库名v0.1是标签
注意!!!项目名称和仓库名一定要与dockerhub上的保持一致
制作镜像范例2:docker container commit -p -a "zhangqiang<444198655@qq.com>" -c "CMD ['/bin/httpd -f -h /data/web/html']" b1
注意没打标签:忘记打标签的补救方法
1. docker image ls 查看镜像ID
2. docker image tag ID zhangqiang3715/zq:v0.2
```
```
docker login 登陆到dockerhub上
docker image push zhangqiang3715/zq:v0.1 将刚刚制作好的镜像推送到dockerhub上
```

 

 

## Docker network

- 虚拟桥接式网络
- 隔离桥:只能在同一桥上的个主机间进行通讯而且地址要在同一网段上
- 仅主机桥:
- 路由桥:
- NAT桥:
- docker的四种网络

1. 桥网络:`bridge`;
1. docker0 这个NAT桥
2. 共享桥;共享接口;
1. 可以理解为联盟式网络;容器之间共享网络
3. host网络;共享宿主机的网络及其网络名称空间
1. 开放式容器
4. none网络;无需用到网络类型;封闭式网络;只有127接口

 

 


```
docker network ls 查看网络类型列表
docker network inspect bridge 查看bridge网络详细信息
--add-host www.heizq.com:172.17.0.1 地址解析;可重复使用以生成多条记录
示例:docker run --name bbox2 -it --rm --hostname bbox --add-host www.heizq.com:172.17.0.1 busybox

```

## 解决外部不能访问容器方式

 

docker虚拟机上监听的端口外部是不能访问的;

- 解决方式:

- 共享宿主机网路

- --add-host

- DNAT

- 外部访问宿主机的时候DNAT到容器上来

- ```shell
iptables -t nat -A PREROUTING -d 宿主机对外的IP -p tcp|udp --
```

- 此方式解决过于麻烦!可以用docker -p选项

- -p选项的使用格式

- ```
-p <containerPort>
将指定的容器端口映射至主机所有地址的一个动态端口
-p <hostPort>:<containerPort>
将容器端口<containerPort>映射至指定的主机端口<hostPort>
-p <ip>::<containerPort>
将指定的容器端口<containerPort>映射至主机指定<IP>的动态端口
-p <ip>:<hostPort>:<containerPort>
将指定的容器端口<containerPort>映射至主机指定<ip>的端口<hostPort>
"动态端口"指随机端口,具体的映射结果可使用docker port命令或iptables -t nat -vnL 查看
-p选项是可以重复使用多次的
```

 

 

 

 

 

 

 

 

 

 


# Nginx

工作在应用层

对nginx来讲核心功能分为三类

http

mail

stream

奇数版本是测试版

偶数版本是正常版本

## Web server

 

 

 

 

## 如何作为代理服务器工作

- Proxy
- HTTP
- mail
- stream (单独的大模块)

- 正向代理:
- 代表客户端发请求
- 客户端发请求时被代理
- 类似于SNAT
- 工作在应用层.TCP/IP协议栈的

- 反向代理:
- 代表服务方接收客户端的请求
- 类似于DNAT

 

`Proxy_set_header field value`

 

 

Proxy_cache

先定义出一个缓存;然后代理再用这个缓存

​ 什么是缓存?

 

 

配置nginx缓存功能

 

键;值是分开存放的 键放在内存中;也就是索引;值存放在磁盘中

索引就是键

缓存服务器IO能力一定要够好

 

## Nginx缓存配置:

`proxy_cache_path /var/cache/nginx levels=1:2:3 keys_zone=webcache:10m max_size=2g`

- /var/cache/nginx缓存路径
- levels=1:2:3 缓存级别
- max_size=2g 分配多大磁盘空间

 

 

 

## fastcgi

fastcgi调用变量名称与nginx不同

​ 需将fastcgi变量的值传给nginx

```shell
docker run --name fpmsrv1 -d --netwoek bridge -v /vols/phpsrv1:/appdata php:7-fpm-alpine
cd /vols/phpsrv1/

```

 

```
location ~* ^/(pm_status|ping)$ {
fastcgi_pass 172.17.0.3:9000

```

 

 

## Nginx负载均衡

- Scale Out
- 四层:nginx(stream),ipvs
- 七层:nginx(http_upstream)

 

- session保持
- session sticky
- cookie
- session replication cluster
- session server

 

 

### 四层负载均衡

简介

```
以mysql为例反向代理和负载均衡是如何工作的
自己不对报文做任何解析,只作为一个通道
类似于DNAT
注意是steam上下文而不是http上下文
```

 

启动容器 注意启两个

```shell
docker run --name db1 -d -e "MYSQL_ROOT_PASSWORD=magedu.com" -v /vols/db1:/var/lib/mysql mysql:5.7
```

连接容器并启动mysql

```shell
docker exec -it db1 /bin/sh
# mysql -pmagedu.com
```

Nginx配置(如果是长连接机制建议使用least_conn)

```shell
stream {
upstream dbsrvs {
server 172.17.0.5:3306;
server 172.17.0.6:3306;

server {
listen 3306;
proxy_pass 172.17.0.6:3306
}
}
```

测试验证

```

```

 

 

## Nginx优化

实现nginx高并发Linux内核优化

 

跨机房调度是SLB

全局负载均衡调度器GSLB

```
fs.file-max=999999
表示单个进程较大的可以打开的句柄数
net.ipv4.tcp_reuse = 1
表示允许让TIME_WAIT状态的socket重新用于新的TCP链接
这对服务器来说意义重大,因为总有大量TIME_WAIT状态的链接存在
net.ipv4.tcp_keepalive_time = 600
当keepalive启动时,TCP发送keepalive消息的频度;默认是2小时;建议不调整
net.ipv4.tcp_fin_timeout = 30
当服务器主动关闭链接时,socket保持
net.ipv4.tcp_max_tw_buckets = 5000
默认是8000
net.ipv4.ip_local_port_range =1024 65000
定义UDP和TCP链接本地端口取值范围
net.ipv4.tcp_rmem = 10240 87380 12582912
定义了TCP接受缓存的最小值,默认值,最大值
net.ipv4.tcp_wmem = 10240 87380 12582912
定义了TCP发送缓存的最小值,默认值,最大值


```

进程数量调整

单进程连接数量调整

启用压缩功能

如果启用ssl会话建议ssl使用共享的

必要时单链接限速

 

 

 

 

# Tomcat

有些应用程序无需安装客户端

一个Tomcat 大概能够实现 3/5百的并发请求

应用程序:

* C/S 客户端与服务端相对应
* B/S 客户端无需安装对应的客户端程序
* 浏览器

 

* 前端开发
* 客户端运行
* 语言:JS
* 后端开发
* 服务器端运行
* 语言:php(适用于中小规模企业,业务结构不复杂的);jsp;c# .net

 

nio bio nio速度更快;

 

fpm

* 软件架构模式
* 分层架构:表现层,业务层,持久层,数据库层
* 事件驱动架构:分布式异步架构,调度解耦
* 微内核架构:即插件式架构
* 类如 nginx
* 微服务架构:API REST-based,application REST-based, 中心化消息
* 每一个模块都是一个网络上的模块,都需要监听
* 基于空间的架构:云架构

 

J2SE J2ME J2EE

j2:

* SE:Standard Edition (标准版)

* EE:Enterprise Edition(企业版)

* ME:Mobile Edition(移动版) 没人用

 

 

## JAVA 技术体系

## 什么是JDK

JAVA标准版就叫 JDK

JDK由JAVA编程语言;JAVA的各种调试工具开发工具;以及JRE组成

JRE:JAVA运行时环境

 

 

![1547888656644](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547888656644.png)

 

 

## 什么是JSP

 

全称:Java Server Page; Java 服务器页面

由 Servlet提供基础架构

JSP属于java 2 EE中的组件

 

.jsp --> Jasper --> .java --> JavaC --> .class --> Servlet

 

Tomcat 基础

1. 运行在JVM之上,然后才能监听套接字
2. tomcat对外监听的有三种协议 http/https/ajp (apache jserv protocol 仅专用于apache内部的协议)
3. 除了自己监听套接字之外并不能服务于用户的请求(部署在tomcat之上的网页站点程序文件才可以)
4.

 

 

 

反代

在使用Nginx进行反代时 客户端与Nginx用HTTPS进行通讯而Nginx与Tomcat进行通讯时用HTTP

 

 

 

 

 

 

 

HotSpot JVM JAVA虚拟机

 

一次编写 到处执行

| | Java code(.java) | |
| :-----: | :-----------------------: | :--: |
| | ↓ | |
| | javac compiler | |
| | ↓ | |
| | Byte Code(.class)(类文件) | |
| | ↓ | |
| JVM | JVM | JVM |
| ↕ | ↕ | ↕ |
| Windows | Linux | Mac |

 

 

 

 

 

JSP是什么

java server page

* applet

CGI

* servlet

 

 

Tomcat 版本的使用是由程序员定义的

监听http与https端口;可以直接解析

 

JDK+Tomcat

 

Tomcat默认监听8080端口

Tomcat本质就是java 2 EE的不完整实现

 

 

### 部署 JDK

open JDK centos 7中yum仓库中直接提供

如果想要下载最新的JDK 自己上网搜索 oracle jdk

#### open JDK 部署

yum list java* 列出open JDK的各个版本

3个版本可以同时安装

alternatives 可以设置默认版本

 

#### oracle jdk

rpm -ivh jdk-8u191-linux-x64.rpm

安装目录

/usr/java/

测试安装成功与否

bin/java -version

 

 

## Tomcat 部署

yum list all tomcat*

```shell
yum install tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp
```

 

 

 

## Tomcat server

 

 

 

![1547447049756](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547447049756.png)

 

如何区别虚拟主机:最简单方式是主机名;(需设置默认虚拟主机名)

 

部署是

 

 

 

## 配置文件

主配置文件:server.xml

web.xml

 

 

 

 

日志必须转为JSON格式才能够存储下来

 

 

 

默认的群集配置:

```shell
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">

<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>

<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>

<SenderclassName="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<TransportclassName="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<InterceptorclassName="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<InterceptorclassName="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>

<Cluster ListenerclassName="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener">
<Cluster ListenerclassName="org.apache.catalina.ha.session.ClusterSessionListener">
</Cluster>
```

 

 

 

 

## session server

此处以memcached为例 但更推荐使用redis

 

存储系统种类繁多

* session manager需要专门添加

存储系统性能高

* 能够存储K/V
* Reids;Memcached

存储系统要有冗余能力

 

 

Cache:无持久能力

* memcached

Store:持久是必备功能

* redis(aof机制)

 

数据流式化

 

 

### 常用优化配置

 

 

# JVM

java程序在执行时能够自动内存回收

主要由两部分组成

1. 执行引擎

2. class loader


![1547543909631](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547543909631.png)

堆时用来放置各种对象

 

 

* 自动内存回收
* 回收方式
* 增量
* 分代:新生代(Eden Spece);老年代(Old Gen);持久代(1.7之后取消了)
* 新生代:Eden;Survivor(存活区)
* Survivor分为:S1;S0; from,to
* 回收机制
* 串行 回收时一个一个的回收
* 并行 多个核心一起工作回收(一般来说线程不应该超过CPU核心线程)
* 并发

 

回收新生代时叫小GC

回收老年代时叫大GC

一般在回收老年代时也会回收新生代叫Full GC

 

垃圾回收算法:

* 新生代:
* Serial 串行回收
* ParNew 新生代并行回收
* Parallel Scavenge:吞吐量
* 老年代
* Serial Old
* Parallel Old
* CMS (Concurrent Mark Sweep):以获得最短回收停顿时长为目标,是互联网站点服务端的B/S系统上较佳的回收算法
* 标记 -> 清除
* 整个过程分为四个阶段
* 初始标记
* 并发标记
* 重新标记
* 并发清楚
* G1 Garbage First
* 并行和并发,分代手机,空间整合,可预测的停顿

JVM频繁使用垃圾回收意味着什么?

内存太小(堆内存空间)

 

## 如何调内存

![1547545980075](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547545980075.png)

内存分配参数:

* -Xmx:堆内存(新生代和老年代)的最大空间;
* -Xms:初始内配内存空间;
* -XX:NewSize:新生代空间大小
* -Xms-(-XX:NewSize)
* -XX:MaxNewSize:新生代的最大空间;
* -Xmx- (-XX:MaxNewSize)
* -XX:NewRatio:新生代除以老年代的值
*

![1547546301965](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547546301965.png)

 

 

# Zabbix监控

监控Java服务时 会有一个中间代理层 Java gatway

 

 

 

##

最小化安装系统安装以下常用包

```
yum install vim iotop bc gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel zip unzip zlib-devel net-tools lrzsz tree ntpdate telnet lsof tcpdump wget libevent libevent-devel
```

 

 

## 安装配置Zabbix

### 编译安装:

 

#### 安装zabbix server端

安装依赖包:

```
yum install gcc libxml2-devel net-snmp net-snmp-devel curl curl-devel php php-bcmath php-mbstring mariadb mariadb-devel –y
```


1. 配置数据库
```shell
[zabbix-mysql]# yum install mariadb mariadb-server
[zabbix-mysql]# systemctl start mariadb
[zabbix-mysql]# mysql_secure_installation mysql
[zabbix-mysql]# mysql
MariaDB [(none)]> show databases;
MariaDB [(none)]> create database zabbix character set utf8 collate utf8_bin; (创建一个数据库zabbix 使用utf-8编码)
MariaDB [(none)]> grant all privileges on zabbix.* to zabbix@localhost identified by 'centos'; 此步骤是授权数据库授权用户及设置密码 zabbix@代表用户 localhost代表地址 'centos'密码
```

2. 测试连接数据库

```
[root@zhangqiang zabbix-server]# yum install mysql -y
[root@zhangqiang zabbix-server]# mysql -uzabbix -p394355 -h192.168.31.41
注意:如果连接不了 有可能是防火墙的问题:
关闭防火墙 systemctl stop firewalld.service
永久关闭防火墙 systemctl disable firewalld.service

```

3. 开始编译安装

```
[root@zhangqiang zabbix-server]# cd /usr/local/src/
[root@zhangqiang zabbix-server]# tar -xvf zabbix-4.0.1.tar.gz
如果选择开启Java 即监控Java服务 则需安装java-1.8.0(ubutun系统安装openjdk-1.8.0)
[root@zhangqiang zabbix-server]# ./configure --prefix=/apps/ --enable-server --enable-agent --with-mysql --enable-ipv6 --with-net-snmp --with-libcurl --with-libxml2 --enable-java
[root@zhangqiang zabbix-server]# make && make install
注意在/usr/local/src/zabbix-4.0.5下执行
如果只安装agent则只需要执行./configure --enable-agent
```

4. 编译zabbix安装时报错解决办法:

```
错误: checking for libevent support... no
configure: error: Unable to use libevent (libevent check failed)
解决: yum install libevent-devel -y

错误: configure: error: MySQL library not found
解决: #yum install mysql-devel

错误: configure: error: Jabber library not foun
解决: #wget http://iksemel.googlecode.com/files/iksemel-1.4.tar.gz
下载完成后解压、配置、安装:
tar zxvf iksemel-1.4.tar.gz
cd iksemel-1.4
configure
make
make install
之后对zabbix进行configure还是会遇到这个问题,那么将jabber目录指定即可:#./configure --enable-server --enable-agent --with-mysql --with-net-snmp --with-jabber=/usr/local/ --with-libcurl

错误: configure: error: Not found curl Library
解决: #yum install curl-devel (此项未经测试)

错误: configure: error : Not found NET-SNMP library
解决: yum install net-snmp-devel

错误: error: Invalid Net-SNMP directory - unable tofind net-snmp-config
解决: yum install net-snmp-devel

错误: configure: error: Jabber library not found
解决: #yum install iksemel-devel -y 即可,

错误: configure: error: LIBXML2 library not found
解决: #yum install libxml2-devel -y

错误: configure: error: unixODBC library not found
解决: #yum install unixODBC-devel -y

错误: configure: error: Invalid OPENIPMI directory -unable to findipmiif.h
解决: #yum install OpenIPMI-devel

错误: configure:error: Unable to find"javac" executable in path
解决: yum install java-devel -y

错误: configure: error: Curl library not found
解决: # yum install curl-devel –y

错误: configure: error: SSH2 library notfound
解决: yum install -y libssh2-devel
```

 

5. 导入数据库

```
#先导入此文件,如果做zabbix代理服务器,则只导入此文件即可

[root@zabbix-server zabbix-4.0.5]# mysql -uzabbix -pcentos -h192.168.31.41 zabbix< database/mysql/schema.sql
[root@zabbix-server zabbix-4.0.5]# mysql -uzabbix -pcentos -h192.168.31.41 zabbix< database/mysql/images.sql
[root@zabbix-server zabbix-4.0.5]# mysql -uzabbix -pcentos -h192.168.31.41 zabbix< database/mysql/data.sql

```

6. 复制启动脚本

```shell
[root@zabbix-server zabbix-4.0.5]# cp /usr/local/src/zabbix-4.0.3/misc/init.d/fedora/core/zabbix_server /etc/init.d/
[root@zabbix-server zabbix-4.0.5]# cp /usr/local/src/zabbix-4.0.3/misc/init.d/fedora/core/zabbix_agentd /etc/init.d/

```

7. 更改启动脚本

```
vim /etc/init.d/zabbix_server
# Zabbix-Directory
BASEDIR=/apps/zabbix(更改为安装路径)

# PID file
PIDFILE=/apps/zabbix/$BINARY_NAME.pid

```

8. 更改zabbix_server.con配置文件

```
cd /apps/zabbix/etc
vim /apps/zabbix/etc/zabbix_server.conf
更改LogFile路径为/apps/zabbix/zabbix_server.log
将Option:PodFile下的PidFile取消注释并更改路径为PidFile=/apps/zabbix/zabbix_server.pid
将socketDir=取消注释并更改为socketDir=/apps/zabbix
将DBHost=localhost更改为MySQL服务器地址
将DBPassword密码更改为对应的密码
将DBPort端口更改为3306
```

9. 创建用户

```
[root@zabbix-server zabbix-4.0.5]# useradd zabbix -s /sbin/nologin 创建不能登陆的zabiix用户
[root@zabbix-server zabbix-4.0.5]# chown zabbix.zabbix /apps/zabbix/ -R 授权
```

10. 启动zabbix server

```shell
[root@zabbix-server]# /etc/init.d/zabbix_server start 启动
ss -tnl查看是否启动

如启动不成功且没有日志文件 用-c强制指定配置文件
/apps/zabbix/sbin/zabbix_server -c /apps/zabbix/etc/zabbix_server.conf
```

11. 配置web界面/解决报错

```
[root@zabbix-server]# yum install httpd -y
[root@zabbix-server]# mkdir /var/www/html/zabbix
[root@zabbix-server]# cp -a /usr/local/src/zabbix-4.0.3/frontends/php/* /var/www/html/zabbix
[root@zabbix-server]# systemctl start httpd
注意:如果不能访问则有可能是防火墙问题;
解决方法: systemctl stop firewalld.service 关闭firewalld防火墙
systemctl disable firewalld.service 永久关闭防火墙

解决报错:
1. yum install php-gettext php-session php-ctype php-xmlreader php-xmlwriter php-xml php-net-socket php-gd php-mysql -y
yum -y install php-ldap
2.vim /etc/php.ini
post_max_size = 8M更改为16M 上传文件大小
max_execution_time = 30更改为300 最大指定时间
max_input_time = 60更改为300 最大输入时间
date.timezone = Asia/Shanghai 时区设定为上海

配置完成重启httpd
```

12. 默认用户名是Admin 密码是zabbix(注意大小写)

13. 更改语言为中文:依次点击Administration --> Users --> Admin

14. 如果web界面出现乱码的解决办法

```
注意:如果web界面里面有乱码的解决办法
在Windows的控制面板中复制字体 上传到服务器上
/var/www/html/ fonts 上传到此处
cd .. 切换到上级目录
grep "DejaVuSans" ./* -R
vim ./include/defines.inc.php 将此文件内的原来的文字名称更改为自己刚刚上传的名称
```

15. server端也可以监控自己 此处是server服务器上的agent配置

```
更改agent参数;server端也可以监控自己,但server端中的agentd.conf更改的参数较少
vim /apps/zabbix/etc/zabbix_agentd.conf
LogFile= 日志文件路径
Server= zabbix_server的IP地址 如本机是server端则可以不做修改(被动模式)
StartAgents=3 取消注释(至少一个) 是agent进程起来会先起来几个进程做数据的收集
ServerActive=IP地址 主动模式下是谁
Hostname= 在zabbix_server里面用于区分监控主机的值 注意:必须保留不能重复;(web界面的主机名称必须和此处的相同 一般设置为本机的IP地址)
```

16. ```
vim /etc/init.d/zabbix_agentd

\# Zabbix-Directory

BASEDIR=/apps/zabbix/ 启动脚本的路径 将此处路径更改为装路径
```

17. 创建启动zabbix_server启动脚本

```
vim /etc/init.d/zabbix_server

# Zabbix-Directory
BASEDIR=/apps/zabbix/ 注意:只更改这也可以但注意一定要有后面的/

# Full Binary File Call
FULLPATH=/apps/zabbix/sbin/zabbix_server

start() {
if [ $RUNNING -eq 1 ]
then
echo "$0 $ARG: $BINARY_NAME (pid $PID) already running"
else
action $"Starting $BINARY_NAME: " /apps/zabbix/sbin/zabbix_server -c /apps/zabbix/etc/zabbix_server.conf
touch /var/lock/subsys/$BINARY_NAME
```

 

 

 

#### zabbix_agent安装配置

```
将源码包上传至/usr/local/src/下

安装开发包组 yum install gcc libxml2-devel net-snmp net-snmp-devel curl curl-devel php php-bcmath php-mbstring mariadb mariadb-devel –y

解压RPM包 tar -xvf zabbix-4.0.3.tar.gz

开始编译安装 ./configure --prefix=/apps/zabbix --enable-agent
```

 

1. 更改agent配置文件

```
vim /apps/zabbix/etc/zabbix_agentd.conf
PidFile=/apps/zabbix/zabbix_agentd.pid pid路径更改为安装目录下
LogFile=/apps/zabbix/zabbix_agentd.log 日志文件路径更改为安装目录下
DebugLevel=3 Debug模式打开 取消注释
Server=127.0.0.1 如果是被动模式则无需更改默认127.0.0.1 如是主动则更改为对应的server服务器IP
ListenPort=10050
ListenIP=0.0.0.0
StartAgents=3 agent事先开启的进程数 至少为1
Hostname=192.168.122.129 一定要更改为本机IP 或保证主机名的唯一性
Timeout=30 超时时长 最长30秒
UnsafeUserParameters=1 是否支持特殊符号 1表示支持

grep "^[a-Z]" zabbix_agentd.conf 查看更改哪些配置
```

2. 拷贝启动脚本

```
cp /usr/local/src/zabbix-4.0.3/misc/init.d/fedora/core/zabbix_agentd /etc/init.d/ 拷贝启动脚本
```

3. 创建用户

```
useradd zabbix -s /sbin/nologin 创建用户
chown zabbix.zabbix /apps/zabbix/ -R 授权用户

```

4. 更改启动脚本

```
[root@zabbix-web1 etc]# vim /etc/init.d/zabbix_agentd
\# Zabbix-Directory
BASEDIR=/apps/zabbix/ 启动脚本的路径 将此处路径更改为装路
```

 

#### zabbix get命令

如果是编译安装的话 在编译安装目录的/bin下 如:/apps/zabbix/bin下

```
将其拷贝至/usr/bin下
cd /apps/zabbix/bin
cp zabbix_get /usr/bin/
zabbix_get -h 获取帮助
-s ip地址 指定主机 -p 10050指定端口(默认10050) -k "system.cpu.load[all,ang1]"(例子 cpu 还有:agent.ping )指定监控项

```

安装文件详解

```
bin 放可执行程序的
etc 放配置文件的
sbin 放zabbix_agentd和zabbix_server
share 后面放脚本时放在这里
```

 

 

 

 

 

## 监控服务:TomCat

什么是java gateway?

答:server想监控java服务 会先向Java gateway会发起采集数据的请求 说我要监控或采集莫一个主机的Java监控项 这个就是java gateway java gateway相当于是个代理 会将监控java服务的请求转发到后端java服务(JMX-12345)

 

在zabbix-proxy上安装javagateway

 

 

 

##### 安装JDK / 配置JDK环境

下载源码包到/apps目录里

```
[root@zabbix-web1 apps]# tar xvf jdk-8u191-linux-x64.tar.gz 解压
[root@zabbix-web1 apps]# ln -sv /apps/jdk1.8.0_191 /apps/jdk 创建软连接方便日后升级
```

 

修改配置文件

```
vim /etc/profile 将下面的参数全部粘贴进去
export JAVA_HOME=/usr/local/jdk
export TOMCAT_HOME=/apps/tomcat
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOME/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
```

重新读取配置文件

```
source /etc/profile
java -version
```

 

 

###### 配置tomcat

将tomcat解压出来 并进入到webapps里面创建一个目录里在里面建立一个index页面

```
[root@zabbix-web1 apps]# tar xxvf apache-tomcat-8.5.37.tar.gz
[root@zabbix-web1 apps]# cd apache-tomcat-8.5.37
[root@zabbix-web1 apache-tomcat-8.5.37]# cd webapps/
[root@zabbixweb1 webapps]# mkdir testweb
[root@zabbixweb1 webapps]# vim testweb/index.html
```

###### 启动/停止tomcat

```
[root@zabbixweb1 apache-tomcat-8.5.37]# ./bin/startup.sh 或shutdown.sh
[root@zabbixweb1 apache-tomcat-8.5.37]# ./bin/catalina.sh run 也是启动在业务启动时出现问题用此方法 会显示各种日志 前台方式启动
此处我们用的是./bin/catalina.sh start
```

###### 测试访问

```
浏览器中输入http://192.168.31.159:8080/testweb/
```

 

 

###### 配置tomcat监控参数:

```
[root@zabbix-web1 apache-tomcat-8.5.37]# vim /apps/apache-tomcat-8.5.37/bin/catalina.sh

CATALINA_OPTS="$CATALINA_OPTS
-Dcom.sun.management.jmxremote#启用远程监控JMX
-Dcom.sun.management.jmxremote.port=12345 #默认启动的JMX端口号,要和zabbix添加主机时候的端口一致即可
-Dcom.sun.management.jmxremote.authenticate=false #不使用用户名密码
-Dcom.sun.management.jmxremote.ssl=false #不使用ssl认证
-Djava.rmi.server.hostname=x.x.x.x" #tomcat主机自己的IP地址,不要写zabbix服务器的地址
```

 

 

 

 

 

 

 

 

## 主动zabbix proxy

* 主动模式与被动模式工作原理
* 安装主动模式zabbix proxy
* 配置agent为主动模式
* 添加主机并关联模板
* 验证数据

 

 

主动zabbix proxy

 

![1547708467491](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547708467491.png)

 

### 主动与被动

* 这是对于zabbix agent来说的工作模式
* 被动模式就是由zabbix server向zabbix agent发出指令获取数据,即zabbix agent被动的去获取数据并返回给zabbixserver,zabbix server周期性的向agent 索取数据,这种模式的最大问题就是会加大zabbix server的工作量,在数百台服务器的环境下zabbix server不能及时获取到最新数据,但这也是默认的工作方式。
* 主动模式是有zabbix agent主动采集数据并返回给zabbix server,不再需要zabbix serve进行干预,因此主动模式在一定程度上可减轻zabbix server的压力。
* ![1547708565648](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1547708565648.png)

 

### Zabbix proxy

0 是主动模式

1 是被动模式

默认是被动模式

 

 

 

Proxy 主动模式配置文件:

```
# grep"^[a-Z]" /usr/local/zabbix/etc/zabbix_proxy.conf
ProxyMode=0 #0为主动,1为被动
Server=192.168.15.201 #zabbixserver服务器的地址或主机名
Hostname=mage_proxy#代理服务器名称,需要与zabbixserver添加代理时候的proxy name是一致的!
LogFile=/tmp/zabbix_proxy.log
DBHost=192.168.15.203 #数据库服务器地址
DBName=zabbix_proxy
DBUser=zabbix
DBPassword=123456
DBPort=3306
ProxyLocalBuffer=3 #已经提交到zabbixserver的数据保留时间
ProxyOfflineBuffer=24 #未提交到zabbixserver的时间保留时间
HeartbeatFrequency=60 #心跳间隔检测时间,默认60秒,范围0-3600秒,被动模式不使用
ConfigFrequency=5 #间隔多久从zabbixserver 获取监控信息
DataSenderFrequency=5 #数据发送时间间隔,默认为1秒,范围为1-3600秒,被动模式不使用
StartPollers=20 #启动的数据采集器数量
JavaGateway=192.168.15.202 #java gateway服务器地址
JavaGatewayPort=10052
StartJavaPollers=20 #启动多少个线程采集数据
CacheSize=2G #保存监控项而占用的最大内存
HistoryCacheSize=2G #保存监控历史数据占用的最大内存
Timeout=30
LogSlowQueries=3000
```

 

Proxy 主动数据库配置:

```
[root@mysql-serverzabbix-proxy-mysql-4.0.1]# pwd
/usr/share/doc/zabbix-proxy-mysql-4.0.1
#zcatschema.sql.gz | mysql-uzabbix_active-p123456 -h192.168.15.203 zabbix_proxy_active
# systemctl restart zabbix-proxy.service
```

 

客户端安装agent

```shell
Web 客户端安装zabbixagent:
# yum install gcc-y
# useraddzabbix-s /sbin/nologin
# tar xvfzabbix-4.0.1.tar.gz
# cd zabbix-4.0.1
# ./configure --prefix=/usr/local/zabbix--enable-agent
# make install
# cpmisc/init.d/fedora/core/zabbix_agentd/etc/init.d/
# vim /etc/init.d/zabbix_agentd
–22 BASEDIR=/usr/local/zabbix
```

更改配置文件:

```shell
[root@web-serverapps]# grep"^[a-Z]" /usr/local/zabbix/etc/zabbix_agentd.conf
LogFile=/tmp/zabbix_agentd.log
DebugLevel=4
Server=192.168.15.203
ListenPort=10050
ListenIP=0.0.0.0
StartAgents=3
ServerActive=192.168.15.203
Hostname=192.168.15.204
Timeout=30
UnsafeUserParameters=1
```

 

 

监控Memcache

204 安装memcached

 

1.监控脚本内容:

注意提前安装好nc命令

```shell
#!/bin/bash
memcached_status(){
M_PORT=$1
M_COMMAND=$2
echo -e "stats\nquit" | nc127.0.0.1 "$M_PORT" | grep"STAT $M_COMMAND " | awk'{print $3}'
}
main(){
case $1 in
memcached_status)
memcached_status $2 $3
;;
esac
}

main $1 $2 $3
```

 

调用脚本

```
[root@zabbix-web2 zabbix_agentd.conf.d]# cat all.conf
UserParameter=linux_status[*],/usr/local/zabbix/etc/zabbix_agentd.conf.d/tcp_conn_plugin.sh "$1" "$2" "$3"
UserParameter=memcache_status[*],/usr/local/zabbix/etc/zabbix_agentd.conf.d/memcache.sh "$1" "$2" "$3"
测试脚本:bash memcache.sh memcached_status 11211 curr_connections
```

```
/etc/init.d/zabbix_agentd restart
```

```
curr_connections是当前链接;其他选项用此命令查看
echo -e "stats \nquit" | nc 127.0.0.1 11211
```

 

 

 

# HAProxy负载均衡

### 什么是负载均衡

![1548034456717](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1548034456717.png)

* 负载均衡(Load Balance, 简称LB) 是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务,网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高公司业务的并发处理能力,保证里业务的高可用性,方便里业务后期的1水平动态扩展
* https://

 

 

### 为什么使用负载均衡

* Web服务器的动态水平扩展
* 对用户无感知
* 增加业务并发访问及处理能力
* 解决但服务器瓶颈问题
* 节约公网IP地址
* 降低IT支出成本
* 隐藏内部服务器IP
* 提高内部服务器安全性
* 配置简单
* 固定格式的配置文件
* 功能丰富
* 支持四层和七层,支持动态下线主机
* 性能较强
* 并发数万甚至数十万

 

 

### 常见有哪些负载均衡

* 软件负载:
* 四层:
* LVS
* HAProxy
* Nginx(1.9.9以上版本)
* 七层:
* HAProxy
* Nginx
* ...
* 硬件负载:
* F5
* Netscler

### 典型应用场景

* 四层:Redis Mysqk RabbitMQ Memcache 等
* Nginx,Tomcat Apache,PHP,图片,动静分离,API等

 

 

## HAproxy

### 功能

* HAProxy是TCP/HTTP反向代理服务器,尤其适合于高可用高并发环境
* 可以针对HTTP请求添加cookie,进行路由后端服务器
* 可平衡负载至后端服务器,并支持持久连接
* 支持基于cookie进行调度
* 支持所有主服务器故障切换至备用服务器
* 支持专用端口实现监控服务
* 支持不影响现有连接情况下停止接受新连接请求
* 可以在双向添加,修改或删除HTTP报文首部
* 支持基于pattern实现连接请求的访问控制
* 通过特定的URL为授权用户提供详细的状态信息
* 历史版本更新功能:1.4 1.5 1.6 1.7 1.8 1.9 2.0-dev

 

## 安装HAProxy

yum install haproxy

 

 

编译安装:

解决依赖关系

```
yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget ntpdate
```

一定要安装systemd-devel

 

开始编译安装:

```
tar xvf haproxy-1.8.16.tar.gz && cd haproxy-1.8.16
make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
cp haproxy /usr/sbin/
```

 

创建启动脚本

```
cat /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
```

 

 

 

## HAProxy静态调度算法

* balance: 指明对后端服务器的调度算法,配置在listen或backend

```
balance first/static-rr
```

* 静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能重启后生效。
* static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制
* 部署此方式需安装socet yum install socat
* first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。

## HAProxy 动态调度算法

* 动态算法:基于后端服务器 状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。
* roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法,server 权重设置 weight
* leastconn: 加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度,比较适合长连接的场景使用,比如MySQL等场景。


### HAProxy调度算法-source

* 会话保持,小型业务或这用户源地址非集中访问

* source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持等场景。

* map-based:**取模法**,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,**不支持慢启动**,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变。
* consistent:**一致性哈希**,该hash是动态的,**支持在线调整权重,支持慢启动**,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,该算法很容易导致后端服务器负载不均衡,但是比较适合session保持。
* 只适用与访问量较小的网站

```shell
vim /etc/haproxy/haproxy.cfg
listen web_prot_http_nodes
bind 192.168.7.101:80
mode http
balance source
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
```

 

### HAProxy调度算法-uri

URL是URI的一个子项

* uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器

* map-based:取模法

* consistent:一致性哈希
* http://example.org/absolute/URI/with/absolute/path/to/resource.txt #URI/URL
* ftp://example.org/resource.txt #URI/URL
* /relative/URI/with/absolute/path/to/resource.txt #URI

uri: uniform resource identifier,统一资源标识符,是一个用于标识某一互联网资源名称的字符串

 

#### uri调度算法示例:

```
vim /etc/haproxy/haproxy.cfg
listen web_prot_http_nodes
bind 192.168.7.101:80
mode http #不支持tcp,会切换到tcp的roundrobin负载模式
balance uri
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
```

```
[root@s2 ~]# curl http://192.168.7.101/index.html
<h1>192.168.7.101</h1>
[root@s2 ~]# curl http://192.168.7.101/index.html
<h1>192.168.7.101</h1>
[root@s2 ~]# curl http://192.168.7.101/test.html
<h1>192.168.7.101-test</h1>
[root@s2 ~]# curl http://192.168.7.101/test.html
<h1>192.168.7.101-test</h1>
```

### HAProxy调度算法-url_param

只有电商

* url_param:

对用户请求的url中的<params>部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server

 

假设url = <http://www.magedu.com/foo/bar/index.php?k1=v1&k2=v2>

则:

host = "www.magedu.com"

url_param = "k1=v1&k2=v2"

 

#### url_param调度算法示例

```
vim /etc/haproxy/haproxy.cfg
listen web_prot_http_nodes
bind 192.168.7.101:80
mode http #不支持tcp,会切换到tcp的roundrobin负载模式
balance url_param name #基于参数name做hash
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
```

 

### HAProxy 调度算法-hdr

* hdr(<name>):针对用户每个http头部(header)请求中的指定信息做hash,此处由<name>指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度
* hdr( Cookie、 User-Agent、host )

```
listen web_prot_http_nodes
bind 192.168.7.101:80
mode http
balance hdr(User-Agent)
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
```

 

 

### HAProxy 调度算法-rdp-cookie

- rdp-cookie对远程桌面的负载,使用cookie保持会话
- rdp-cookie(<name>)

 

```
listen RDP
bind 192.168.7.101:3389
balance rdp-cookie
mode tcp
server rdp0 172.18.139.20:3389 check fall 3 rise 5 inter 2000 weight 1
server rdp1 172.18.139.21:3389 check fall 3 rise 5 inter 2000 weight 1
```

- 基于iptables实现目标地址转换:

- ```
- iptables -t nat -A PREROUTING -d 192.168.7.101 -p tcp --dport 3389 -j DNAT --to-destination 172.18.139.20:3389
- iptables -t nat -A POSTROUTING -s 192.168.0.0/21 -j SNAT --to-source 192.168.7.101
```


算法总结

roundrobin-------->tcp/http 动态

leastconn----------->tcp/http 动态

static-rr-------------->tcp/http 静态

first-------------------->tcp/http 静态

==source---------------->tcp/http==

==Uri---------------------->http==

==url_param---------->http 取决于hash_type是否consistent==

==hdr--------------------->http==

==rdp-cookie--------->tcp==

 

## Cookie配置

```
cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
<name>:cookie名称,用于实现持久连接
rewrite:重写
insert:插入
prefix:前缀
nocache:当client和hapoxy之间有缓存时,不缓存cookie

```

 

Cookie配置实例

* 基于cookie实现的session 保持

```
listen web_prot_http_nodes
bind 192.168.7.102:80
mode http
cookie SERVER-COOKIE insert indirect nocache
server 192.168.7.101 192.168.7.101:8080 cookie web1 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 cookie web2 check inter 3000 fall 3 rise 5
```

![1548061746306](C:\Users\zhangqiang\AppData\Roaming\Typora\typora-user-images\1548061746306.png)

 

 

### 配置HAProxy状态页

```
stats enable #基于默认的参数启用stats page
stats hide-version # 隐藏版本
stats refresh <delay> # 设定自动刷新时间间隔
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能
```

配置HAProxy状态页

```
listen stats
bind :9009
stats enable
#stats hide-version
stats uri /haproxy-status
stats realm HAPorxy\ Stats\ Page
stats auth haadmin:123456
stats auth admin:123456
stats refresh 30s
stats admin if TRUE
```

 

## HAProxy日志配置

```
在default配置项定义:
log 127.0.0.1 local{1-7} info #基于syslog记录日志到指定设备,级别有(err、warning、info、debug)
配置rsyslog:
$ModLoad imudp
$UDPServerRun 514
local3.* /var/log/haproxy.log
配置HAProxy:
listen web_port
bind 127.0.0.1:80
mode http
log global
option tcplog
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
重启syslog服务并访问haproxy状态页
```

 

 

 

## HAProxy动态上下线

```shell
yum install socat
echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock
echo "get weight web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock
echo "disable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock
echo "enable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock
```

 

posted @ 2019-03-31 00:02  张强0514  阅读(138)  评论(0编辑  收藏