系统服务运维第三阶段

一、Mysql

1、基本操作

1、下载和安装

固定主机ip
  1. 打开配置文件:/etc/sysconfig/network-scripts/ifcfg-ens33

  2. 查看网卡:route -n

    先安装net-tools

  3. 修改配置文件

1.1、rpm 安装

安装顺序

  1. 先将四个rpm包放在 /opt 目录下
  2. rpm -ivh mysql-community-common-5.7.37-1.el7.x86_64.rpm
  3. rpm -ivh mysql-community-libs-5.7.37-1.el7.x86_64.rpm
  4. rpm -ivh mysql-community-client-5.7.37-1.el7.x86_64.rpm
  5. rpm -ivh mysql-community-server-5.7.37-1.el7.x86_64.rpm

进入数据库

  1. mysql -u root -p

    我们需要先从 cat /var/log/mysqld.log | grep password 查看密码

  2. 在我们进行其他操作的时候都出提示让你修改密码:set password=password('1234.Com')

  3. 启动服务:systemctl start mysqld

1.2、源码包安装

安装数据库

# 1、获取镜像源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 2、检查是否有残留的mysql
rpm -qa | grep mysql

# 3、检查是否有残留的mariadb
rpm -qa | grep mariadb

# 4、删除mariadb
rpm -e --nodeps mariadb-libs
注意:如果此时使用yum删除会将与mariadb的依赖关系的包一并删除

# 5、安装相关软件包:
yum install -y cmake make gcc gcc-c++ openssl openssl-devel ncurses ncurses-devel bison bison-devel

# 6、上传并解压
tar -zxf mysql-boost-5.7.37.tar.gz -C /usr/local/
cd /usr/local/mysql-5.7.37/

# 7、编译文件
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -
DSYSCONFDIR=/usr/local/mysql/etc -DWITH_INNOBASE_STORAGE_ENGINE=ON -DWITH_MYISAM_STORAGE_ENGINE=ON -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -
DENABLED_LOCAL_INFILE=ON -DMYSQL_TCP_PORT=3306 -DMYSQL_UNIX_ADDR=/usr/local/mysql/tmp/mysql.sock -
DWITH_INNODB_MEMCACHED=ON -DWITH_BOOST=boost/boost_1_59_0

# 8、将代码变成可执行文件
make && make install

初始化数据库

1、

groupadd mysql
useradd -r -g mysql -s /bin/false mysql
cd /usr/local/mysql
mkdir -p /usr/local/mysql/data
mkdir -p /usr/local/mysql/etc
mkdir -p /usr/local/mysql/tmp
mkdir -p /usr/local/mysql/logs
chown -R mysql:mysql /usr/local/mysql
vim /usr/local/mysql/etc/my.cnf

2、修改my.cnf文件

[client] #客户端设置
port=3306 #服务器监听端口,默认为3306
socket=/usr/local/mysql/tmp/mysql.sock #Unix套接字文件路径,默认/tmp/mysql.sock
[mysqld] #服务端设置
## 一般配置选项
port=3306 #服务器监听端口,默认为3306
basedir=/usr/local/mysql #MySQL安装根目录
datadir=/usr/local/mysql/data #MySQL数据文件目录
socket=/usr/local/mysql/tmp/mysql.sock #Unix套接字文件路径,默认/tmp/mysql.sock
pid-file=/usr/local/mysql/tmp/mysql.pid #服务进程pid文件路径
character_set_server=utf8 #默认字符集
default_storage_engine=InnoDB #默认InnoDB存储引擎
user=mysql
## 连接配置选项
max_connections=200 #最大并发连接数
table_open_cache=400 #表打开缓存大小,默认2000
open_files_limit=1000 #打开文件数限制,默认5000
max_connect_errors=200 #最大连接失败数,默认100
back_log=100 #请求连接队列数
connect_timeout=20 #连接超时时间,默认10秒
interactive_timeout=1200 #交互式超时时间,默认28800秒
wait_timeout=600 #非交互超时时间,默认28800秒
net_read_timeout=30 #读取超时时间,默认30秒
net_write_timeout=60 #写入超时时间,默认60秒
max_allowed_packet=8M #最大传输数据字节,默认4M
thread_cache_size=10 #线程缓冲区(池)大小
thread_stack=256K #线程栈大小,32位平台196608、64位平台262144
## 临时内存配置选项
tmpdir=/tmp #临时目录路径
tmp_table_size=64M #临时表大小,默认16M
max_heap_table_size=64M #最大内存表大小,默认16M
sort_buffer_size=1M #排序缓冲区大小,默认256K
join_buffer_size=1M #join缓冲区大小,默认256K

join_buffer_size=1M #join缓冲区大小,默认256K
## Innodb配置选项
#innodb_thread_concurrency=0 #InnoDB线程并发数
innodb_io_capacity=200 #IO容量,可用于InnoDB后台任务的每秒I/O操作数(IOPS),
innodb_io_capacity_max=400 #IO最大容量,InnoDB在这种情况下由后台任务执行的最大IOPS数
innodb_lock_wait_timeout=50 #InnoDB引擎锁等待超时时间,默认50(单位:秒)
innodb_buffer_pool_size=512M #InnoDB缓冲池大小,默认128M
innodb_buffer_pool_instances=4 #InnoDB缓冲池划分区域数
innodb_max_dirty_pages_pct=75 #缓冲池最大允许脏页比例,默认为75
innodb_flush_method=O_DIRECT #日志刷新方法,默认为fdatasync
innodb_flush_log_at_trx_commit=2 #事务日志刷新方式,默认为0
transaction_isolation=REPEATABLE-READ #事务隔离级别,默认REPEATABLE-READ
innodb_data_home_dir=/usr/local/mysql/data #表空间文件路径,默认保存在MySQL的datadir中
innodb_data_file_path=ibdata1:128M:autoextend #表空间文件大小
innodb_file_per_table=ON #每表独立表空间
innodb_log_group_home_dir=/usr/local/mysql/data #redoLog文件目录,默认保存在MySQL的datadir中
innodb_log_files_in_group=2 #日志组中的日志文件数,默认为2
innodb_log_file_size=128M #日志文件大小,默认为48MB
innodb_log_buffer_size=32M #日志缓冲区大小,默认为16MB
## MyISAM配置选项
key_buffer_size=32M #索引缓冲区大小,默认8M
read_buffer_size=4M #顺序读缓区冲大小,默认128K
read_rnd_buffer_size=4M #随机读缓冲区大小,默认256K
bulk_insert_buffer_size=8M #块插入缓冲区大小,默认8M
myisam_sort_buffer_size=8M #MyISAM排序缓冲大小,默认8M
#myisam_max_sort_file_size=1G #MyISAM排序最大临时大小
myisam_repair_threads=1 #MyISAM修复线程
skip-external-locking #跳过外部锁定,启用文件锁会影响性能
## 日志配置选项
log_output=FILE #日志输出目标,TABLE(输出到表)、FILE(输出到文件)、NONE(不输出),可选择一个或多个以逗>号分隔
log_error=/usr/local/mysql/logs/error.log #错误日志存放路径
log_error_verbosity=1 #错误日志过滤,允许的值为1(仅错误),2(错误和警告),3(错误、警告和注释),默认值为3。
log_timestamps=SYSTEM #错误日志消息格式,日志中显示时间戳的时区,UTC(默认值)和 SYSTEM(本地系统时区)
general_log=ON #开启查询日志,一般选择不开启,因为查询日志记录很详细,会增大磁盘IO开销,影响性能
general_log_file=/usr/local/mysql/logs/general.log #通用查询日志存放路径
## 慢查询日志配置选项
slow_query_log=ON #开启慢查询日志
slow_query_log=ON #开启慢查询日志
slow_query_log_file=/usr/local/mysql/logs/slowq.log #慢查询日志存放路径
long_query_time=2 #慢查询时间,默认10(单位:秒)
min_examined_row_limit=100 #最小检查行限制,检索的行数必须达到此值才可被记为慢查询
log_slow_admin_statements=ON #记录慢查询管理语句
log_queries_not_using_indexes=ON #记录查询未使用索引语句
log_throttle_queries_not_using_indexes=5 #记录未使用索引速率限制,默认为0不限制
log_slow_slave_statements=ON #记录从库复制的慢查询,作为从库时生效,从库复制中如果有慢查询也将被记录
## 复制配置选项
server-id=1 #MySQL服务唯一标识
log-bin=mysql-bin #开启二进制日志,默认位置是datadir数据目录
log-bin-index=mysql-bin.index #binlog索引文件
binlog_format=MIXED #binlog日志格式,分三种:STATEMENT、ROW或MIXED,MySQL 5.7.7之前默认为STATEMENT,之后默认为ROW
binlog_cache_size=1M #binlog缓存大小,默认32KB
max_binlog_cache_size=1G #binlog最大缓存大小,推荐最大值为4GB
max_binlog_size=256M #binlog最大文件大小,最小值为4096字节,最大值和默认值为1GB
expire_logs_days=7 #binlog过期天数,默认为0不自动删除
log_slave_updates=ON #binlog级联复制
sync_binlog=1 #binlog同步频率,0为禁用同步(最佳性能,但可能丢失事务),为1开启同步(影响性能,但最安全不会丢失任何事务),为N操作N次事务后同步1次
relay_log=relay-bin #relaylog文件路径,默认位置是datadir数据目录
relay_log_index=relay-log.index #relaylog索引文件
max_relay_log_size=256M #relaylog最大文件大小
relay_log_purge=ON #中继日志自动清除,默认值为1(ON)
relay_log_recovery=ON #中继日志自动恢复
auto_increment_offset=1 #自增值偏移量
auto_increment_increment=1 #自增值自增量
slave_net_timeout=60 #从机连接超时时间
replicate-wild-ignore-table=mysql.% #复制时忽略的数据库表,告诉从线程不要复制到与给定通配符模式匹配的表
skip-slave-start #跳过Slave启动,Slave复制进程不随MySQL启动而启动
## 其他配置选项
#memlock=ON #开启内存锁,此选项生效需系统支持mlockall()调用,将mysqld进程锁定在内存中,防止遇到操作系统导致mysqld交换到磁盘的问题
[mysqldump] #mysqldump数据库备份工具
quick #强制mysqldump从服务器查询取得记录直接输出,而不是取得所有记录后将它们缓存到内存中
max_allowed_packet=16M #最大传输数据字节,使用mysqldump工具备份数据库时,某表过大会导致备份失败,需要增大该值(大>于表大小即可)
[myisamchk] #使用myisamchk实用程序可以用来获得有关你的数据库表的统计信息或检查、修复、分区 MySQ安装 的第 7 页 
[myisamchk] #使用myisamchk实用程序可以用来获得有关你的数据库表的统计信息或检查、修复、优化他们
key_buffer_size=32M #索引缓冲区大小
myisam_sort_buffer_size=8M #排序缓冲区大小
read_buffer_size=4M #读取缓区冲大小
write_buffer_size=4M #写入缓冲区大小

3、初始化: bin/mysqld --defaults-file=/usr/local/mysql/etc/my.cnf --initialize --user=mysql

配置环境变量

  1. vim /etc/profile
    1. export MYSQL_HOME=/usr/local/mysql
    2. export PATH=$MYSQL_HOME/bin:$PATH
  2. 刷新文件:source /etc/profile
  3. 复制配置文件到系统服务配置 cp support-files/mysql.server /etc/init.d/mysql
  4. 重新加载系统服务配置 systemctl daemon-reload
  5. 启动mysql服务 systemctl start mysql
1.3、yum安装mysql
wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum -y install mysql57-community-release-el7-11.noarch.rpm
yum -y install mysql-server  --nogpgcheck

2、导入导出

导出数据

  1. 导出所有数据库

    mysqldump -u root -p1234.Com -A > all.sql

  2. 导出某个数据库

    mysqldupm -u root -p1234.Com temp > temp.sql

  3. 导出单张表

    mysqldump -u root -p1234.Com temp tab_stu > student.sql

  4. 导出数据库表结构

    mysqldump -d temp > desc.sql

  5. 导出数据库数值

    mysqldump -t temp > value.sql

  6. 导出数据库(自带创建数据库)

    mysqldump -B temp > temp.sql


导入数据

  1. 导入所有数据库

    mysql -uroot -p1234.Com < all.sql

  2. 导入数据库

    mysql -uroot -p1234.Com < temp.sql

    在导入数据库之前需要手动创建数据库

  3. 在数据库中导入数据库表

    source /usr/local/mysql/data/temp.sql

3、备份

冷备份
  1. 通过操作 mysql/data 目录下的文件实现冷备份

    # 压缩所有文件
    tar -zcf backups *
    
    # 解压所有文件
    tar -zxf /backups
    
  2. 通过 source 实现导入操作

    # 导出文件
    mysqldump -uroot -p1234.Com temp stu > stu.sql
    # 进入数据库导入表格文件
    source /usr/local/mysql/data/stu.sql
    
增量备份

什么是增量备份?

​ mysql没有提供直接的增量备份方法,但是可以通过mysql二进制日志间接实现增量备份。二进制日志对备份的意义如下

  1. 二进制日志保存了所有更新或者可能更新数据库的操作
  2. 二进制日志在启动mysql服务器后开始记录,并在文件达到所设大小或者是收到flush logs 命令后重新创建新的日志文件
  3. 只需定时执行flush logs方法重新创建新的日志,生成二进制文件序列,并及时把这些文件保存到一个安全的地方即完成了一个时间段的增量备份

增量备份优点

  1. 优点:没有重复的数据,辈份量不大,时间短。
  2. 缺点:需要建立在上次 完全备份之后 所有的增量才能恢复

增量备份相关指令

  1. 临时关闭二进制文件:set SQL_LOG_BIN=0
  2. 查看二进制文件:mysqlbinlog mysql-bin.000001
  3. 查看二进制文件状态:show variables like "log_bin"
  4. 恢复增量数据:mysqlbinlog mysql-in.00003 | mysql -uroot -p
  5. 刷新生成增量文件:mysqlamdin -u -p flush-logs
  6. 清空日志文件:reset master
  • 案例:只恢复数值4的数据

    mysqlbinlog --start-position='304' --stop-position='411' mysql-bin.00008 | mysql -uroot -p1234.Com
    

2、主从复制

原理

  1. I/O线程:Slave将Master的Binary log(二进制日志)复制到其Relay log(中继日志)。首先Slave开始一个工作进程——I/O线程,开始二进制日志转储过程。从Master的二进制日志中读取事件,如果已经跟上Master,它就会睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志;
  2. SQL线程:SQL线程从中继日志中读取事件,使其与Master中的数据一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

操作

主表

# 关闭防火墙
systemctl stop firewall

# 修改mysql配置文件my.cnf
log-bin=mysql-bin # 启动二进制文件
server-id=1	      # 服务器唯一表示

# 重启服务
systemctl restart mysql

# 创建数据同步的用户并授权
GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identified by 'Root@123456';

# 刷新策略
flush privileges;

# 登录mysql数据库,查看master同步状态
show master status;

从库

# 修改数据库配置文件my.cnf
server-id=2 # 服务器唯一ID

# 重启服务
systemctl restart mysql

# 登录数据库,设置主库信息

change master to master_host='192.168.227.50',master_user='root',master_password='1234.Com',master_log_file='mysql-bin.000018',master_log_pos=1021;


start slave;

出现的问题

  1. 出现了 “Slave_IO_Running:Connection”

在主表的服务器中的iptables在作怪

  1. 出现了 “Slave_IO_Running:No”

原因:因为从表的服务器是拷贝的所以两台msyql的uuid是一样的
操作:找到/usr/local/mysql/data/auto.cnf文件修改

3、主从从

主从从关系图

主服务器

server-id=1		# 数据库唯一表示
log-bin=mysql-bin	# 日志文件名

中继代理服务器

server-id=2
log-bin=mysql-bin
log-slave-updates=1
default-storage-engine=blackhole

从服务器

server-id=3

4、读写分离

原理

一般系统中会出现读操作比写操作多,单个数据库实例在写入的时候会影响读取性能,这是做读写分离的原因。

  1. 读写分离是基于主从复制来实现的。在实际的应用环境中,肯定是读操作多,我们基于主从复制的读写分离配置,就是让一个主库专门用来做数据的修改
  2. 主库用来数据更新(写操作),从库用来做读操作,这样一来可以很好的分摊读写的压力,对于后端服务的并发处理能力有很大的提高,当主库挂了以后,可以把指定的从库变成主库。

当主节点宕机以后又重启了,会自动给加入到队列中,会继续充当主节点的写操作,因为MySQL5.5之后主从复制默认支持半同步的策略

image-20230523151831536

1.什么是数据库中间件

  • 中间件:是一类连接软件组件和应用的计算机软件,以便软件间的通信

  • 数据库中间件:连接java应用程序和数据库

2.为什么用Mycat?

  • java与数据库紧耦合(防止java或者是数据库宕机)

  • 高并发对数据库的压力(减轻服务器的压力)

  • 读写请求数据不一致(减轻服务器压力)

3.Mycat能干什么?

  • 可以分库分表
  • 可以读写分离
  • java不需要配置多个数据源,直接交给mycat就可以了

操作

  1. 安装JDK8

    因为启动 mycat 需要依赖于jdk8

    1. 下载jdk-8u131-linux-x64.tar.gz文件

    2. 新建/usr/java文件夹,将jdk-8u131-linux-x64.tar.gz放到该文件夹中,并解压到当前目录下

    3. 配置环境变量 在/etc/profile

      JAVA_HOME=/usr/java/jdk1.8.0_131 
      PATH=$JAVA_HOME/bin:$PATH 
      CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar 
      export PATH JAVA_HOME CLASSPATH
      
    4. 刷新配置文件:source /etc/profile

  2. 安装Mycat

    Mycat是数据库中间件,所谓中间件,是一类连接软件组件和应用的计算机软件,以便软件各组件之间的通信。

    ​ 例如 tomcat,web的中间件。而数据库中间件是连接Java应用程序和数据库中间的软件。

    img
    1. 文件下载

      wget http://dl.mycat.org.cn/1.6.7.6/20220518163531/Mycat-server-1.6.7.6-release-20220518222606-linux.tar.gz
      
    2. 添加环境变量

      MYCAT_HOME=/usr/local/mycat 
      PATH=$MYCAT_HOME/bin:$PATH
      
    3. 修改 /etc/hosts 文件

    4. 修改mycat用户账号和授权信息 /conf/server.xml

      <!DOCTYPE mycat:server SYSTEM "server.dtd">
      <mycat:server xmlns:mycat="http://io.mycat/">
              <system>
                      <!-- 系统属性,可以查看mycat文档 -->
                      <property name="defaultSqlParser">druidparser</property>
                      <property name="charset">utf8</property>
              </system>
              <!-- 配置用户信息 -->
              <user name="root">
                      <property name="password">1234.Com</property>
                      <property name="schemas">aa</property>
              </user>
      </mycat:server>
      
    5. 编辑mycat的配置文件/conf/schema.xml

      <?xml version="1.0"?>
      <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
      <mycat:schema xmlns:mycat="http://io.mycat/">
      
              <!-- 定义MyCat的逻辑库 dataNode代表映射真实数据节点 -->
              <schema name="aa" checkSQLschema="false" sqlMaxLimit="100" dataNode="emsNode"></schema>
      
              <!-- 定义MyCat的数据节点 name:名字必须和dataNode数值一致 dataHost:映射真实主机 database:映射真实的数据库 -->
              <dataNode name="emsNode" dataHost="emsHost" database="temp" />
      
              <!-- 定义数据注意 name:名字必须和dataHost保持一致 -->
              <dataHost name="emsHost" maxCon="1000" minCon="10" balance="1" writeType="0"  dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
                      <!-- 心跳检查 -->
                      <heartbeat>select user()</heartbeat>
                      <!-- 写节点 -->
                      <writeHost host="master" url="192.168.227.50:3306" user="root" password="1234.Com">
                              <!-- 从节点 -->
                              <readHost host="slave" url="192.168.227.60:3306" user="root" password="1234.Com" />
                      </writeHost>
              </dataHost>
      
      </mycat:schema>
      
    6. 启动服务(进入bin目录):./mycat console

遇到的问题

  1. mycat正常启启动,会遇到 show tables 一直卡顿的状态

那是因为没有远程访问的权限此时我们应该

  • 授权指令:grant all privileges on . to ‘root’@“%” identified by ‘1234.Com’
  1. 为什么已经启动了却没有读写分离的效果

    1. balance=“0”, 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
    2. balance=“1”,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
    3. balance=“2”,所有读操作都随机的在writeHost、readhost上分发。
    4. balance=“3”,所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
    # 找到schema.xml文件修改参数
    <dataHost balance="1">
    

5、MHA

  1. MHA(MasterHigh Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决MySQL 单点的问题。
  2. MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可用。

原理

工作原理
  1. 主备切换:MHA Manager可以独立部署在一台独立的机器上管理多个Master-Slave集群,也可以部署在一台Slave上。当 Master 出现故障是,它可以自动将最新数据的Slave 提升为新的 Master,然后将所有其他的 Slave 重新指向新的 Master。
  2. 心跳监测:MHA通过在主备服务器之间建立心跳连接进行实时监测。主服务器会定期发送心跳信号到备服务器,如果备服务器在一定时间内没有接收到心跳信号,就会触发主备切换。
  3. 数据同步:MHA使用MySQL的复制功能实现数据的实时同步。当主服务器上发生写操作时,其修改的数据会通过二进制日志(binlog)传输到备服务器上,保持数据的一致性。
  4. 故障检测和恢复:MHA能够检测到主服务器的故障,并自动执行故障恢复过程。一旦检测到主服务器故障,MHA会协调备服务器中的某个节点成为新的主服务器,并更新相关配置信息,以确保应用程序可以正确地连接到新的主服务器。

MHA manager管理者所有的master、slave,对所有节点做心跳检测,如果服务器一定时间内没有收到心跳信号,会认真master宕机,则就会出发主备切换的动作,再通过mysql的数据同步机制实现数据的实时更新。

隐患
img

操作

  1. 准备三台虚拟机(一主一从一MHA)

  2. 一主一从同时装上node软件包

    # 两台数据库服务器
    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
    yum -y install perl-DBD-mysql
    rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
    
  3. MHA控制端(从)

    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
    yum -y install perl-DBD-mysql perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager
    rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
    rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
    
  4. 两台数据库服务器通过rpm安装数据库,并修改密码

    # 上传数据库rpm软件包
    
    # 下载
    rpm -ivh mysql-community-common-5.7.37-1.el7.x86_64.rpm
    rpm -ivh mysql-community-libs-5.7.37-1.el7.x86_64.rpm
    rpm -ivh mysql-community-client-5.7.37-1.el7.x86_64.rpm
    rpm -ivh mysql-community-server-5.7.37-1.el7.x86_64.rpm
    
  5. 修改数据库配置文件

    vim /etc/my.cnf
    server-id=1
    log-bin=mysql-bin
    relay-log=relay-log-bin
    relay-log-purge=0
    
  6. 关闭防火墙

    # 关闭防火墙
    systemctl stop firewalld
    # 关闭iptables
    service iptables stop
    
  7. 配置主从信息,并配置授权信息

    【主】
    grant replication slave on *.* to 'mha'@'192.168.0.%' identified by '1234.Com';
    grant all on *.* to 'mha'@'192.168.0.%' identified by '1234.Com';
    flush privileges;
    show master status\G
    
    【从】
    grant replication slave on *.* to 'mha'@'192.168.0.%' identified by '1234.Com';
    grant all on *.* to 'mha'@'192.168.0.%' identified by '1234.Com';
    flush privileges;
    change master to master_host='192.168.227.148',master_user='root',master_password='1234.Com',master_log_file='mysql-bin.000001',master_log_pos=154;
    start slave;
    show slave status\G;
    
  8. 免密登录

    ssh-keygen
    ssh-copy-id 用户@ IP
    
  9. MNA服务器配置 etc/mha/ma.cnf 配置文件

    mkdir /etc/mha
    vim /etc/mha/mha.cnf
    
    [server default]
    user=mha
    password=1234.Com
    ssh_user=root
    repl_user=mha
    repl_password=1234.Com
    ping_interval=1
    master_ip_failover_script=/usr/bin/master_ip_failover
    manager_workdir=/var/mha
    manager_log=/var/mha/manager.log
    [server1]
    hostname=192.168.0.161
    ssh_port=22
    master_binlog_dir=/var/lib/mysql
    [server2]
    hostname=192.168.0.13
    ssh_port=22
    candidate_master=1
    master_binlog_dir=/var/lib/mysql
    [server3]
    hostname=192.168.0.56
    ssh_port=22
    no_master=1
    master_binlog_dir=/var/lib/mysql
    
  10. 编辑 /usr/bin/master_ip_failover 文件

    ivim /usr/bin/master_ip_failover
    
    #!/usr/bin/env perl
    use strict;
    use warnings FATAL => 'all';
    use Getopt::Long;
    my (
     $command, $ssh_user, $orig_master_host, $orig_master_ip,
     $orig_master_port, $new_master_host, $new_master_ip, $new_master_port
    );
    my $vip = '192.168.0.252/24'; 
    my $key = "1";
    my $ssh_start_vip = "/usr/sbin/ifconfig ens33:$key $vip";
    my $ssh_stop_vip = "/usr/sbin/ifconfig ens33:$key down";
    GetOptions(
     'command=s' => \$command,
     'ssh_user=s' => \$ssh_user,
     'orig_master_host=s' => \$orig_master_host,
     'orig_master_ip=s' => \$orig_master_ip,
     'orig_master_port=i' => \$orig_master_port,
     'new_master_host=s' => \$new_master_host,
     'new_master_ip=s' => \$new_master_ip,
     'new_master_port=i' => \$new_master_port,
    );
    exit &main();
    sub main {
     print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
     if ( $command eq "stop" || $command eq "stopssh" ) {
     my $exit_code = 1;
     eval {
     print "Disabling the VIP on old master: $orig_master_host \n";
     &stop_vip();
     $exit_code = 0;
     };
     if ($@) {
     warn "Got Error: $@\n";
     exit $exit_code;
     }
     exit $exit_code;
     }
     elsif ( $command eq "start" ) {
     my $exit_code = 10;
     eval {
     print "Enabling the VIP - $vip on the new master - $new_master_host \n";
     &start_vip();
     $exit_code = 0;
     };
     if ($@) {
     warn $@;
     exit $exit_code;
     }
     exit $exit_code;
     }
     elsif ( $command eq "status" ) {
     print "Checking the Status of the script.. OK \n";
     `ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
     exit 0;
     }
     else {
     &usage();
     exit 1;
     }
    }
    sub start_vip() {
     `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
    }
    sub stop_vip() {
     `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
    }
    sub usage {
     print
     "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --
    orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
    }
    
  11. 检查

    chmod a+x /usr/bin/master_ip_failover #赋予可执行权限
    masterha_check_repl --conf=/etc/mha/mha.cnf #检测节点之间的主从复制是否正常连接 
    masterha_check_ssh --conf=/etc/mha/mha.cnf #检测节点之间ssh是否正常连接
    

验证

  1. Mysql主有漂移IP,Mysqls从无飘逸IP,
  2. Mysql主停止Mysql:systemctl stop mysqld
  3. MHA:masterha_manager --conf=/etc/mha/mha.cnf #启动服务会阻塞终端
  4. Mysql从1:获得飘逸IP,成为新的主
  5. 创建新的数据库
  6. Mysql从2:数据库同步成功

6、分库分表

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拆分策略

垂直拆分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

水平拆分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • shardinlDBC:基于AOP原理,在应用程序中对本地执行的SOL进行拦截,解析、改写、路由处理。需要自行编码配置实现,只支持java语言,性能较高。
  • MyCat:数据库分库分表中间件,不用调整代码即实现分库分表,支持多种语言,性能不及shardingJDBC。

安装

JDK安装
tar -xvf jdk-8u144-linux-x64.tar.gz -C /use/local/java

修改文件

vi /etc/profile
JAVA_HOME=/usr/local/java
PATH=$PATH:$JAVA_HOME/bin

刷新配置

source /etc/profile
MyCat

水平分表

  1. 文件下载

    wget http://dl.mycat.org.cn/1.6.7.6/20220518163531/Mycat-server-1.6.7.6-release-20220518222606-linux.tar.gz
    
  2. 添加环境变量

    MYCAT_HOME=/usr/local/mycat 
    PATH=$MYCAT_HOME/bin:$PATH
    
  3. 修改 /etc/hosts 文件

  4. 修改mycat用户账号和授权信息 /conf/server.xml

            <user name="root" defaultAccount="true">
                    <property name="password">1234.Com</property>
                    <property name="schemas">DB01</property>
    
                    <!-- 表级 DML 权限设置 -->
                    <!--            
                    <privileges check="false">
                            <schema name="TESTDB" dml="0110" >
                                    <table name="tb01" dml="0000"></table>
                                    <table name="tb02" dml="1111"></table>
                            </schema>
                    </privileges>           
                     -->
            </user>
    
            <user name="user">
                    <property name="password">1234.Com</property>
                    <property name="schemas">DB01</property>
                    <property name="readOnly">true</property>
            </user>
    
  5. 编辑mycat的配置文件/conf/schema.xml

    <mycat:schema xmlns:mycat="http://io.mycat/">    
            # 需要修改的地方
            # rule设置的是分片规则
            <schema name="DB01" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
                    <table name="order" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-intfile"  />
            </schema>
    
    		# 需要修改的地方
            <dataNode name="dn1" dataHost="localhost1" database="db01" />
            <dataNode name="dn2" dataHost="localhost2" database="db01" />
            <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
                    <writeHost host="hostM1" url="jdbc:mysql://192.168.227.20:3306" user="root"
                                       password="1234.Com">
                    </writeHost>
            </dataHost>
            <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
                              writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                    <heartbeat>select user()</heartbeat>
                    <writeHost host="hostM1" url="jdbc:mysql://192.168.227.21:3306" user="root"
                                       password="1234.Com">
                    </writeHost>
            </dataHost>
    </mycat:schema>
    
  6. 启动服务(进入bin目录):

    # 启动
    bin/mycat start
    # 停止
    bin/mycat stop
    # 占用端口8066端口
    [root@master mycat]# netstat -anput | grep java
    tcp6    0   0 :::9066   :::*      LISTEN      9749/java
    
  7. 测试数据库连接

    mysql -uroot -p1234.Com -P8066 -h 192.168.227.20
    

目录介绍

  • bin:存放可执行文件,用于启动停止mycat
  • conf:存放mycat的配置文件
  • lib:存放mycat的项目依赖包(jar)
  • logs:存放mycat的日志文件

MyCat配置

schema.xml

schema标签

  • name:指定自定义的逻辑库名
  • checksOLschema: 在SOL语句操作时指定了数据库名称,执行时是否自动去除; true: 自动去除,fase: 不自动去除
  • sqlMaxLimit: 如果未指定limit进行查询,列表查询模式查询多少条记录

table标签

  • name: 定义逻辑表表名,在该逻辑库下唯一
  • dataNode: 定义逻辑表所属的dataNode,该属性需要与dataNode标签中name对应; 多个
  • dataNode逗号分隔rule: 分片规则的名字,分片规则名字是在rule.xml中定义的
  • primaryKey: 逻辑表对应真实表的主键
  • type: 逻辑表的类型,目前逻辑表只有全局表和普通表,如果未配置,就是普通表;全局表,配置为 global

dataNode标签

  • name: 定义数据节点名称
  • dataHost: 数据库实例主机名称,引用自 dataHost 标签中name属性
  • database: 定义分片所属数据库

dataHost标签

  • name: 唯一标识,供上层标签使用
  • maxCon/minCon: 最大连接数/最小连接数
  • balance: 负载均衡策略,取值 0,1,2,3writeType: 写操作分发方式 (0: 写操作转发到第一个
  • writeHost,第一个挂了,切换到第二个,1: 写操作随分发到配置的writeHost)dbDriver: 数据库驱动,支持 native、jdbc
rule.xml

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

server.xml

server配置文件中包含了mycat的系统配置信息,主要有两个重要的标签:system、user。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

user标签

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MyCat分片

垂直分库拆分

在业务系统中,涉及以下表结构,但是由于用户与订单每天都会产生大量的数据,单台服务器的数据存储及处理能力是有限的,可以对数据库表进行拆分原有的数据库表如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
准备工作:在三台实体数据库中创建好 shopping

修改配置schema.xml配置文件

<schema name="SHOPPING" checkSQLschema="true" sqlMaxLimit="100">
	<table name="tb_goods_base" dataNode="dn1" primaryKey="id" />
	<table name="tb_goods_brand" dataNode="dn1" primaryKey="id" />
    <table name="tb_goods_cat" dataNode="dn1" primaryKey="id" />
    <table name="tb_goods_desc" dataNode="dn1" primaryKey="id" />
    <table name="tb_goods_item" dataNode="dn1" primaryKey="id" />
    
    <table name="tb_order_item" dataNode="dn2" primaryKey="id" />
    <table name="tb_order_master" dataNode="dn2" primaryKey="id" />
    <table name="tb_order_pay_log" dataNode="dn2" primaryKey="id" />
    
    <table name="tb_user" dataNode="dn3" primaryKey="id" />
    <table name="tb_user_address" dataNode="dn3" primaryKey="id" />
    <table name="tb_areas_provinces" dataNode="dn3" primaryKey="id" />
    <table name="tb_areas_city" dataNode="dn3" primaryKey="id" />
    <table name="tb_areas_region" dataNode="dn3" primaryKey="id" />
</schema>

<dataNode name="dn1" dataHost="dhost1" database="shopping" />
<dataNode name="dn2" dataHost="dhost2" database="shopping" />
<dataNode name="dn3" dataHost="dhost3" database="shopping" />

修改server.xml配置文件

        <user name="root" defaultAccount="true">
                <property name="password">1234.Com</property>
                <property name="schemas">SHOPPING</property>
        <user name="user">
                <property name="password">1234.Com</property>
                <property name="schemas">SHOPPING</property>
                <property name="readOnly">true</property>
        </user>

在测试阶段的时候我们会发现,通过多表联查会出现报错的情况。

需要将字典表设置成全局表,也就是说三个数据库中都有改表信息

<table name="tb_user" dataNode="dn1,dn2,dn3" primaryKey="id" type="global" />
<table name="tb_user_address" dataNode="dn1,dn2,dn3" primaryKey="id" type="global" />
<table name="tb_areas_provinces" dataNode="dn1,dn2,dn3" primaryKey="id" type="global" />
<table name="tb_areas_city" dataNode="dn1,dn2,dn3" primaryKey="id" type="global" />
<table name="tb_areas_region" dataNode="dn1,dn2,dn3" primaryKey="id" type="global" />
水平分表拆分

在业务系统中,有一张表(日志表,业务系统每天都会产生大量的日志数据,单台服务器的数据存储及处理能力是有限的,可以对数据库表进行拆分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
准备工作:给三台实体数据库创建itcast

创建逻辑库

<schema name="ITCAST" checkSQLschema="true" sqlMaxLimit="100">
	替换分片规则
	<table name="tb_log" dataNode="dn4,dn5,dn6" primaryKey="id" rule="mod-log"/>
</schema>

<dataNode name="dn4" dataHost="dhost1" database="itcast" />
<dataNode name="dn5" dataHost="dhost2" database="itcast" />
<dataNode name="dn6" dataHost="dhost3" database="itcast" />

添加用户权限

<user name="root" defaultAccount="true">
        <property name="password">1234.Com</property>
        <property name="schemas">SHOPPING,ITCAST</property>
<user name="user">
        <property name="password">1234.Com</property>
        <property name="schemas">SHOPPING</property>
        <property name="readOnly">true</property>
</user>

需要在mycat数据库中创建tb_log

7、性能分析工具的使用

1、数据库服务器的优化步骤

在这里插入图片描述

2、查看系统性能参数

在MySQL中,可以使用 SHOW STATUS 语句查询一些MySQL数据库服务器的 性能参数执行频率

SHOW STATUS语句语法如下:

SHOW [GLOBAL|SESSION] STATUS LIKE '参数';

一些常用的性能参数如下:

  • connections:连接MySQL服务器的次数。
  • Uptime:MySQL服务器的上线时间。
  • Slow_queries:慢查询的次数。
  • Innodb_rows_read:Select查询返回的行数
  • Innodb_rows_inserted:执行INSERT操作插入的行数
  • Innodb_rows_updated:执行UPDATE操作更新的行数
  • Innodb_rows_deleted:执行DELETE操作删除的行数
  • Com_select:查询操作的次数。
  • Com_insert:插入操作的次数。对于批量插入的 INSERT 操作,只累加一次。
  • Com_update:更新操作的次数。
  • Com_delete:删除操作的次数

3. 定位执行慢的 SQL:慢查询日志

3.1 开启慢查询日志参数

1. 开启slow_query_log

# 开启慢查询日志
mysql > set global slow_query_log='ON';

然后我们再来查看下慢查询日志是否开启,以及慢查询日志文件的位置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传你能看到这时慢查询分析已经开启,同时文件保存在/var/lib/mysql/atguigu02-slow.log 文件中。

2. 修改long_query_time阈值

接下来我们来看下慢查询的时间阈值设置,使用如下命令:

mysql > show variables like '%long_query_time%';

这里如果我们想把时间缩短,比如设置为 1 秒,可以这样设置

#测试发现:设置global的方式对当前session的long_query_time失效。对新连接的客户端有效。所以可以一并执行下述语句
mysql > set global long_query_time = 1;
mysql> show global variables like '%long_query_time%';

mysql> set long_query_time=1;
mysql> show variables like '%long_query_time%';

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


3.2 查看慢查询数目

查询当前系统中有多少条慢查询记录

SHOW GLOBAL STATUS LIKE '%Slow_queries%';

3.4 测试及分析

1.测试

mysql> SELECT * FROM student WHERE stuno = 3455655;
+---------+---------+--------+------+---------+
| id | stuno | name | age | classId |
+---------+---------+--------+------+---------+
| 3523633 | 3455655 | oQmLUr | 19 | 39 |
+---------+---------+--------+------+---------+
1 row in set (2.09 sec)
mysql> SELECT * FROM student WHERE name = 'oQmLUr';
+---------+---------+--------+------+---------+
| id | stuno | name | age | classId |
+---------+---------+--------+------+---------+
| 1154002 | 1243200 | OQMlUR | 266 | 28 |
| 1405708 | 1437740 | OQMlUR | 245 | 439 |
| 1748070 | 1680092 | OQMlUR | 240 | 414 |
| 2119892 | 2051914 | oQmLUr | 17 | 32 |
| 2893154 | 2825176 | OQMlUR | 245 | 435 |
| 3523633 | 3455655 | oQmLUr | 19 | 39 |
+---------+---------+--------+------+---------+
6 rows in set (2.39 sec)

从上面的结果可以看出来,查询学生编号为“3455655”的学生信息花费时间为2.09秒。查询学生姓名为“oQmLUr”的学生信息花费时间为2.39秒。已经达到了秒的数量级,说明目前查询效率是比较低的,下面的小节我们分析一下原因。

2. 分析

show status like 'slow_queries';

4.5 **慢查询日志分析工具:**mysqldumpslow

在生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具mysqldumpslow

查看mysqldumpslow的帮助信息

mysqldumpslow --help

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

mysqldumpslow 命令的具体参数如下:

  • -a: 不将数字抽象成N,字符串抽象成S

  • -s: 是表示按照何种方式排序:

    • c: 访问次数

    • l: 锁定时间r: 返回记录

    • t: 查询时间

    • al:平均锁定时间

    • ar:平均返回记录数

    • at:平均查询时间 (默认方式)

    • ac:平均查询次数

  • -t: 即为返回前面多少条的数据;

  • -g: 后边搭配一个正则匹配模式,大小写不敏感的;

举例:我们想要按照查询时间排序,查看前五条 SQL 语句,这样写即可:

工作常用参考:

#得到返回记录集最多的10个SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log
#得到访问次数最多的10个SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/atguigu-slow.log
#得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/atguigu-slow.log
#另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log | more

4.6 关闭慢查询日志

MySQL服务器停止慢查询日志功能有两种方法:

方式1:永久性方式

[mysqld]
slow_query_log=OFF

或者,把slow_query_log一项注释掉 或 删除

[mysqld]
#slow_query_log =OFF

重启MySQL服务,执行如下语句查询慢日志功能。

SHOW VARIABLES LIKE '%slow%'; #查询慢查询日志所在目录
SHOW VARIABLES LIKE '%long_query_time%'; #查询超时时长

方式2:临时性方式

使用SET语句来设置。

(1)停止MySQL慢查询日志功能,具体SQL语句如下。

SET GLOBAL slow_query_log=off;

(2)重启MySQL服务,使用SHOW语句查询慢查询日志功能信息,具体SQL语句如下

mysqldumpslow -s t -t 5 /var/lib/mysql/atguigu01-slow.log
[root@bogon ~]# mysqldumpslow -s t -t 5 /var/lib/mysql/atguigu01-slow.log
Reading mysql slow query log from /var/lib/mysql/atguigu01-slow.log
Count: 1 Time=2.39s (2s) Lock=0.00s (0s) Rows=13.0 (13), root[root]@localhost
	SELECT * FROM student WHERE name = 'S'
Count: 1 Time=2.09s (2s) Lock=0.00s (0s) Rows=2.0 (2), root[root]@localhost
	SELECT * FROM student WHERE stuno = N
Died at /usr/bin/mysqldumpslow line 162, <> chunk 2.

**5、 **查看 SQL **执行成本:**SHOW PROFILE

mysql > show variables like 'profiling';
image-20230704165752757

通过设置 profiling='ON’ 来开启 show profile:

mysql > set profiling = 'ON';
image-20230704165808261

然后执行相关的查询语句。接着看下当前会话都有哪些 profiles,使用下面这条命令:

mysql > show profiles;
image-20230704165823338

你能看到当前会话一共有 2 个查询。如果我们想要查看最近一次查询的开销,可以使用:

mysql > show profile;
image-20230704165845635
mysql> show profile cpu,block io for query 2;
image-20230704173803595

show profile的常用查询参数:

  • ① ALL:显示所有的开销信息。
  • ② BLOCK IO:显示块IO开销。
  • ③ CONTEXT SWITCHES:上下文切换开销。
  • ④ CPU:显示CPU开销信息。
  • ⑤ IPC:显示发送和接收开销信息。
  • ⑥ MEMORY:显示内存开销信息。
  • ⑦ PAGE FAULTS:显示页面错误开销信息。
  • ⑧ SOURCE:显示和Source_function,Source_file,Source_line相关的开销信息。
  • ⑨ SWAPS:显示交换次数开销信息。

8、面试题

ACID特性(原一隔持)

InnoDB支持事务,它是基于表级锁定的存储引擎,有以下几个特性:

  1. 原子性(Atomicity):指一个事务中的所有操作要么全部执行成功,要么全部失败回滚。如果一个事务中的任何操作失败,系统将回滚所有已执行的操作,恢复到事务开始前的状态。
  2. 一致性(Consistency):指事务在执行前后都必须满足数据库的完整性约束。这意味着一个事务将数据库从一种有效状态转换为另一种有效状态,而不会破坏数据的完整性。
  3. 隔离性(Isolation):指并发执行的事务之间应该相互隔离,使它们看起来像是按顺序执行的,避免了并发执行可能引发的问题,如脏读(Dirty Read)、不可重复读(Non-repeatable Read)和幻读(Phantom Read)。
  4. 持久性(Durability):指一旦事务提交成功,对数据库的改变将永久保存,即使系统发生故障也不会丢失。系统将通过将事务的日志记录持久保存来保证数据的持久性。

Myisam VS Innodb(锁事外崩)

  1. 事务支持:MyISAM不支持事务,它是基于表级锁定的存储引擎,没有ACID特性。而InnoDB支持事务,使用行级锁定,可以满足高并发环境下的并发控制需求,具备ACID特性。
  2. 锁定机制:MyISAM使用表级锁定,当一个线程对表进行读写操作时,其他线程无法同时对该表进行写操作,会出现锁定冲突。InnoDB使用行级锁定,不同的线程可以同时对表中的不同行进行读写操作,提供了更好的并发性能。
  3. 外键约束:MyISAM不支持外键约束,而InnoDB支持外键约束,可以维护表与表之间的关系完整性。
  4. 索引方式:MyISAM使用B+树索引结构,适合于读操作频繁的场景,但对于写操作较多的场景性能较低。InnoDB也使用B+树索引结构,但它的主键索引和数据是紧密集成的,更适合于同时进行读写操作的场景。
  5. 数据缓存:MyISAM将索引和数据分别缓存在内存中,缓存效果较好,但对于大量写操作可能造成数据不一致。InnoDB使用统一的缓冲池管理索引和数据,可以提供更好的读写性能和数据一致性。
  6. 崩溃恢复:MyISAM发生崩溃时,很难恢复数据,可能会有数据丢失。InnoDB具备崩溃恢复能力,通过事务日志(redo log)实现故障恢复,可以尽可能地保证数据的持久性。
  7. 使用场景:myisam更适合读多写少的场景。

事务隔离级别

脏写( Dirty Write

如果一个事务修改了另一个未提交事务修改过的数据,那就意味着发生了脏写

发生时间序号SessionASessionB
BEGIN;
BEGIN;
UPDATE student SET name=‘张三’
WHERE student no = 1
UPDATE student SET name=‘李四’
WHERE student no = 1
commit
name=‘李四’

举个例子来说明脏写现象:假设有两个并发的事务 A 和事务 B,它们同时对同一行数据进行修改。事务 A 修改了该行数据的某些字段,并且尚未提交。与此同时,事务 B 也修改了同一行数据的另外的字段,并且提交了修改。结果是事务 B 的修改已经永久保存,而事务 A 的修改却丢失了,因为它没有机会提交。

脏读( Dirty Read )

当一个事务读取了另一个未提交的事务,那就意味着发生了脏读

Session A和Session B各开启了一个事务,Session B中的事务先将studentno列为1的记录的name列更新为’张三’,然后Session A中的事务再去查询这条studentno为1的记录,如果读到列name的值为’张三’,而Session B中的事务稍后进行了回滚,那么Session A中的事务相当于读到了一个不存在的数据,这种现象就称之为 脏读

不可重复读( Non**-**Repeatable Read )

同一查询在同一事务中多次进行,由于其他的事务所作的修改或删除,每次返回不同的结果集

我们在Session B中提交了几个 隐式事务 (注意是隐式事务,意味着语句结束事务就提交了),这些事务都修改了studentno列为1的记录的列name的值,每次事务提交之后,如果Session A中的事务都可以查看到最新的值,这种现象也被称之为 不可重复读

幻读( Phantom )

同一查询在同一事务中多次进行,由于其他的事务所作的插入,每次返回不同的结果集

Session A中的事务先根据条件 studentno > 0这个条件查询表student,得到了name列值为’张三’的记录;之后Session B中提交了一个 隐式事务 ,该事务向表student中插入了一条新记录;之后Session A中的事务再根据相同的条件 studentno > 0查询表student,得到的结果集中包含Session B中的事务新插入的那条记录,这种现象也被称之为 幻读 。我们把新插入的那些记录称之为 幻影记录

SQL中的四种隔离级别

上面介绍了几种并发事务执行过程中可能遇到的一些问题,这些问题有轻重缓急之分,我们给这些问题按照严重性来排一下序:

脏写 > 脏读 > 不可重复读 > 幻读
  • READ UNCOMMITTED :读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。不能避免脏读、不可重复读、幻读。
  • READ COMMITTED :读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读、幻读问题仍然存在。
  • REPEATABLE READ :可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍然存在。这是MySQL的默认隔离级别
  • SERIALIZABLE :可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下。能避免脏读、不可重复读和幻读。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

mysql优化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 选择合适的存储弓擎: InnoDB
  2. 保证从内存中读取数据。将数据保存在内存中
  3. 定期优化重建数据库
  4. 降低磁盘写入操作
  5. 提高磁盘读写速度
  6. 充分使用索引
  7. 分析查询日志和慢查询日志

优化MySQL的参数是提高数据库性能的重要步骤之一。下面是一些常见的MySQL参数优化建议:

  1. innodb_buffer_pool_size:这是InnoDB存储引擎使用的内存缓冲池的大小。根据你的服务器可用内存和数据集大小,适当调整该参数可以提高读取性能。
  2. innodb_flush_log_at_trx_commit :表示 何时将缓冲区的数据写入日志文件 ,并且将日志文件写入磁盘中。该参数对于innoDB引擎非常重要。该参数有3个值,分别为0、1和2。该参数的默认值为1。
    • 值为0时,表示 每秒1次 将数据写入日志文件并将日志文件写入磁盘。每个事务的commit并不会触发前面的任何操作。该模式速度最快,但不太安全,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失。
    • 值为 1 时,表示 每次提交事务时 将数据写入日志文件并将日志文件写入磁盘进行同步。该模式是最安全的,但也是最慢的一种方式。因为每次事务提交或事务外的指令都需要把日志写入(flush)硬盘。
    • 值为 2 时,表示 每次提交事务时 将数据写入日志文件,把日志文件刷到文件系统中去,但并不会立即刷写到磁盘, 而是交给操作系统自己处理。该模式速度较快,也比0安全,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。
  3. key_buffer_size:对于使用MyISAM存储引擎的表,key_buffer_size参数指定了索引缓冲区的大小。如果你的系统主要基于InnoDB,可以将该参数设置为一个较小的值或者设为0。
  4. query_cache_size:启用查询缓存可以加快查询速度,但在高并发环境下可能产生锁竞争。如果你的系统主要执行写操作,建议将该值设置为0。
  5. max_connections:该参数指定数据库允许的最大连接数。根据你的应用程序需求和硬件资源,设置适当的值以避免连接过多导致系统负载过高。
  6. tmp_table_sizemax_heap_table_size:这两个参数控制临时表的最大大小,如果你的应用经常使用临时表,适当调整这两个参数可以提高性能。
  7. innodb_file_per_table:对于使用InnoDB存储引擎的表,启用此选项可以让每个表有独立的表空间,提高性能和管理灵活性。
  8. innodb_log_file_size:该参数指定了InnoDB事务日志文件的大小。根据你的数据库负载和事务频率,适当调整该参数可以提高写入性能。
  9. back_log:参数是指MySQL服务器允许的最大等待连接请求队列长度。当有新的客户端连接请求到达服务器时,如果当前连接数达到了max_connections限制,MySQL会将这个新请求放到等待连接请求队列中。

除了上述参数,还有许多其他MySQL参数可以根据实际情况进行优化。关注并监测数据库性能,并根据需求进行调整是持续优化的关键。同时,确保在修改任何参数之前备份数据库,并且小心谨慎地进行测试和评估性能的变化。

二、Redis

1、原理

2、安装

tar -zxf redis-6.2.6.tar.gz -C /usr/src/
cd /usr/src/redis-6.2.6/
make && make install
redis-server & 启动redis数据库
redis-cli 进入redis数据库,默认进入本地的redis

3、基本指令

  1. 设置key:set [key] [value]

  2. 创建多个:mset key value key2 value2 key3 value3

  3. 删除:del key

  4. 查看:get key

  5. 查看多个:mget key1 key2 key3

  6. 切换数据库:select [index]

  7. 查看所有键:keys [options]

    1. 查看所有:keys *
    2. 模糊查询:keys k*
    3. 占位符:keys key?
  8. flush清除指令

    1. 清空所有数据库数据:flushall
    2. 清空当前数据库数据:flushdb

    flushall 清空数据库并执行持久化操作

    flushdb 清空数据库,但是不执行持久化操作

  9. save保存指令

    1. save
    2. bgsave

    SAVE 和 BGSAVE 都是 Redis 进行持久化操作的命令,但它们有以下几点不同:

    1. 执行方式:SAVE 是同步执行的命令,会在执行期间阻塞 Redis 服务器进程;而 BGSAVE 是异步执行的命令,会在后台执行,不会阻塞 Redis 服务器进程。
    2. 执行效率:因为 SAVE 是同步执行的命令,会在执行期间阻塞 Redis 服务器进程,所以它的执行效率比较低,尤其是在数据比较大的情况下。而 BGSAVE 是异步执行的命令,在后台执行,不会阻塞 Redis 服务器进程,所以它的执行效率比较高。
    3. 操作方式:SAVE 命令会将整个数据集保存到磁盘上,如果数据集比较大,保存操作会比较耗时,同时也会占用比较多的磁盘空间。而 BGSAVE 命令则是通过 fork 函数创建一个子进程来进行持久化操作,子进程将数据写入磁盘,完成后再通知主进程,所以 BGSAVE 的操作方式相比 SAVE 更加高效。
    4. 安全性:因为 SAVE 是同步执行的命令,会在执行期间阻塞 Redis 服务器进程,所以如果在 SAVE 执行期间 Redis 服务器进程异常退出,可能会导致数据丢失。而 BGSAVE 是异步执行的命令,在后台执行,不会阻塞 Redis 服务器进程,所以即使 Redis 服务器进程异常退出,也不会导致数据丢失。
  10. 查看key过期时间:ttl [key_name]

    1. -1:表示key存在但是没有设置生于生存时间
    2. -2:不存在,已经过期
  11. 设置key过期时间:expire [key_name] [time]

  12. 将健转到其他数据库:move [key_name] [database]

    1. 1:移动成功返回1
    2. 0:转移失败返回0

    标数据库中有相同的健同样也会转移失败

  13. 停止服务:shutdown

    1. 停止所有客户端
    2. 如果至少有一个保存点在等待,执行save命令
    3. 如果AOF选项被打开,更新AOF文件
    4. 关闭redis服务器(server)
  14. 修改密码

    # 1.找到redis的配置文件redis.cnf
    # 2.找到修改密码的行
    requirepass foobared
    # 3.把注释打开并且把foobared换成想要的密码就行了
    
  15. 重启redis服务

    # 关闭redis服务
    redis-cli shutdown
    # 使用配置文件后台启动redis服务
    redis-sevrer redis.conf &
    
  16. 从库连接主库:replicaof [host] [port]

  17. 停止主从复制:slaveof no one


4、主从复制

原理

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份,具体步骤如下:

(1)slave服务器连接到master服务器,便开始进行数据同步,发送psync命令(Redis2.8之前是sync命令)

(2)master服务器收到psync命令之后,开始执行bgsave命令生成RDB快照文件并使用缓存区记录此后执行的所有写命令

  • 如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是每个连接都执行一次,然后再把这一份持久化的数据发送给多个并发连接的slave。
  • 如果RDB复制时间超过60秒(repl-timeout),那么slave服务器就会认为复制失败,可以适当调节大这个参数

(3)master服务器bgsave执行完之后,就会向所有Slava服务器发送快照文件, 并在发送期间继续在缓冲区内记录被执行的写命令

client-output-buffer-limit slave 256MB 64MB 60,如果在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么停止复制,复制失败

(4)slave服务器收到RDB快照文件后,会将接收到的数据写入磁盘,然后清空所有旧数据,在从本地磁盘载入收到的快照到内存中,同时基于旧的数据版本对外提供服务。

(5)master服务器发送完RDB快照文件之后,便开始向slave服务器发送缓冲区中的写命令

(6)slave服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

(7)如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

操作

  1. 配置主节点(Master):
    • 打开 Redis 主服务器的配置文件 redis.conf
    • 找到 #bind 127.0.0.1 这一行,并将注释去掉,以允许其他服务器连接到主节点。
    • 找到 # requirepass foobared 这一行,并将注释去掉,设置一个密码来保护主节点的访问。
    • 找到 dir ./ 这一行,并确保该目录存在且可写,用于持久化数据。
  2. 启动主节点:
    • 使用命令 redis-server /path/to/redis.conf 启动 Redis 主节点。
  3. 配置从节点(Slave):
    • 打开 Redis 从服务器的配置文件 redis.conf。
    • 找到 #bind 127.0.0.1 这一行,并将注释去掉,以允许其他服务器连接到从节点。
    • 找到 # replicaof <masterip> <masterport> 这一行,并将注释去掉,然后将 <masterip><masterport> 替换为主节点的 IP 地址和端口号。
    • 找到 # masterauth <master-password> 这一行,并将注释去掉,如果主节点的访问有密码,就将 <master-password> 替换为主节点的密码。
    • 找到 dir ./ 这一行,并确保该目录存在且可写,用于持久化数据。
  4. 启动从节点:
    • 使用命令 redis-server /path/to/redis.conf 启动 Redis 从节点。
  5. 查看状态:info replication

5、哨兵模式

原理

什么是哨兵模式

​ 在主从模式下(主从模式就是把上图的所有哨兵去掉),master节点负责写请求,然后异步给slave节点,从节点负责处理读请求。如果master宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源。这就无法达到高可用,而通过哨兵模式就可以解决这一问题。

哨兵模式是Redis的高可用方式,哨兵节点是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。

每个哨兵节点都会定期向所有主服务器发送PING命令检测其存活状态。如果一个哨兵节点发现主服务器无响应,并且在slave节点中重新选出来一个新的master,领导者会发送命令给其他从服务器,让它们切换到新的主服务器。从而实现高可用

  1. 监控阶段

    用于同步各个节点的状态信息:各个sentinel的状态(是否在线)、获取master的状态、获取所有slave的状态(根据master中的lave信息)

    • sentinel会向master和slave获取状态

    • sentinel会发布订阅共享信息、同步信息等

  2. 通知(提醒)

当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知

  1. 自动故障转移

断开master与slave连接,通过竞选的方式选取一个slave作为master,将其他slave连接到新的master,并告知客户端的服务器地址

注意:也是一台redis服务器,知识提供数据服务,通常哨兵配置数量为单数

操作

  1. 准备工作

    1. 准备三台redis服务器端口分别为:6379、6380、6381,并完成主从复制
    2. 准备三台哨兵服务器端口分别为:26379、26380、26381
  2. 复制三个 sentinel.conf 配置文件

    port 26379
    daemonize no
    pidfile "/var/run/redis-sentinel.pid"
    logfile ""
    dir "/tmp
    # 地址选择需要监控的主节点
    # 数值2表示:如果我的主机宕机了,我有三台哨兵,那么只需要两台同意就行了。
    sentinel monitor mymaster 192.168.227.40 6381 2
    
    acllog-max-len 128
    
    sentinel deny-scripts-reconfig yes
    sentinel resolve-hostnames no
    sentinel announce-hostnames no
    
  3. 三台redis服务器通过配置文件的方式启动

    # 启动服务器
    redis-server redis6389.conf
    
  4. 三台哨兵通过配置文件的方式启动

    # 启动哨兵
    redis-sentinel sentinel26381.conf
    

6、cluster 集群

6.1、原理

一、为什么需要redis集群?

  1. 写并发

    ​ Redis单实例读写分离可以解决读操作的负载均衡,但对于写操作,仍然是全部落在了master节点上面,在海量数据高并发场景,一个节点写数据容易出现瓶颈,造成master节点的压力上升。

  2. 海量数据的存储压力

    ​ 单实例Redis本质上只有一台Master作为存储,如果面对海量数据的存储,一台Redis的服务器就应付不过来了,而且数据量太大意味着持久化成本高,严重时可能会阻塞服务器,造成服务请求成功率下降,降低服务的稳定性。

    针对以上的问题,Redis集群提供了较为完善的方案,解决了存储能力受到单机限制,写操作无法负载均衡的问题。

二、什么是Redis集群?

数据分片:redis集群采用无中心节点方式实现,通过分片机制将数据散发在各个主节点上,根据同样的hash算法计算出key对应的slot,然后直接在slot对应的redis节点上执行命令。

心跳检测:为了去中心化,Redis Cluster使用Gossip协议进行节点间通信,各个节点相互交换状态信息,监听新的节点加入。

故障转移:Redis Cluster使用心跳机制来监测节点的健康状态。如果一个节点离线或发生故障,集群会自动将该节点的分片迁移到其他健康节点上,并选择新的主节点。

redis集群支持动态加入节点,动态迁移slot,以及自动故障转移。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.2、操作

实验的准备准备签体:六台redis服务器,可以通过伪分布式来实现

  1. 修改 redis.conf 配置文件

    port 6379
    bind 0.0.0.1	# 允许所有服务器访问
    
  2. 启动所有服务器

  3. 集群启动指令

    redis-cli --cluster create 192.168.227.40:6379 192.168.227.40:6380 192.168.227.40:6381 192.168.227.40:6382 192.168.227.40:6383 192.168.227.40:6384 --cluster-replicas
    
  4. 查看集群状态:redis-cli cluster info

  5. 插入数据:redis-cli -c

6.3、问题

  1. 为什么我的一组服务器挂了集群就没用了呢?

    当集群中的 一组主从redis服务挂了 整个集群不可用

  2. 为什么我使用了集群指令会报错

    注意事项

    1. 删除redis里面的所有数据
    2. 删除目录中的 dump.rdb、appendonly.aof、nodes.conf文件

7、持久化机制

​ redis会根据策略进行持久化,并写入持久化文件,因为redis是将数据存放在内存中的,所以当服务器断电数据就不见了,那么redis就会重新加载持久化文件

  • RDB存储则是基于内存数据,生产持久化文件

  • AOF则是基于命令字符串,生成持久化文件

  • 可以通过redis.conf文件修改持久化文件

    在哪里启动redis,那么redis默认会在当前目录下查找持久化文件

7.1、RDB

原理

bgsave原理是fork() + copyonwrite,那么现在来聊一下fork()

1、fork()是什么

fork()是unix和linux这种操作系统的一个api,而不是Redis的api。

2、fork()有什么用

fork()用于创建一个子进程注意是子进程,不是子线程。

fork()出来的进程共享其父类的内存数据。仅仅是共享fork()出子进程的那一刻的内存数据,后期主进程修改数据对子进程不可见,同理,子进程修改的数据对主进程也不可见。

比如:A进程fork()了一个子进程B,那么A进程就称之为主进程,这时候主进程子进程所指向的内存空间是同一个,所以他们的数据一致。但是A修改了内存上的一条数据,这时候B是看不到的,A新增一条数据,删除一条数据,B都是看不到的。而且子进程B出问题了,对我主进程A完全没影响,我依然可以对外提供服务,但是主进程挂了,子进程也必须跟随一起挂

这一点有点像守护线程的概念。Redis正是巧妙的运用了fork()这个牛逼的api来完成RDB的持久化操作。

3、Redis中的fork()

子进程与Redis主进程共享同一份内存空间,所以子进程可以搞他的rdb文件持久化工作,主进程又能继续他的对外提供服务,二者互不影响。我们说了他们之后的修改内存数据对彼此不可见,但是明明指向的都是同一块内存空间,这是咋搞得?肯定不可能是fork()出来子进程后顺带复制了一份数据出来,如果是这样的话比如我有4g内存,那么其实最大有限空间是2g,我要给rdb留出一半空间来,扯淡一样!那他咋做的?采取了copyonwrite技术。

4、copyonwrite

然而,为了避免在备份过程中对父进程内存数据进行修改,以保证备份的一致性,Redis 使用了 Copy-on-write 技术。

Copy-on-write 的机制是,在共享数据被修改之前,不会真正创建新的副本,而是共享原始数据。当有进程或线程试图修改共享数据时,系统会将原始数据标记为只读,并为修改者创建一个新的副本。这样,父进程和子进程共享大部分内存,避免了完全复制数据的开销

通过使用 Copy-on-write 技术,Redis 在 RDB 备份过程中实现了高效的内存共享。父进程和子进程之间共享同一份内存数据,在父进程持续处理写入操作的同时,子进程可以继续读取数据,并在需要写入时才执行复制操作,确保备份数据的一致性。

什么情况下会触发?
  1. shutdown时,如果没有开启aof,会触发配置文件中默认的快照配置

  2. bgsave:redis会同故宫fork子进程进行持久化操作,同时可以响应客户端的请求,程序不会进入阻塞状态。

  3. flushall:清空内存并进行持久化操作

7.2、AOF

原理

就是每次都在aof文件后面追加命令。他与主进程收到请求、处理请求是串行化的,而非异步并行的。图示如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 写命令追加到AOF缓冲区:Redis会将执行的写命令以追加的方式添加到AOF缓冲区中。AOF缓冲区是一个内存中的缓冲区,用于临时存储待写入AOF文件的命令。
  2. AOF缓冲区写入到AOF文件:当AOF缓冲区的数据量达到一定阈值或达到一定时间间隔(根据配置决定),Redis会将AOF缓冲区的内容写入到AOF文件中。写入AOF文件采用的是系统调用,通常是以追加的方式写入文件末尾。
  3. AOF文件同步:Redis提供了多种AOF文件同步策略,可以选择每次写操作都立即将数据同步到硬盘上的磁盘同步策略(always),或者根据一定时间间隔对AOF文件进行同步(everysec),也可以完全依赖操作系统的自动同步(no)。同步操作确保AOF文件中的写入操作持久化到硬盘,以避免数据丢失。
  4. AOF文件的后台重写:为了避免AOF文件过大导致读取和恢复速度变慢,Redis会周期性地启动AOF文件的后台重写过程。重写过程会生成一个新的AOF文件,其中只包含能够还原当前数据集的最小命令集合。重写过程是通过读取现有数据集并转换为命令序列来完成的,从而减少AOF文件的大小。
  • 通过redis.conf开启aof持久化:appendonly yes
触发机制

appendfsync是Redis的一个配置项,用于指定数据写入磁盘时的策略。它可以设置为以下三个选项之一:

参数内容
always每次收到数据修改命令后,立即将数据同步到磁盘(通过调用系统的fsync函数)。这种方式可以提供最高的数据安全性,但也可能导致较低的写入性能。
everysec(默认)每秒将数据同步到磁盘一次。这种方式在数据持久化和性能之间取得了平衡,适合绝大多数的应用场景。如果Redis出现故障,可能会丢失最近一秒内的写入数据。
no完全依赖操作系统的文件系统缓存来处理AOF文件的刷盘。即写命令只会先写入到内核的页缓存中,而不会直接写入硬盘。这个策略可以获得最好的性能,但在发生意外断电或宕机时可能会造成较多数据的丢失。

注意,即使将appendfsync设置为everysecno,Redis仍然会通过后台的子进程进行持久化操作,将数据写入磁盘的RDB文件或AOF文件中,以便在重启时恢复数据。因此,即使在这两种情况下,Redis的数据仍然具有持久性。

选择适当的appendfsync设置取决于应用的需求和可靠性要求。如果对数据的可靠性要求非常高,可以选择always;如果对性能优化更为关注,可以选择everysecno。需要根据具体的业务情况进行权衡和选择。

aof重写机制
  • 当AOF文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写

    # 当文件达到64M*100%的时候会进行自动重写
    auto-aof-rewrite-min-size 100
    
  • 当aof文件增长到一定大小的时候redis能够调用 bgrewriteaof 对日志文件进行重写

    # 当日志文件达到64Mb进行重写
    auto-aof-rewrite-min-size 64mb
    

7.3、reids4.0后混合持久化机制(rdb+aof)对重写的优化

  • 4.0版本的混合持久化默认关闭,同故宫aof-usr-rdb-preamble配置参数控制,yes表示开启。5.0版本默认开启
  • 混合持久化是通过bgrewriteaof完成的,不同的是当开启混合持久化,fork子进程先将共享的副本全量以RDB方式写入aof文件,再将重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新信息,替换成就得aof文件。”新得aof文件前半段是rdb格式得全量数据后半段是aof格式的增量数据“
  • 优点:混合持久化结合了RDB持久化AOF持久化的优点,由于绝大部分都是RDB格式,加载速度快,同时结合AOF的增量方式保存,数据更少的丢失
  • 缺点:兼容性差,在4.0以前版本都不识别aof文件。

7.4、RDB和AOF优缺点

RDB 优点
  1. 体积更小:相同的数据量 RDB 数据比 AOF 的小,因为 RDB 是紧凑型文件。
  2. 恢复更快:因为 RDB 是数据的快照,基本上就是数据的复制,不用重新读取再写入内存。
  3. 性能更高:父进程在保存 RDB 时候只需要fork一个子进程,无需父进程的进行其他io操作,也保证了服务器的性能。
RDB 缺点
  1. 故障丢失:因为 RDB 是全量的,我们一般是使用shell脚本实现30分钟或者1小时或者每天对 Redis 进行 RDB 备份,(注,也可以是用自带的策略),但是最少也要5分钟进行一次的备份,所以当服务死掉后,最少也要丢失5分钟的数据。
  2. 耐久性差:相对 AOF 的异步策略来说,因为 RDB 的复制是全量的,即使是 fork 的子进程来进行备份,当数据量很大的时候对磁盘的消耗也是不可忽视的,尤其在访问量很高的时候,主线程 fork 的时间也会延长,导致 cpu 吃紧,耐久性相对较差。
AOF 优点
  1. 数据保证:我们可以设置fsync策略,一般默认是 Everysec,也可以设置每次写入追加,所以即使服务死掉了,也最多丢失一秒数据
  2. 自动缩小:当 AOF 文件大小到达一定程度的时候,后台会自动的去执行 AOF 重写,此过程不会影响主进程,重写完成后,新的写入将会写到新的 AOF 中,冗余的数据就会被删除掉
  3. 灵活性大:可以通过借助工具对文件进行修改
AOF 缺点
  1. 性能相对较差:它的操作模式决定了它会对 Redis 的性能有所损耗。(主线程写文档)
  2. 体积相对更大:尽管是将 AOF 文件重写了,但是毕竟是操作过程和操作结果仍然有很大的差别,体积也毋庸置疑的更大。
  3. 恢复速度更慢:AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的。

7.5、问题

1、为什么要fork子进程?

  • redis主线程去做redis持久化操作了,那么数据库会进入阻塞状态。

2、redis提供哪两种方式进行持久化

  1. 一种是RDB持久化(默认)
  2. 一种是AOF(append only file)持久化

8、面试题

8.1、redis作用,应用场景

作用:

  • 主要用Redis实现缓存数据的存储,可以设置过期时间,对于一些高频读写、临时存储的数据特别适合.

应用场景:

  • 缓存:Redis最常见的用途是作为缓存层。由于Redis将数据存储在内存中,读写速度非常快,可以显著提高应用程序的性能。它可以用作常规数据的缓存,也可以用作热门数据、会话数据和页面片段的缓存。
  • 分布式锁:利用Redis的原子操作和过期时间特性,可以实现分布式锁。分布式锁能够确保在分布式环境下对共享资源进行互斥访问,解决并发竞争的问题。
  • 消息队列:Redis提供了简单且高效的发布-订阅模式,可以用作消息队列的中间件。通过将消息发布到特定的频道,然后订阅者可以接收到这些消息,实现了解耦和异步处理。

8.2、redis主从复制模式下,主挂了怎么办?

何谓哨兵模式?就是通过哨兵节点进行自主监控主从节点以及其他哨兵节点,发现主节点故障时自主进行故障转移。

8.3、使用redis有哪些好处

  1. 多种数据结构支持:Redis支持多种数据结构,包括字符串、哈希、列表、集合和有序集合,这使得数据存储更加灵活和高效。
  2. 持久化支持:Redis提供了两种持久化机制(AOF和RDB),可以将数据写入磁盘,并在重启后恢复数据,以防止数据丢失。
  3. 高可用性和复制支持:Redis支持主从复制,可以将数据复制到多个节点,实现高可用性和容错能力。

8.4、MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据(redis有哪些数据淘汰策略???)

  1. LRU(Least Recently Used,最近最少使用):Redis默认的数据淘汰策略就是LRU。当内存达到限制时,Redis会尝试淘汰最近最少使用的键值对。
  2. LFU(Least Frequently Used,最不经常使用):Redis也支持LFU策略。LFU会淘汰最不经常使用的键值对,在一段时间内被访问次数最少的数据会被淘汰。
  3. TTL(Time-To-Live,生存时间):通过设置键的过期时间,可以在Redis中自动淘汰数据。适用于那些具有时效性的数据,一旦过期就会被自动删除。
  4. Random(随机淘汰):Redis还提供了随机淘汰策略,即随机选择一些键值对进行淘汰。这种策略相对简单,但无法保证热点数据的优先性。

8.5、看你简历上写了你项目里面用到了Redis,你们为啥用Redis?

因为传统的关系型数据库如Mysql已经不能适用所有的场景了,比如秒杀的库存扣减,APP首页的访问流量高峰等等,都很容易把数据库打崩,所以引入了缓存中间件,目前市面上比较常用的缓存中间件有Redis 和Memcached 不过综合考虑了他们的优缺点,最后选择了Redis。

  1. 数据持久化能力较弱:相比Redis而言,Memcached的数据持久化能力较弱。它通常将数据完全存储在内存中,不会将数据写入磁盘。因此,在系统崩溃或重启时,数据可能会丢失。
  2. 功能相对简单:Memcached的功能相对较为简单,仅提供基本的键值存储模型。相比之下,Redis拥有更丰富的数据结构和功能,可以进行更复杂的操作和计算。
  3. 不支持主从复制和高可用性:Memcached不支持内置的主从复制机制,这意味着在节点故障时无法实现自动故障转移。对于要求高可用性的应用来说,这可能是一个劣势。
  4. 缺乏分布式功能:虽然Memcached可以通过添加更多的节点实现水平扩展,但它缺乏内置的分布式管理功能。这意味着需要通过额外的工作来实现负载均衡和节点故障恢复,相对来说较为繁琐。
  5. 生态系统相对较小:相比Redis而言,Memcached的生态系统相对较小。这意味着可能会在集成和社区支持方面受到一些限制。在某些特定的使用场景下,这可能被视为一个劣势。

8.6、redis有哪些数据结构呀?

  • String(字符串):
    • 用途:存储字符串值,可以是文本、数字或二进制数据。
    • 特点:支持丰富的操作,如设置、获取、追加、计数等。
  • Hash(哈希):
    • 用途:存储字段和值的映射关系,类似于关联数组或字典。
    • 特点:适用于存储对象或实体,每个哈希可以包含多个字段和对应的值。
  • List(列表):
    • 用途:按照插入顺序存储一个有序的字符串元素集合
    • 特点:可以快速在两端执行插入、删除、查找操作,常用于实现队列、栈等数据结构。
  • Set(集合):
    • 用途:存储唯一的、无序的字符串元素集合。
    • 特点:支持集合运算,如交集、并集、差集等,还可以快速判断元素是否存在。
  • Sorted Set(有序集合):
    • 用途:存储带有分数(score)的字符串元素集合,按照分数排序。
    • 特点:可以根据分数范围进行检索,支持快速插入、删除和更新操作。

8.7、那你使用过Redis分布式锁么,它是什么回事?

先拿setnx来争抢锁,抢到之后,再用expire(一颗四百额)给锁加一个过期时间防止锁忘记了释放。

使用脚本对rdb文件持久化

# 执行持久化操作
msg=`redis-cli -p $1 -a $2 bgsave`
# 获取结果非零则是进行持久化操作
result=`redis-cli -p $1 -a $2 info Persisetence | grep 'rdb_bgsave_in_progress | awk -F':' '{print $2}'`
# 如果一直处于持久化则一直都会循环
while [ `echo $result | awk -v temp=0 '{print($1>$temp) ? "1":"0"}` -eq "1"];
do 
	sleep 1
	result =`redis-cli -p $1 -a $2 info Persisetence | grep 'rdb_bgsave_in_progress | awk -F':' '{print $2}'`
done

三、Nginx

介绍

多模型基本请求流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

反向代理服务器

  1. 什么是正向代理

    ​ 当用户想访问某一网址时,用户先访问代理服务器,然后由代理服务器向目标网址发送请求最终将数据返回代理服务器,最后代理服务器将数据返回给用户这一过程我们称之为正向代理。

  2. 什么是反向代理

    img

    ​ 基本流程是与正向代理是相同的,都是通过 用户发送请求 -->代理服务器–>目标服务器。但是二者的区别在于正向代理时用户知道自己访问的是代理服务器,而反向代理是无感知的,用户本质上是不知道自己访问的是代理服务器。

  3. 正向和反向代理的区别

    1. 使用场景:
      • 正向代理中,服务器不知道真正的用户是谁。
      • 反向代理中,用户不知道真正的服务器是谁。
    2. 使用场景:
      • 正向代理:正向代理是客户端与目标服务器之间的中间人。当客户端需要访问互联网上的资源时,它通过正向代理服务器发送请求并获取响应。正向代理可以用于访问受限制的内容或绕过防火墙限制,同时也可以提供缓存、安全性和匿名性等功能。(客户端架构)
      • 反向代理:反向代理是服务器与目标服务器之间的中间人。当客户端发起请求时,反向代理服务器接收请求,并将其转发给后端的服务器。反向代理可以用于负载均衡、请求分发、缓存、SSL 加密等。(服务端架构)
    3. 功能:
      • 正向代理:正向代理可以代表客户端发起请求,隐藏客户端的身份和位置。它还可以提供缓存功能以加快请求速度,并且可以进行访问控制和安全过滤。
      • 反向代理:反向代理可以通过负载均衡将请求分发给多个后端服务器,以提高系统的性能和可伸缩性。它还可以缓存常用的响应数据、提供 SSL 加密以保护通信安全,以及进行请求过滤和访问控制。

Https证数配置

  1. 密钥管理

    • 非对称协议:非对称协议使用一对密钥,即公钥和私钥。公钥加密私钥解密。公钥可以公开发送给任何人,而私钥必须保密。
    • 对称协议:对称协议使用相同的密钥进行加密和解密。发送方和接收方必须共享同一个密钥。
  2. 安全性

    • 非对称协议:非对称加密提供了更好的安全性,因为私钥是保密的,并且对手中仅有的公钥进行加密的数据只能使用对应的私钥解密。这样即使公钥被泄露,也无法轻易破解密文。
    • 对称协议:对称加密的安全性相对较低,因为发送方和接收方必须共享同一个密钥。如果密钥泄露,就可能导致数据被未授权的人读取或篡改。
  3. 性能

    • 非对称协议:非对称加密算法的计算复杂度较高,加密解密速度相对较慢,特别是在处理大量数据时。因此,非对称加密通常用于密钥交换和数字签名等辅助用途。
    • 对称协议:对称加密算法的计算复杂度较低,加密解密速度较快,在大量数据通信时更加高效。因此,对称加密常用于传输过程中的数据加密。
  4. 对称协议算法

img
  1. 非对称协议算法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置文件

# 工作进程
worker_processes  1;
events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
	# 用于设置Nginx在传输文件时是否启用高效传输模式
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.php;
        }
	location /stub_status {
		stub_status on;
	}

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      file.crt;
        ssl_certificate_key  file.key;

    }

}

sendfile

  • 启用该参数可以显著提高Nginx传输文件的性能,因为它允许Nginx直接在内核中复制数据,而不是通过用户空间的数据拷贝。这减少了系统调用的次数,从而降低了CPU的使用率和内存的消耗。
  • sendfile off:nginx应用程序需要在磁盘中找到对应的文件并读取,再将读取到的文件发送给网络接口缓存,再反馈给用户
  • sendfile on:ngixn应用程序发送一个信号sendfile(),再让操作系统的网络接口读取这个文件,通过网络发送给用户
image-20230620093027611

1、源码包安装

  1. 安装
# 下载仓库
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

# 安装依赖
yum -y install gcc gcc-c++ zlib zlib-devel pcre pcre-devel openssl openssl-devel

# 解压nginx
tar -zxf nginx-1.20.2.tat.gz -C /usr/src
cd /usr/src/nginx-1.20.2/

# 执行脚本
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

# 将来makefile文件编译成可执行文件
make && make install

# 添加系统服务
ln -s /usr/local/nginx/sbin/* /usr/local/sbin/ 
  1. 添加系统服务以常用命令
vim /etc/rc.d/init.d/nginx
# 添加
#!/bin/bash
#chkconfig: 35 85 21
case $1 in
start)
 /usr/local/sbin/nginx
 ;;
stop)
 killall -9 nginx
 rm -f /var/run/nginx.pid
 ;;
restart)
 $0 stop
 $0 start
 ;;
*)
 echo "start|stop|restart"
 ;;
esac
  1. 启动服务
chmod +x /etc/rc.d/init.d/nginx
chkconfig --add nginx
chkconfig nginx on
killall -9 nginx
systemctl restart nginx
systemctl status nginx

2、常用指令

  1. 启动nginx服务:nginx

  2. 重新加载配置文件:nginx -s reload

    nginx服务器不需要重启

  3. 关闭nginx:killall -9 nginx

  4. 检查nginx文件是否正确:nginx -t

  5. 重启:直接killall -9 nginxnginx开启

3、虚拟主机

  • 购买域名:https://dns.console.aliyun.com/
  1. 基于ip的虚拟主机

    不同IP对应的网站访问方便,用户直接通过ip访问,维护方便,但是一个服务器就需要多个ip地址

  2. 基于域名的虚拟主机(IP,端口号相同)

    多个网站使用一个IP,通过不同的域名对应不同的网站

  3. 基于端口的虚拟主机

    多个网站IP相同,通过不同的端口对应不同的网站,节省ip地址

4、添加模块

4.1、添加步骤

1、查看现有Nginx的安装版本和已编译的参数
# 进入Nginx的安装目录
$ cd /usr/local/nginx/sbin
 
# 查看现有Nginx的版本和已编译的参数
$ ./nginx -V

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2、带上新模块重新编译
# 进入刚下载解压出来的Nginx安装目录
$ cd /data/soft/nginx-1.20.1
 
# 带上新模块重新编译
$ ./configure --prefix=/usr/local/nginx/ --sbin-path=/usr/local/nginx/sbin/ --with-http_ssl_module --with-http_v2_module --with-stream --conf-path=/usr/local/nginx/conf/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --http-fastcgi-temp-path=/usr/local/nginx/fastcgi_temp --http-client-body-temp-path=/usr/local/nginx/client_body_temp --http-proxy-temp-path=/usr/local/nginx/proxy_temp --http-uwsgi-temp-path=/usr/local/nginx/uwsgi_temp --http-scgi-temp-path=/usr/local/nginx/scgi_temp
 
# 编译 注意:这里只有make,一定不要手贱顺手执行了make install,不然会覆盖安装的
$ make

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


4.2、平滑重启

上一步执行完成后,会在当前目录下生成objs目录,其中的nginx文件即为新的二进制文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1、备份原来的nginx文件
# 进入Nginx的原安装目录
$ cd /usr/local/nginx/sbin
 
# 备份原Nginx运行脚本文件
$ cp -rf nginx nginx_bak
2、替换nginx二进制文件
$ cp -f /data/soft/nginx-1.20.1/objs/nginx /usr/local/nginx/sbin/nginx
3、正确性检查
nginx -t
4、重启
killall -9 nginx
nginx
5、查看最终编译的新模块
$ /usr/local/nginx/sbin/nginx -V

需要添加--with-http_v2_module --with-stream模块已成功加上

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6、重新加载Nginx
nginx -s reload

特别注意:重新编译了Nginx,只是/usr/local/nginx/sbin/nginx -s reload 新增加模块不会报错,但Nginx新增的配不会生效。这个折腾了很久,一直以为配置问题。

如果不生效,确保不想要业务的情况下,可以把一台Nginx节点下线,使用 /usr/local/nginx/sbin/nginx stop停止后,再重新启动Nginx。


5、模块介绍

5.1、http_ssl_module(openSSL)

http_ssl_module模块主要负责提供HTTPS(SSL/TLS加密)连接的功能。该模块能够实现对客户端连接的认证、密钥交换、加密保护、证书管理等,确保了数据传输的安全性。

  1. 安装依赖关系

    yum -y install openssl openssl-devel
    
  2. 生成密钥

    opensll genrsa -out /file.key 2048	
    genrsa:加密类型
    -out:输出位置
    2048:密钥的长度
    
  3. 生成密钥文件

    openssl req -new -key /file.key -out /file.csr -days -365
    
  4. 颁发证书

    openssl x509 -req -in /file.csr -signkey /file.key -out /file.crt -days 365
    

5.2、http_stub_status_module(服务器监控)

ngx_http_fastcgi_module(LNMP)

​ 这个模块作用是为系统管理员和开发人员提供了来监控Nginx服务器的运行状况, 用于查看和收集有关Nginx服务器的各种状态信息,例如当前连接数、请求数、带宽使用情况等。

  1. 添加模块

    ./confgiure --prefix=/usr/local/nginx/ --with-http_ssl_module --with-http_stub_status_module
    
  2. 修改配置文件

    server{
    	location /stub_status {
    		stub_status on;
    	}
    }
    

5.3、ngx_http_fastcgi_module(LNMP)

​ 使用 ngx_http_fastcgi_module 模块,可以使得 Nginx 与后端应用程序之间的通信更加高效,同时也提供了负载均衡、缓存等功能,从而提高了 Web 服务器的性能和可靠性。

服务器配置(php)
  1. 上传PHP软件包

  2. 安装依赖

    yum -y install gd libxml2-devel libjpeg-devl libpng-devel
    
  3. 编译安装

    1. 编译文件:./configure --prefix=/usr/local/php --with-gd --with-zlib --with-mysql=mysqlnd --with-config-file-path=/usr/local/php --enable-fpm --enable-mbstring --with-jpeg-dir=/usr/lib --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config

    2. 编译安装:make -j4 && make install

      make -j4:意思是启动多线程编译文件

  4. 拷贝初始化文件:

    cp php.ini-development /usr/local/php/php.ini
    
  5. 修改ini配置文件

    vim /usr/local/php/php.ini 
    	784行 default_charset = "utf-8" #修改字符集
    	226行 short_open_tag = On #支持后面脚本写为<? ?>格式
    
  6. 拷贝php-fpm,给php-fpm执行权限,并且加入到系统服务

    cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
    	chmod +x /etc/init.d/php-fpm
    	chkconfig --add php-fpm
    
  7. 切换目录,拷贝conf文件

    cd /usr/local/php/etc/
    cp php-fpm.conf.default php-fpm.conf
    
  8. 修改.conf配置文件

    vim php-fpm.conf
    	25行去掉注释 pid = run/php-fpm.pid #开启php-fpm进程
    	217行添加 pm.max_children = 50 #子进程最大数
    	222行添加 pm.start_servers = 20 #启动是进程数
    	227行添加 pm.min_spare_servers = 5 #保证空闲进程最小值
    	232行添加 pm.max_spare_servers = 35 #保证空闲进程最大数
    	listen = 192.168.227.60:9000
    
  9. 启动php

    systemctl start php-fpm
    systemctl status php-fpm
    
  10. 创建共享目录,并赋予权限

    mkdir /www
    	vim /etc/exports
    	/www 192.168.1.0/24(rw,sync,no_root_squash)
    
  11. 查看共享目录,并且启动服务

    exportfs -rv
    	systemctl start rpcbind
    	systemctl start nfs
    
Web服务器(Nginx)
  1. 改配置文件

    location ~ \.php$ {
               root           /www;
               fastcgi_pass   192.168.227.60:9000;
               fastcgi_index  index.php;
               fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
               include        fastcgi.conf;
            }
    
  2. nginx创建共享目录,然后让nginx挂载php的共享目录

    mount -t nfs 192.168.227.60:/www /aaa
    

数据库(MySQL)
  1. 用户授权

    grant all on *.* to 'root'@'192.168.227.60' by identify '1234.Com'
    

6、负载均衡

概述:负载均衡是一种将请求分摊到多个操作单元上执行的技术,从而提高服务的可用性和响应速度,带给用户更好的体验。Nginx可以实现负载均衡的方式包括轮询方式、权重方式、ip_hash方法,以及利用第三方模块的方式。

  1. 实验前提:两天web服务器(nignx服务器)+ 一台负载均衡服务器(Nginx服务器)

    注意:当nginx服务器开启了负载均衡模式,同时也可以拥有web服务功能

  2. 修改负载均衡服务器

    upstream nginxserver{
        # 服务器已经死亡
    	server 192.168.227.50:80 weight=1 down;
        # 服务器作为备用机使用,当没有机器可以用了就启动
    	server 192.168.227.60:80 weight=1 backup;
        server 192.168.227.70:80 weight=1;
    }
    server{
    	location / {
    		root html;
    		index index.html index.htm;
    		proxy_pass http://nginxserver;
    	}
    }
    

8、动静分离

  • 静态资源部署在Nginx上,当一个请求来的时候,如果是静态资源的请求,就直接到nginx配置的静态资源目录下面获取资源,
  • 如果是动态资源的请求,nginx利用反向代理的原理,把请求转发给后台应用去处理,从而实现动静分离

基本配置

  1. 创建轮询集合

    用户可以通过访问不同的

  2. 设置响应域名

    server {
            location ~ \.php$ {
                proxy_pass http://192.168.227.60;
            }
            location ~ \.htm$ {
                proxy_pass http://192.168.227.50;
            }
    }
    
  3. 静态资源

    server{
        location /css {
            root html;
            index index.html index.htm;
        }
        location /js {
            root html;
            index index.html index.htm;
        }
        location /img {
            root html;
            index index.html index.htm;
        }
    }
    
    # 正则表达是
    server{
        location ~*/(js|css|img|js) {
            root html;
            index index.html index.htm;
        }
    }
    

伪静态

注意:rewrite要放在proxy_pass前面否则会失效

server{
    localtion / {
        rewrit ^/([0-9]+).html$   /index.jsp?pageNum=$1   break;
    }
}
flag标记说明
last:#本次规则匹配完成后,继续向下匹配新得localtion url规则
break:#本次规则匹配完成后,不在匹配后面的规则。
redirect:#返回302临时重定向,浏览器会显示跳转后的地址
permanent:#返回301永久冲顶先

防盗链

​ 当浏览器向web服务器发送请求的时候,一般都会带上Referer,来告诉浏览器该网页是从哪个页面链接过来的。

​ 后台服务器可以根据获取到的这个Referer信息来判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息。

如果invalid_referer=0是允许访问的

  1. 返回错误页面

    # 防盗链
    server{
        location ~*/(js|css|css){
            valid_referers 0 none blocked 192.168.44.101;
            if($invalid_referer){
                return 401;
            }
        }
        
        error_page 401 /401.html;
        location = /401.html{
            root html;
        }
    }
    
  2. 整合rewrite返回报错图片

    # 防盗链
    server{
        location ~*/(js|css|css){
            valid_referers none 192.168.44.101;
            if($invalid_referer){
                rewrite ^/	/img/x.png break;
            }
        }
    }
    

9、工作原理

9.1、工作原理

  1. 什么是正向代理

    ​ 当用户想访问某一网址时,用户先访问代理服务器,然后由代理服务器向目标网址发送请求最终将数据返回代理服务器,最后代理服务器将数据返回给用户这一过程我们称之为正向代理。

  2. 什么是反向代理

    img

    ​ 基本流程是与正向代理是相同的,都是通过 用户发送请求 -->代理服务器–>目标服务器。但是二者的区别在于正向代理时用户知道自己访问的是代理服务器,而反向代理是无感知的,用户本质上是不知道自己访问的是代理服务器。

  3. 正向和返现服务器的区别

    1. 正向代理实际代理的是客户端。反向代理代理的是目标服务器
    2. 正向代理是客户端架构,而反向代理是服务器架构。
    3. 正向代理中,服务器不知道真正的用户是谁。反向代理中,用户不知道真正的服务器是谁。
    4. 正向代理主要用来解决访问问题。反向代理主要用于解决负载均衡、安全防护,但二者都能提高访问速度。

9.2、优化

  • 网络IO事件模型优化
  • 隐藏软件名称和版本号
  • 防盗链优化
  • 禁止恶意域名解析
  • 禁止通过IP地址访问网站
  • 严格设置web站点目录的权限
  • HTTP请求方法优化

9.3、Nginx宕机怎么处理?

Nginx上传大文件150M以上上传不了。是因为带宽的问题,因为大家都在上传,小文件可以传是因为在优化的65秒可以上传内容这么大。把上传的优化断开时间修改到1800秒。过了几天服务器直接宕机了。后来发现后来服务器的进程满级了。因为上传的小的文件也是占用1800秒。所以很多人上传不了文件,因为进程都被占用了。解决。。要进行逻辑业务分离,上传的专门做上传服务器,不再走网站形式进行上传。

10、面试题

请解释一下什么是Nginx?

  1. 反向代理服务器:是一款免费的、自由的、开源的、高性能HTTP服务器和反向代理服务器
  2. Web服务器:Nginx本身就可以托管网站(类似于Tomcat一样),可以将打包好的前端资源直接放在Nginx服务器中,提高性能,也可以作为反向代理服务器 、负载均衡器和HTTP缓存。

请列举Nginx的一些特性

  1. 高并发处理能力:Nginx采用异步非阻塞事件驱动架构,能够高效地处理大量并发连接,适用于高流量的网站和应用程序。
  2. 负载均衡:Nginx支持负载均衡,可将请求分发到多个后端服务器,以提高系统的整体性能和可用性。
  3. 反向代理:Nginx可以作为反向代理服务器,接收客户端请求并转发到后端服务器,隐藏了后端服务器的真实IP地址,提高了系统的安全性和灵活性。
  4. 静态文件服务:Nginx可以高效地提供静态文件的访问,如HTML、CSS、JavaScript、图片等,减轻了动态服务器的负担。

请解释Nginx如何处理HTTP请求。

  1. 多进程机制

服务器每当收到一个客户端时,就有 服务器主进程 ( master process )生成一个 子进程( worker process )出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。

各个进程之间相互独立,如果一个进程发生异常退出时,其它进程正常工作, master 进程则很快启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。

缺点是操作系统生成一个子进程需要进行 内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降

  1. 异步非阻塞机制

每个工作进程 使用 异步非阻塞方式 ,可以处理 多个客户端请求 。

当某个 工-098765·作进程 接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去 处理其他请求 (即为 非阻塞 );而 客户端 在此期间也 无需等待响应 ,可以去处理其他事情(即为 异步 )。

请列举Nginx和Apache 之间的不同点

  1. 处理并发连接

    • Nginx 使用事件驱动、异步非阻塞的处理模型,而不是为每个连接创建一个线程,每个连接使用较少的系统资源,并能同时处理大量并发连接,适合高并发场景。

    • Apache 使用多线程多进程的模型,每个连接都需要独占一个线程或进程,对系统资源的消耗较大。

  2. 内存消耗

    • Nginx 的内存消耗相对较低,它使用较少的内存来存储每个连接的状态信息,可以支持更多的并发连接。
    • Apache 的内存消耗较高,尤其是在处理大量并发连接时,每个连接都需要占用较多的内存。
  3. 静态文件处理

    • Nginx 在处理静态文件时表现出色,它可以高效地提供静态文件的访问,支持 Sendfile 技术,可以直接将文件从磁盘发送到客户端,减少了 CPU 和内存的开销。
    • Apache 的静态文件处理性能较差,每个请求都需要通过 Apache 进程进行处理。
  4. 反向代理和负载均衡

    • Nginx 内置了反向代理和负载均衡功能,可以将请求转发给后端的多个服务器,并实现负载均衡算法。
    • Apache 需要通过额外的模块(如 mod_proxy)来实现反向代理和负载均衡功能。

请解释Nginx服务器上的Master和Worker进程分别是什么?

  1. Master进程: Master进程是Nginx服务器启动时创建的主进程,它主要负责控制整个服务器的运行。Master进程的主要任务包括:
    • 读取并解析配置文件,加载配置项。
    • 创建Worker进程,并分配任务给它们。
    • 监听端口,接收来自客户端的连接请求。
    • 处理信号,如重载配置、重新启动、停止服务器等。
    • 管理Worker进程的生命周期。
  2. Worker进程: Worker进程是由Master进程创建的子进程,它们实际处理来自客户端的请求。
    • 接收Master进程分配的任务,处理来自客户端的请求。
    • 执行与请求相关的操作,如读取文件、执行后端程序等。
    • 返回响应给客户端。

一般推荐 worker 进程数与CPU内核数一致

常见状态码

200 (OK):请求被正常处理并返回;

301 (Moved Permanently):永久性重定向,表示请求的资源被分配了新的URL,之后 应使用更改的URL;

302 (Found):临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新 的URL;

301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)

303 (See Other):表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的 资源;

302与303的区别:后者明确表示客户端应当采用GET方式获取资源

304 (Not Modified):表示客户端发送附带条件(是指采用GET方法的请求报文中包含
if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任 一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;

307 (Temporary Redirect):临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);

400 (Bad Request):表示请求报文中存在语法错误;

401 (Unauthorized):未经许可,需要通过HTTP认证;

403 (Forbidden):访问权限出现问题

404 (Not Found):表示服务器上无法找到资源

499:客户端主动断开

500 InterServer Error:表示服务器在执行请求时发生了错误,也有可能是web应用 存在的bug或某些临时的错误时;

502 Bad Gateway:网关错误,从后端接收到无效的响应。

503 ServerUnavailable:表示服务器暂时处于超负载

504 Gateway Time-out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器响应。

模块的作用

  • ngx_http_upstream_module用于定义可通过fastcgi传递、proxy传递、uwsgi传递、memcached传递和scgi传递指令来引用的服务器组。
  • ngx_http_fastcgi_module(LNMP):使用 ngx_http_fastcgi_module 模块,可以使得 Nginx 与后端应用程序之间的通信更加高效,同时也提供了负载均衡、缓存等功能,从而提高了 Web 服务器的性能和可靠性。
  • http_stub_status_module(服务器监控):这个模块作用是为系统管理员和开发人员提供了来监控Nginx服务器的运行状况, 用于查看和收集有关Nginx服务器的各种状态信息,例如当前连接数、请求数、带宽使用情况等。
  • http_ssl_module:模块主要负责提供HTTPS(SSL/TLS加密)连接的功能。该模块能够实现对客户端连接的认证、密钥交换、加密保护、证书管理等,确保了数据传输的安全性。

请解释什么是C10K问题?

C10K问题是指无法同时处理大量客户端(10,000)的网络套接字。

请陈述指令的作用是什么?

  • gzip_types:指令MIMS的压缩类型

  • gzip_comp_leve:压缩程度,级别1-9,1是效率最高的,9效率最低,数值越大cpu利用率越高

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • Stub_status指令:该指令用于了解Nginx当前状态的当前状态,如当前的活动连接,接受和处理当前读/写/等待连接的总数;

  • Sub_filter指令:它用于搜索和替换响应中的内容,并快速修复陈旧的数据;

解释Nginx是否支持将请求压缩到上游?

您可以使用Nginx模块gunzip将请求压缩到上游。gunzip模块是一个过滤器,它可以对不支持“gzip”编码方法的客户机或服务器使用“内容编码:gzip”来解压缩响应。

解释如何在Nginx中获得当前的时间?

要获得Nginx的当前时间,必须使用SSI模块、 d a t e g m t 和 date_gmt和 dategmtdate_local的变量。

Proxy_set_header THE-TIME $date_gmt;

用Nginx服务器解释-s的目的是什么?

  • nginx -s reload:用来加载更新的配置文件

解释如何在Nginx服务器上添加模块?**

在编译过程中,必须选择Nginx模块,因为Nginx不支持模块的运行时间选择。

四层负载和七层负载

四层负载均衡和七层负载均衡是在网络中用于分发请求和平衡流量的两种不同的负载均衡方式。

  1. 四层负载均衡(Layer 4 Load Balancing): 四层负载均衡基于传输层来进行负载分发。四层负载均衡可以检查IP、端口号等信息,将请求分发给后端服务器。

    四层负载均衡主要关注网络传输的连接性和数据传输的可靠性,不关心应用层协议和内容。

    四层负载均衡的优点是处理速度快、效率高,适用于大规模、高并发的网络流量分发。常见的四层负载均衡器有LVSHAProxy等。

  2. 七层负载均衡(Layer 7 Load Balancing): 七层负载均衡基于应用层来进行负载分发。七层负载均衡可以根据URL、域名等信息进行请求分发。

    七层负载均衡除了具有四层负载均衡的功能外,还能根据应用层特征进行更复杂的负载分发,如会话保持、内容缓存、SSL加速等。七层负载均衡适用于需要深度识别和处理应用层协议的场景。常见的七层负载均衡器有Nginx、F5 BIG-IP等。

负载均衡策略

  1. 轮询(Round Robin): 默认的负载均衡策略。按照顺序将请求依次分发给后端服务器,实现简单且均匀的负载分配。
  2. IP哈希(IP Hash): 根据客户端的IP地址进行哈希计算,将相同IP的请求分发到同一台后端服务器,确保来自同一客户端的请求都发送到同一服务器,用于保持会话等需要保持一致性的场景。
    • 如果有大量的客户端使用相同的IP地址(例如在NAT环境下),会导致请求被集中分发给同一台服务器,而其他服务器的负载较低。
    • 当后端服务器的数量发生变化时(如增加或减少服务器),会导致哈希计算的结果发生变化,从而导致连接会话断开
  3. 最少连接(Least Connections): 将请求发送给连接数最少的后端服务器,保证负载均衡时后端服务器的连接数尽可能平衡。
    • 当连接数较少的服务器处理的请求耗时较长时,会导致负载不均衡,因为它们处理较慢的请求比其他服务器更久
    • 当连接数较少的服务器突然失效时,会导致请求被发送到已经无法处理的服务器上造成延迟。
  4. 加权轮询(Weighted Round Robin): 给每个后端服务器分配一个权重值,根据权重比例分配请求。可以根据服务器的性能和负载情况设置不同的权重值,使性能更好的服务器获得更多的请求。
  5. 加权最少连接(Weighted Least Connections): 类似于最少连接策略,但考虑了每个服务器的权重。根据服务器的权重和连接数,动态选择最适合的后端服务器来处理请求。
    • 如果权重设置不合理,可能导致服务器之间的负载不均衡,某些服务器过载,而其他服务器闲置。

四、LVS

1、LVS-DR

1.1、LVS-DR 工作原理

LVS-DR(Linux Virtual Server Director Server)工作模式 ,是生产环境中最常用的一 种工作模式。

  • LVS-DR 模式,Director Server 作为群集的访问入口,不作为网关使用
  • 节点 Director Server 与 Real Server 需要在同一个网络中,返回给客户端的数据不需要经过 Director
    Server。
  • 为了响应对整个群集的访问,Director Server 与 Real Server 都需要配置 VIP 地址。

1.2、数据包流向分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LVS-DR原理:请求由LVS接受,它通过修改MAC地址端口号来实现源地址和目标地址的转换,由真实提供服务的服务器(RealServer, RS)直接返回给用户,返回的时候不经过LVS。

  • 数据包转发:DR模式下需要LVS服务器和RS绑定同一个VIP(虚拟IP), 一个请求过来时,LVS只需要将网络帧的MAC地址修改为某一台RS的MAC,该包就会被转发到相应的RS处理
  • DR模式下,lvs接收请求输入,将请求转发给RS,由RS输出响应给用户,性能非常高。
    它的不足之处是要求负载均衡器与RS在一个网络中

1.3、LVS-DR 模式的特点

名称含义
DS(Director Server)前端负载均衡节点服务器
RS(Real SERVER)后端真实服务器
CIP(Client IP)客户端IP地址
VIP(Virtual IP)负载均衡对外提供访问的IP地址,一般负载均衡IP都会通过Viirtual IP实现高可用
RIP(RealServer IP)负载均衡后端的真实服务器IP地址.
  1. Director Server 和 Real Server 必须在同一个物理网络中。
  2. Real Server 可以使用私有地址,也可以使用公网地址。如果使用公网地址,可以通过 互联网对 RIP 进行直接访问。
  3. 所有的请求报文经由 Director Server,但回复响应报文不能经过 Director Server。
  4. Real Server 的网关不允许指向 Director Server IP,即不允许数据包经过 Director S erver。
  5. Real Server 上的 lo 接口配置 VIP 的 IP 地址。

1.4、操作

配置负载调度器

192.168.61.44
虚拟vip:192.168.61.45

   1. #关闭防火墙
      systemctl stop firewalld.service
      setenforce 0
   2. #安装ipvsadm工具
      yum install ipvsadm.x86_64 -y
   3. #配置虚拟IP地址(VIP:192.168.61.44)
      cd /etc/sysconfig/network-scripts/
      cp ifcfg-ens33 ifcfg-ens33:0
      vim ifcfg-ens33:0
      #删除UUID,dns与网关,注意子网
      NAME=ens33:0
      DEVICE=ens33:0
      IPADDR=192.168.61.45
      NETMASK=255.255.255.255
   4. #重启网络服务、启动网卡
      systemctl restart network
      ifup ifcfg-ens33:0
   5. #调整/proc响应参数   
      #对于 DR 群集模式来说,由于 LVS 负载调度器和各节点需要共用 VIP 地址,应该关闭 Linux 内核的重定向参数响应服务器不是一台路由器,那么它不会发送重定向,所以可以关闭该功能
      vi /etc/sysctl.conf
      net.ipv4.ip_forward = 0
      net.ipv4.conf.all.send_redirects = 0
      net.ipv4.conf.default.send_redirects = 0
      net.ipv4.conf.ens33.send_redirects = 0
   6. #刷新配置
      sysctl -p
   7. #加载模块
      modprobe ip_vs
      cat /proc/net/ip_vs
   8. #配置负载分配策略,并启动服务
      ipvsadm-save >/etc/sysconfig/ipvsadm
      systemctl start ipvsadm.service
   9. #清空ipvsadm,并做策略
      ##添加真实服务器-a  指定VIP地址及TCP端口-t   指定RIP地址及TCP端口 -r 指定DR模式-g
      ipvsadm -C
      ipvsadm -A -t 192.168.61.45:80 -s rr
      ipvsadm -a -t 192.168.61.45:80 -r 192.168.61.22:80 -g
      ipvsadm -a -t 192.168.61.45:80 -r 192.168.61.33:80 -g
   10. #保存设置
       ipvsadm
       ipvsadm -ln
       ipvsadm-save >/etc/sysconfig/ipvsadm
       

第一台web服务器

192.168.61.22

1. #关闭防火墙
systemctl stop firewalld.service
setenforce 0
 
2. #安装httpd、开启服务
yum install httpd -y
systemctl start httpd
 
3. #创建一个站点文件
vim /var/www/html/index.html
this is 192.168.61.22
 
3. #添加回环网卡,修改回环网卡名,IP地址,子网掩码
cd /etc/sysconfig/network-scripts/
cp ifcfg-lo ifcfg-lo:0
vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.61.45
NETMASK=255.255.255.255
NETWORK=127.0.0.0
 
systemctl restart network
 
 
4. #设置路由
route add -host 192.168.61.45 dev lo:0
route -n
 
5. #开机执行命令
vim /etc/rc.d/rc.local 
/usr/sbin/route add -host 192.168.61.45 dev lo:0
 
chmod +x /etc/rc.d/rc.local
 
6. #调整 proc 响应参数
#添加系统只响应目的IP为本地IP的ARP请求
#系统不使用原地址来设置ARP请求的源地址,而是物理mac地址上的IP
vim /etc/sysctl.conf
 
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
 
sysctl -p

第二台web服务器

192.168.61.33

1. #关闭防火墙
systemctl stop firewalld.service
setenforce 0
 
2. #安装httpd、开启服务
yum install httpd -y
systemctl start httpd
 
3. #创建一个站点文件
vim /var/www/html/index.html
this is 192.168.61.33
 
3. #添加回环网卡,修改回环网卡名,IP地址,子网掩码
cd /etc/sysconfig/network-scripts/
cp ifcfg-lo ifcfg-lo:0
vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.61.45
NETMASK=255.255.255.255
NETWORK=127.0.0.0
 
systemctl restart network
 
 
4. #设置路由
route add -host 192.168.59.188 dev lo:0
route -n
 
5. #开机执行命令
vim /etc/rc.d/rc.local 
/usr/sbin/route add -host 192.168.59.188 dev lo:0
 
chmod +x /etc/rc.d/rc.local
 
6. #调整 proc 响应参数
#添加系统只响应目的IP为本地IP的ARP请求
#系统不使用原地址来设置ARP请求的源地址,而是物理mac地址上的IP
vim /etc/sysctl.conf
 
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
 
sysctl -p

2、LVS-NAT

工作原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

整个请求过程示意:

  1. client发送request到LVS的VIP上,VIP根据负载算法选择一个Real-server,并记录连接信息到hash表中,然后修改client的
  2. request的目的IP地址为Real-server的地址,将请求发给Real-server;
  3. Real-server收到request包后,发现目的IP是自己的IP,于是处理请求,然后发送reply给LVS;
  4. LVS收到reply包后,修改reply包的的源地址为VIP,发送给client;
  5. 从client来的属于本次连接的包,查hash表,然后发给对应的Real-server;
  6. 当client发送完毕,此次连接结束或者连接超时,那么LVS自动从hash表中删除此条记录。

LVS负载均衡模式—NAT模式特点:

  1. RS和DIP属于同一IP网络中网卡应该使用私网地址,且RS的网关要指向DIP;
  2. 请求和响应报文都要经由director转发;极高负载的场景中,director可能会成为系统瓶颈;
  3. 支持端口映射;
  4. RS可以使用任意操作系统(OS);
  5. DIR需要两块网卡(属于典型的lan/wan)RIP和Director的必须有一块网卡在同一IP网络;
  6. VIP需要配置在DIR接受客户端请求网卡上,且直接对外提供服务。

优点:实现方便简单,也容易理解;

缺点:Director会称为一个优化的瓶颈,所有的报文都要经过Director,因此,负载后端RS的台数在10-20台左右,服务器性能而定,如果Director坏掉,后果很严重,不支持异地容灾;

操作

角色ip/vip
客户端ip:192.168.222.252
第一台web服务器ip:192.168.227.50
第二台web服务器ip:192.168.227.60
lvs服务器ip1:192.168.227.40
ip2:192.168.222.252

lvs服务器

1.添加一块网卡,该网卡是用户可以ping通的网卡
2.开启路由功能
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.conf
3.设置路由策略
#清空策略
ipvsadm -C
#创建集群调度器
ipvsadm -A -t 192.168.222.252:80 -s rr
ipvsadm -a -t 192.168.222.252:80 -r 192.168.227.50:80 -m -w 1
ipvsadm -a -t 192.168.222.252:80 -r 192.168.227.60:80 -m -w 1
#保存策略
ipvsadm-save

3、面试题

lvs原理

LVS通过工作于Linux内核的ipvs模块来实现功能,其主要工作于netfilter 的INPUT链上。
而用户需要对ipvs进行操作配置则需要使用ipvsadm这个工具。
ipvsadm主要用于设置lvs模型、调度方式以及指定后端主机。

3.1、工作原理

  1. LVS-DR原理:请求由LVS接受,它通过修改MAC地址端口号来实现源地址和目标地址的转换,由真实提供服务的服务器(RealServer, RS)直接返回给用户,返回的时候不经过LVS,。

    • 数据包转发:DR模式下需要LVS服务器和RS绑定同一个VIP(虚拟IP), 一个请求过来时,LVS只需要将网络帧的MAC地址修改为某一台RS的MAC,该包就会被转发到相应的RS处理
    • DR模式下,lvs接收请求输入,将请求转发给RS,由RS输出响应给用户,性能非常高。
      它的不足之处是要求负载均衡器与RS在一个网络中
  2. NAT原理: NAT是一种网络协议转换技术,它通过修改IP地址和端口号来实现源地址目标地址的转换。NAT模式请求和响应都需要经过lvs,性能没有DR模式好。

    • LVS需要作为RS的网关,当网络包到达LVS时,LVS做目标地址转换(DNAT),将目标IP改为RS的IP。
    • NAT模式请求和响应都需要经过lvs,性能没有DR模式好

总结起来,LVS-DR通过修改数据包的目标MAC地址IP地址来实现负载均衡,而NAT通过修改IP地址端口号来实现负载均衡。两者的原理和实现方式有所不同,但都能实现在多个后端服务器之间分发请求和返回响应的功能。

3.1、工作模式

  • LVS-DR,LVS-NAT,LVS-FULLNAT,LVS-TUN

Nginx和Lvs的区别

  1. 功能定位:

    • Nginx:Nginx是一款高性能的Web服务器反向代理服务器,主要用于处理HTTP和HTTPS请求。它支持负载均衡、静态文件服务、反向代理、动态缓存、SSL/TLS加密等功能。
    • LVS:LVS是一组基于Linux系统的负载均衡方案,通过修改数据包的目标MAC地址和IP地址来实现负载均衡。它可以应用于多种协议,如TCP、UDP和ICMP,支持四层负载均衡。
  2. 层次不同:

    • Nginx:Nginx是一个应用层负载均衡器,工作在传输层(第四层)和应用层(第七层),通过反向代理方式实现请求的转发和负载均衡。
    • LVS:LVS是一个网络层负载均衡器,工作在传输层(第四层),负责将数据包从客户端直接转发到后端服务器。
  3. 扩展性和性能:

    • Nginx:Nginx以其高性能、低资源消耗和强大的并发处理能力而著名,能够处理大量的并发连接请求,并提供高可用性和稳定性。

    • LVS:LVS是一个可扩展性较好的负载均衡解决方案,可以通过增加后端服务器来实现横向扩展,支持上千个并发连接。但由于工作在网络层,LVS在某些场景下可能会略逊于Nginx。

负载均衡策略

LVS(Linux Virtual Server)是一种开源的负载均衡解决方案,它在Linux内核层面实现了负载均衡功能。LVS调度器支持多种均衡策略(算法),以下是常见的几种:

  1. RR(Round Robin,轮询):将请求依次分配给后端服务器,确保每个服务器都能平均获得请求。与HAProxy中的轮询算法类似。
  2. WRR(Weighted Round Robin,加权轮询):可以为不同的后端服务器分配不同的权重,使得某些服务器处理更多的请求数量。
  3. LC(Least Connections,最少连接):该算法会优先将请求分配给当前负载最轻的服务器,即连接数最少的服务器。和HAProxy中的最少连接算法类似。
  4. WLC(Weighted Least Connections,加权最少连接):类似于LC算法,但是可以通过给每个后端服务器配置不同的权重,使得部分服务器处理更多的连接。
  5. LBLC(Locality-Based Least Connections,基于局部性的最少连接):该算法考虑到客户端IP地址,将请求始终路由到之前已经处理过该客户端请求的服务器上。这样可以提高应用程序的性能,并减少会话状态的切换。
  6. DH(Destination Hashing,目标地址哈希):根据目标IP地址进行哈希计算,将请求发送到对应的服务器。这种方式可以确保相同的目标IP始终被分配到同一台服务器上。
ipvsadm -A -t <虚拟 IP 地址>:<端口号> -s rr

-A 选项表示要添加一个新的虚拟服务器(Virtual Server),用于将流量分发到后端真实服务器(Real Server)。

-t 选项指定要添加的虚拟服务器的地址和端口号。你需要替换 <虚拟 IP 地址>:<端口号> 为你要使用的实际 IP 地址和端口号。

这些均衡策略可以根据不同的场景和需求进行选择和配置,以实现负载均衡和提高系统性能。请注意,LVS调度器中的算法相对于HAProxy或其他软件负载均衡器更加基础和底层。

五、Haproxy

1、简介

​ HAProxy 提供高可用性、负载均衡以及基于TCP和HTTP的应用代理,支持虚拟主机,它是免费、快速并且可靠的一种负载均衡解决方案。适合处理高负载站点的 七层 数据请求。类似的代理服务可以屏蔽内部真实服务器,防止内部服务器遭受攻击。

​ HTTP负载均衡器。其功能是用来提供基于cookie的持久性, 基于内容的交换,过载保护的高级流量管制,自动故障切换,以正则表达式为基础的标题控制运行时间,基于Web的报表,高级日志记录以帮助排除故障的应用或网络及其他功能。

1.1、HAProxy特点和优点

  1. 支持原声SSL,同时支持客户端和服务器的SSL.
  2. 支持IPv6和UNIX套字节(sockets)
  3. 支持HTTP Keep-Alive
  4. 支持HTTP/1.1压缩,节省宽带
  5. 支持优化健康检测机制(SSL、scripted TCP、check agent…)
  6. 支持7层负载均衡。
  7. 可靠性和稳定性非常好。
  8. 并发连接 40000-50000个,单位时间处理最大请求 20000个,最大数据处理10Gbps.
  9. 支持8种负载均衡算法,同时支持session保持。
  10. 支持虚拟主机。
  11. 支持连接拒绝、全透明代理。
  12. 拥有服务器状态监控页面。
  13. 支持ACL。

1.2、HAProxy保持会话的三种解决方法

HAProxy为了让同一客户端访问服务器可以保持会话。有三种解决方法:客户端IP、Cookie以及Session。

  1. 通过 客户端IP 进行Hash计算并保存,以此确保当相同IP访问代理服务器可以转发给固定的真实服务器。
  2. 依靠真实服务器发送客户端的 Cookie信息 进行会话保持。
  3. 将保存真实服务器的 Session 以及服务器标识 ,实现会话保持。
    (HAProxy只要求后端服务器能够在网络联通,也没有像LVS那样繁琐的ARP配置)

1.3、HAProxy的balance 常见4种负载均衡算法

  1. 轮询(Round Robin):默认的负载均衡算法,将请求依次分配给后端服务器,确保每个服务器都能平均获得请求。
  2. 加权轮询(static-rr):可以为不同的后端服务器分配不同的权重,使得某些服务器处理更多的请求数量。例如,你可以给性能更好的服务器分配较高的权重,使其处理更多的请求。
  3. 最少连接(Least Connections):该算法会优先将请求分配给当前负载最轻的服务器,即连接数最少的服务器。这样可以确保请求被均匀地分配给服务器,从而提高整体性能。
  4. source:类似于Nginx中的IP Hash。

1.4、HAProxy 主要工作模式

  1. tcp模式:在客户端和服务器之间将建立一个全双工的连接,且不会对7层的报文做任何处理的简单模式。
    通常用于SSL、SSH、SMTP等应用层。
  2. http模式(一般使用):客户端请求在转发给后端服务器之前会被深度分析,所有不与RFC格式兼容的请求都会被拒绝。

1.5、Haproxy 与LVS、Nginx的比较

  1. LVS基于Linux操作系统实现软负载均衡,而Haproxy和Nginx是基于第三方应用实现的软负载均衡
  2. LVS是可实现4层的IP负载均衡技术,无法实现基于目录、URL的转发。而Haproxy和Nginx都可以实现4层和7层技术,Haproxy可提供TCP和Http应用的负载均衡综合解决方案
  3. Haproxy功能强大,但整体性能低于4层模式的LVS负载均衡
  4. Nginx主要用于web服务器或缓存服务器
  5. lvs:当代理的服务器宕机以后,代理服务器请求分发到到该后端服务器,则会出现"未响应"的情况
    haproxy:具有后端监测的功能,当发现代理的服务器宕机以后,会将该服务器在集群中移除额,再转发到正常的服务器

1.6、安装

  1. 安装

    [root@localhost ~]# yum -y install pcre-devel zlib-devel
    [root@localhost ~]# tar -zxvf haproxy-1.4.24.tar.gz -C /usr/src/
    [root@localhost ~]# cd /usr/src/haproxy-1.4.24/
    [root@localhost ~]# make TARGET=linux31 PREFIX=/usr/local/haproxy
    注意:linux31是指linux的内核版本号。
    [root@localhost ~]# make install PREFIX=/usr/local/haproxy
    
  2. 配置haproxy

    [root@localhost ~]# mkdir /etc/haproxy
    [root@localhost ~]# cp /usr/src/haproxy-1.4.24/examples/haproxy.cfg /etc/haproxy/
    [root@localhost ~]# vim /etc/haproxy/haproxy.cfg
    1.将一下代码注释
    # log loghost local0 info
    # redispatch
    #errorfile      503     /etc/haproxy/errors/503.http
    2.创建文件夹
    mkdir /usr/share/haproxy
    3.允许主机绑定非本地ip
    sysctl -e net.ipv4.ip_nonlocal_bind=1
    
  3. 启动haproxy

    [root@localhost ~]# ln -s /usr/local/haproxy/sbin/* /usr/sbin/ //注意软链接的目录
    [root@localhost ~]# cp /usr/src/haproxy-1.4.24/examples/haproxy.init /etc/init.d/haproxy
    [root@localhost ~]# chmod +x /etc/init.d/haproxy 
    [root@localhost ~]# /etc/init.d/haproxy start
    [root@localhost ~]# /etc/init.d/haproxy status
    [root@localhost ~]# netstat -anp | grep haproxy //占用的也是TCP的80端口
    [root@localhost ~]# chkconfig --add haproxy
    [root@localhost ~]# chkconfig haproxy on
    
  4. 添加web服务器集群

    vim /etc/haproxy/haproxy.conf
    # 添加内容
    listen  webcluster 0.0.0.0:80
            option httpchk GET /index.html
            balance roundrobin
            server inst1 192.168.227.50:80 check inter 2000 fall 3
            server inst2 192.168.227.60:80 check inter 2000 fall 3
    
  5. 代理双从数据库

    listen mysql 0.0.0.0:3306
            option mysql-check user haproxy
            mode tcp
            balance roundrobin
            server mysql1 192.168.227.50:3306
            server mysql2 192.168.227.60:3306
    

2、配置文件

HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是global和proxies部分,配置文件对缩进没有要求

-   global:全局配置段
    -   进程及安全配置相关的参数 
    -   性能调整相关参数 
    -   Debug参数
-   proxies:代理配置段
    -   defaults:为frontend, backend, listen提供默认配置 
    -   frontend:前端,相当于nginx中的server {} ;可以有多组
    -   backend:后端,相当于nginx中的upstream {};可以有多组,
    -   listen:同时拥有前端和后端配置,配置简单,生产推荐使用

### global配置

global 配置参数说明

官方文档:http://cbonte.github.io/haproxy-dconv/2.4/configuration.html#3

~~~shell
chroot  #锁定运行目录,把haproxy的进程禁锢在一个文件夹内
deamon 	#以守护进程运行,后台方式运行,在容器中运行的话不要加这个选项
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin process 1 #socket文件,利用它和haproxy通讯,可以发管理指令
user, group, uid, gid   #运行haproxy的用户身份
nbproc   n 				#开启的haproxy worker 进程数,默认进程数是一个,一般和CPU核数相同
#nbthread 1 	#多进程 nbproc配置互斥(版本有关,CentOS8的haproxy1.8无此问题),指定每个haproxy进程开启的线程数,默认为每个进程一个线程
#如果同时启用nbproc和nbthread 会出现以下日志的错误,无法启动服务
#Apr  7 14:46:23 haproxy haproxy: [ALERT] 097/144623 (1454) : config : cannot enable multiple processes if multiple threads are configured. Please use either nbproc or nbthread but not both.

cpu-map 1 0   	#绑定haproxy worker 进程至指定CPU,将第1个work进程绑定至0号CPU
cpu-map 2 1     #绑定haproxy worker 进程至指定CPU,将第2个work进程绑定至1号CPU
maxconn n   	#每个haproxy进程的最大并发连接数,可以是100000,还可以更大一百万
maxsslconn n   	#每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下,不建议配置,可以把ssl连接放到web服务器上
maxconnrate n   #每个进程每秒创建的最大连接数量,控制瞬间并发
spread-checks n #后端server状态check随机提前或延迟百分比时间,可以错开检查时间,建议2-5(20%-50%)之间,默认值0,不随机
pidfile 		#指定pid文件路径,要和service指定的pid路径一样
log 127.0.0.1 local2 info #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个

3、面试题

3.1、参数优化

  • 长连接超时时间
  • 客户端超时时间
  • 守护进程模式

3.2、作用

作用:高可用,负载均衡和用于TCP和基于http的应用程序代理

优点:

  • HAProxy支持数以万计的 并发连接。

  • 同时可以保护你的web服务器不被暴露到网络上。

六、Tomcat

1、简介

  1. tomcat是一个中间件,在B/S架构中,浏览器发出的http请求经过tomcat中间件,转发到最终的目的服务器上,响应消息再通过,tomcat返回给浏览器

  2. tomcat和apache的区别

    tomcat可以认为是apache的扩展

    apache和tomcat都可以做为独立的web服务器来运行。但是apache不能解释java程序(jsp,serverlet)

    Apache是普通服务器,本身只支持html即普通网页。不过可以通过插件支持PHP,还可以与Tomcat连通(单向Apache连接Tomcat,就是说通过Apache可以访问Tomcat资源)

    apache和tomcat是独立的,在通一台服务器上可以集成

2、操作

安装

1.安装tomcat
rm -rf /usr/bin/java
tar zxf apache-tomcat-8.5.35.tar.gz 
mv apache-tomcat-8.5.35 /usr/local/tomcat
tar zxf jdk-8u91-linux-x64.tar.gz 
mv jdk1.8.0_91/ /usr/local/java
echo $PATH

2.设置环境变量
vim /etc/profile
export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export CLASSPATH=$JAVA_HOME/lib:$JRE_HMOE/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

3.刷新环境变量
source /etc/profile
echo $PATH
cd /usr/local/tomcat/bin/
sh startup.sh
netstat -anput | grep 8080

nginx+tomcat+apache

upstream tomcat {
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:8081 weight=1;
    }
server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        root   html;
        index  index.html index.php;
        #           proxy_pass http://nginxserver;
    }
    location ~ \.php$ {
        proxy_pass http://192.168.227.60;
    }
    location ~ \.htm$ {
        proxy_pass http://192.168.227.50;
    }
    location ~ \.jsp$ {
        proxy_pass http://tomcat;
    }
}

3、面试题

Tomcat是什么?

Tomcat 服务器Apache软件基金会项目中的一个核心项目,是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。
Tomcat的缺省端口是多少,怎么修改
默认8080

修改端口号方式

找到Tomcat目录下的conf文件夹

进入conf文件夹里面找到server.xml文件

打开server.xml文件

在server.xml文件里面找到下列信息

把Connector标签的8080端口改成你想要的端口

怎么在Linux上安装Tomcat

先去下载Tomcat的安装包,gz结尾的(代表Linux上的Tomcat)
上传到Linux上,解压
修改端口号,也可以不修改把。如果要修改在server.xml内改
修改好了之后,你就进入你这个tomcat下的bin目录,输入:./startup.sh 这样就启动成功了。

怎么在Linux部署项目

先使用eclipse或IDEA把项目打成.war包,然后上传到Linux服务器,local/tomcat/webapps,在重启Tomcat就行了。

Tomcat的目录结构

/bin:存放用于启动和暂停Tomcat的脚本
/conf:存放Tomcat的配置文件
/lib:存放Tomcat服务器需要的各种jar包
/logs:存放Tomcat的日志文件
/temp:Tomcat运行时用于存放临时文件
/webapps:web应用的发布目录
/work:Tomcat把有jsp生成Servlet防御此目录下

类似Tomcat,发布jsp运行的web服务器还有那些:

1、Resin Resin提供了最快的jsp/servlets运行平台。在java和javascript的支持下,Resin可以为任务灵活选用合适的开发语言。Resin的一种先进的语言XSL(XML stylesheet language)可以使得形式和内容相分离。

2、Jetty Jetty是一个开源的servlet容器,它为基于Java的web内容,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。

3、WebLogic BEA WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。

4、jboss Jboss是一个基于J2EE的开放源代码的应用服务器。 JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用,而不用支付费用。JBoss是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB3的规范。但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或Jetty绑定使用。

tomcat 如何优化?

  • 最大线程连接数 :需要修改conf/server.xml文件,修改里面的配置文件: maxThreads=”150”//Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可 创建的最大的线程数。默认值200。可以根据机器的时期性能和内存大小调整,一般 可以在400-500。最大可以在800左右。

  • 内存优化:启动时告诉JVM我要多大内存 调优方式的话,修改: Windows 下的catalina.bat Linux 下的catalina.sh 修改方式如: JAVA_OPTS=’-Xms256m -Xmx512m’-Xms JVM初始化堆的大小-Xmx JVM堆的最大值 实际参数大

tomcat 有哪几种Connector 运行模式(优化)?

下面,我们先大致了解Tomcat Connector的三种运行模式。

BIO:同步并阻塞 一个线程处理一个请求。缺点:并发量高时,线程数较多,浪费资源。Tomcat7或以下,在Linux系统中默认使用这种方式。 配制项:protocol=”HTTP/1.1”

NIO:同步非阻塞IO 利用Java的异步IO处理,可以通过少量的线程处理大量的请求,可以复用同一个线程处理多个connection(多路复用)。

Tomcat8在Linux系统中默认使用这种方式。 Tomcat7必须修改Connector配置来启动。 配制项:protocol=”org.apache.coyote.http11.Http11NioProtocol” 备注:我们常用的Jetty,Mina,ZooKeeper等都是基于java nio实现.

APR:即Apache Portable Runtime,从操作系统层面解决io阻塞问题。

AIO方式,异步非阻塞IO(Java NIO2又叫AIO) 主要与NIO的区别主要是操作系统的底层区别.可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。

配制项:protocol=”org.apache.coyote.http11.Http11AprProtocol” 备注:需在本地服务器安装APR库。Tomcat7或Tomcat8在Win7或以上的系统中启动默认使用这种方式。Linux如果安装了apr和native,Tomcat直接启动就支持apr。

Tomcat有几种部署方式?

在Tomcat中部署Web应用的方式主要有如下几种:

利用Tomcat的自动部署。

把web应用拷贝到webapps目录。Tomcat在启动时会加载目录下的应用,并将编译后的结果放入work目录下。

Tomcat作为servlet容器,有三种工作模式:

1、独立的servlet容器,servlet容器是web服务器的一部分;
2、进程内的servlet容器,servlet容器是作为web服务器的插件和java容器的实现,web服务器插件在内部地址空间打开一个jvm使得java容器在内部得以运行。反应速度快但伸缩性不足;
3、进程外的servlet容器,servlet容器运行于web服务器之外的地址空间,并作为web服务器的插件和java容器实现的结合。反应时间不如进程内但伸缩性和稳定性比进程内优;
进入Tomcat的请求可以根据Tomcat的工作模式分为如下两类:

Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;
Tomcat作为独立服务器:请求来自于web浏览器;
面试时问到Tomcat相关问题的几率并不高,正式因为如此,很多人忽略了对Tomcat相关技能的掌握,下面这一篇文章整理了Tomcat相关的系统架构,介绍了Server、Service、Connector、Container之间的关系,各个模块的功能,可以说把这几个掌握住了,Tomcat相关的面试题你就不会有任何问题了!另外,在面试的时候你还要有意识无意识的往Tomcat这个地方引,就比如说常见的Spring MVC的执行流程,一个URL的完整调用链路,这些相关的题目你是可以往Tomcat处理请求的这个过程去说的!掌握了Tomcat这些技能,面试官一定会佩服你的!

学了本章之后你应该明白的是:

Server、Service、Connector、Container四大组件之间的关系和联系,以及他们的主要功能点;
Tomcat执行的整体架构,请求是如何被一步步处理的;
Engine、Host、Context、Wrapper相关的概念关系;
Container是如何处理请求的;
Tomcat用到的相关设计模式;

3.1、配置文件有哪些

Tomcat目录:conf bin logs webapps work lib temp

配置文件一般都在conf文件夹里,主要有server.xml,context.xml,tomcat_user.xml,web.xml四个常用配置文件,

  • server主要是服务器设置的,例如端口设置,路径设置。
  • context里设置tomcat数据源,用来连接数据库。
  • tomcat_user主要是用户名和密码的设置。
  • web是默认首页等等之类的设置。

3.2、参数配置

  • 句柄连接数
  • 最大并发数
  • 线程数
  • 请求超时时间
  • 禁止tomcat manager管理入口
  • 关闭shutdown端口

七、Nginx优化

1、nginx状态码

状态码备注
100-199用于指定客户端相对应的某些动作
200-299用于表示请求成功。
300-399用于已经移动的文件并且常用被包含在定位头信息中指定的地址信息
400-499用于指出客户端错误(自己电脑这边的问题)
500-599用于支持服务器错误。(对方的问题)

2、配置文件

2.1、worker进程个数

语法:worker_processes number;
默认:worker_processes 1;
worker 进程的数量会直接影响性能,那么,用户配置多少个 worker 进程才好呢?这实际上与业务需求有关。
每个 worker 进程都是单线程的进程,它们会调用各个模块以实现多种多样的功能。如
果这些模块确认不会出现阻塞式的调用,那么,有多少 CPU 内核就应该配置多少个进程;反之,如果有可能出现阻塞式调用,那么需要配置稍多一些的 worker 进程。

# 工作进程
worker_processes <cpu数量>/auto;
auto:当用户量少的时候会自动降低工作进程

查看CPU个数:cat /proc/cpuinfo |grep "cores"|uniq  
或者:top命令后 按1

比如查到结果是 cpu cores : 4
worker_processes 4;

并用worker_cpu_affinity 配置来绑定 CPU 内核

为什么要绑定 worker 进程到指定的 CPU 内核呢 ? 假定每一个 worker 进程都是非常繁忙的,如果多个 worker 进程都在抢同一个 CPU , 那么这就会出现同步问题 。 反之 , 如果每一 个 worker 进程都独享一个 CPU , 就在内核的调度策略上实现了完全的并发

例如:

2个CPU内核
worker_processes 2;
worker_cpu_affinity 01 10;

2.2、文件描述符

为何需要文件描述符?
原因1 – 资源问题:节约内存资源。服务器上,每个打开的文件都需要消耗内存来管理。

原因2 – 安全问题:如果不限制的话,如果发生情况为,启动一个进程只是无限的创建和打开新的文件,会让服务器崩溃。

打开文件

vim /etc/security/limits.conf
在文件的末尾添加
root soft nofile 65535
root hard nofile 65535
*

2.3、进程限制

worker rlimit nofile 是一个限制并发连接数的参数,它的默认值为 1024。如果网站访问量过大,导致并发连接数超过了这个限制,就会出现 warn 警告提示。

vim /usr/local/nginx/conf/nginx.conf
# 限制进程数
worker rlimit nofile 1024; 

2.4、设置超时时间

八、keepalived高可用

概述:检查web服务器的状态,如果有一台web服务器/mysql服务器宕机或故障,keepalived将故障节点从系统中剔除,当故障恢复的时候自动加入服务器集群中,非常智能化,只需要手动修复坏的节点即可。

1、操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. yum安装的nginx配置文件在

    1. 老版本:/etc/nginx/nginx.conf.defulat
    2. 新版本:/etc/nginx/nginx.conf
  2. 实现代理

    1. 启动nginx Web服务器
    2. 启动apache Web功能
    3. 准备一台nginx代理服务器(实现对两台服务器负载均衡)
  3. keepalived操作

    1. yum安装

      [root@localhost ~]# yum install -y curl gcc openssl-devel libnl3-devel net-snmp-devel
      [root@localhost ~]# yum install -y keepalived
      
    2. 配置文件 /etc/keepalived/keepalived.conf

      vrrp_instance VI_1 {
          state MASTER
          interface ens33
          virtual_router_id 51 #master跟backup的id要保持一直
          priority 100 #master权值高一点
          advert_int 1
          authentication {
              auth_type PASS
              auth_pass 1111
          }
          virtual_ipaddress {
              192.168.227.253/24 #VIP:虚拟ip
          }
      }
      
    3. 注释掉 vrrp_strick 关闭路由策略

2、面试题

Keepalived原理

Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。

在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息,BACKUP不会抢占MASTER,除非它的优先级更高。当MASTER不可用时(BACKUP收不到通告信息)

多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性
由于安全性考虑,VRRP包使用了加密协议进行加密。BACKUP不会发送通告信息,只会接收通告信息

简述Keepalived体系主要模块及其作用?

keepalived体系架构中主要有三个模块,分别是core、check和vrrp。

  • core模块为keepalived的核心,负责主进程的启动、维护及全局配置文件的加载和解析。
  • vrrp模块是来实现VRRP协议的。
  • check负责健康检查,常见的方式有端口检查及URL检查。

简述Keepalived如何通过健康检查来保证高可用?

Keepalived工作在TCP/IP模型的第三、四和五层,即网络层、传输层和应用层。

网络层,Keepalived采用ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包,如果某个节点没有返回响应数据包,则认为此节点发生了故障,并从服务器集群中剔除故障节点。

传输层,Keepalived利用TCP的端口连接和扫描技术来判断集群节点是否正常。如常见的web服务默认端口80,ssh默认端口22等。Keepalived一旦在传输层探测到相应端口没用响应数据返回,则认为此端口发生异常,从而将此端口对应的节点从服务器集群中剔除。

应用层,可以运行FTP、telnet、smtp、dns等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived的工作方式,来设定监测各种程序或服务是否正常,若监测结果与设定的正常结果不一致,将此服务对应的节点从服务器集群中剔除。

Keepalived通过完整的健康检查机制,保证集群中的所有节点均有效从而实现高可用。

出现keepalived脑裂,是什么原因?

由于某些原因,导致两台keepalived高可用服务器在指定时间内,无法检测到对方存活心跳信息,从而导致互相抢占对方的资源和服务所有权,然而此时两台高可用服务器有都还存活。可能出现的原因:

  1. 服务器网线松动等网络故障;
  2. 服务器硬件故障发生损坏现象而崩溃;
  3. 主备都开启了firewalld 防火墙。

九、RabbitMQ

1、面试题

1.1、作用

  • 消息队列,用在分布式系统存储转发消息

1.2、为什么用

应用场景:异步处理,应用解耦,流量削峰

1.3、RabbitMQ是什么东西?

RabbitMQ也就是消息队列中间件,消息中间件是在消息的传息过程中保存消息的容器消息中间件再将消息从它的源中到它的目标中标时充当中间人的作用队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用消息队列不会保留消息,直到可以成功地传递为止,当然,消息队列保存消息也是有期限地

十、MongoDB

1、面试题

1.1、是什么数据库

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写

1.2、优化参数

  • cachesizeGB(缓存大小) 按配额的60%左右配置即可

  • oplogsizeMB (固定集合) 设置为可用disk空间的5%

  • 启用Log Rotation日志切换 防止MongoDB的log文件无限增大,占用太多磁盘空间,使用Log Rotation并及时清理历史日志文件

  • stack size (连接内存优化) Stack设置小一点,比如说1024

  • MongoDB打开文件数优化 设置文件打开描述数量

十一、服务器区别

Nginx

优点

  1. 高性能:Nginx采用事件驱动的异步非阻塞架构,能够处理大量并发连接并保持低的资源消耗。它能够高效地处理高并发请求,适用于负载较重的场景。
  2. 轻量级和低资源消耗:相比于传统的Web服务器,Nginx的内存占用更低,并且能够处理更多的并发连接。这使得Nginx适用于资源有限的环境,如虚拟机、容器等。
  3. 反向代理和负载均衡:Nginx可以作为反向代理服务器,实现请求的转发和负载均衡。它支持多种负载均衡算法,并能根据请求的URI、来源IP等条件进行灵活的请求分发。
  4. 静态内容缓存:Nginx可以作为静态文件服务器,支持文件压缩、断点续传、目录列表等功能。通过将静态文件缓存在内存中,可以提高响应速度和减少后端服务器的负载。
  5. 端口检测:Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。

缺点

  1. Nginx 仅能支持 http、https 和 Email 协议,这样就在适用范围上面小些,这个是它的缺点。
  2. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过 url 来检测。不支持 Session 的直接保持,但能通过 ip_hash 来解决。

Lvs

优点

  1. 抗负载能力强、是工作在网络 4 层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和 cpu 资源消耗比较低。

  2. 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。

  3. 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived。

  4. 无流量,LVS 只分发请求,而流量并不从它本身出去,这点保证了均衡器 IO的性能不会受到大流量的影响。

  5. 应用范围比较广,因为 LVS 工作在 4 层,所以它几乎可以对所有应用做负载均衡,包括 http、数据库、在线聊天室等等

缺点

  1. 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是 Nginx/HAProxy+Keepalived 的优势所在。

  2. 如果是网站应用比较庞大的话,LVS/DR+Keepalived 实施起来就比较复杂了,特别后面有 Windows Server 的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived 就简单多了。

Haproxy

优点

  1. HAProxy 的优点能够补充 Nginx 的一些缺点,比如支持 Session 的保持,Cookie 的引导;同时支持通过获取指定的 url 来检测后端服务器的状态。
  2. 可以通过url进行健康检查;
  3. HAProxy 支持 TCP 协议的负载均衡转发,可以对 MySQL 读进行负载均衡,对后端的 MySQL 节点进行检测和负载均衡,大家可以用LVS+Keepalived 对 MySQL 主从做负载均衡。

缺点

  1. 功能相对较少:相比其他负载均衡软件如Nginx,HAProxy的功能相对较少。HAProxy专注于负载均衡,并提供了一些基本的监控和管理功能,但缺乏诸如静态文件缓存、Web服务器等高级功能。
  2. 正则比nginx弱

Nginx VS Apache

  1. 架构和性能:Nginx采用了异步非阻塞事件驱动架构,而Apache采用了多进程模型。这意味着Nginx在处理高并发请求时,具有更好的性能和资源利用率。
  2. 高并发处理能力:Nginx不需要每一次连接都创建一个线程,更好的利用系统资源,并同时处理大量的并发连接。而Apache使用的是多进程模型,意味着,每当一个请求过来时都会创建一个线程处理请求。
  3. 静态文件服务:Nginx可以高效地提供静态文件的访问,支持 Sendfile 技术,可以直接将文件从磁盘发送到客户端,减少了 CPU 和内存的开销。
  4. 配置和易用性:Apache的配置比较复杂,需要更多的时间和精力来学习和理解。而Nginx的配置相对简单明了,易于上手和管理。
  5. PHP:Nginx 配置简洁, Apache 复杂 ,Nginx 静态处理性能比 Apache 高 3倍以上 ,Apache 对 PHP 支持比较简单,Nginx 需要配合其他后端用 ,Apache 的组件比 Nginx 多 ,现在 Nginx 才是 Web 服务器的首选

综上所述,Nginx在处理高并发、节约内存以及处理静态内容方面表现优秀,适用于构建高性能的Web服务器。而Apache则具有更多的灵活性和功能扩展性,适用于复杂的Web应用场景。选择哪个Web服务器软件要根据具体需求和项目情况来决定。

Nginx VS Lvs

  1. 功能定位

    • Nginx:Nginx是一款高性能的Web服务器反向代理服务器,主要用于处理HTTP和HTTPS请求。它支持负载均衡、静态文件服务、反向代理、动态缓存、SSL/TLS加密等功能。
    • LVS:LVS是一组基于Linux系统的负载均衡方案,通过修改数据包的目标MAC地址和IP地址来实现负载均衡。它可以应用于多种协议,如TCP、UDP,支持四层负载均衡。
  2. 层次不同

    • Nginx:Nginx是一个应用层负载均衡器,工作在传输层(第四层)和应用层(第七层),通过反向代理方式实现请求的转发和负载均衡。七层负载均衡除了具有四层负载均衡的功能外,还能根据应用层特征进行更复杂的负载分发,如会话保持、内容缓存、SSL加速等
    • Lvs:LVS是一个网络层负载均衡器,工作在传输层(第四层),负责将数据包从客户端直接转发到后端服务器。四层负载均衡主要关注网络传输的连接性和数据传输的可靠性,不关心应用层协议和内容。
  3. 静态文件处理

    • Nginx:支持动静分离的操作
    • lvs:不支持
  4. 大文件处理

    • Nginx:而处理该上传的节点刚好在上传过程中出现故障,Nginx 会把上传切到另一台服务器重新处理
  • lvs:而 LVS 就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满
  1. 正则表达式
    • Nginx:支持
    • Lvs:不支持

2、关系型数据库和非关系性数据库的区别?

数据存储方式不同,扩展方式不同,对事物的支持不同

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织。

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

3、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

  • LVS:是基于四层的转发
  • HAproxy:是基于四层和七层的转发,是专业的代理服务器
  • Nginx:是WEB服务器,缓存服务器,又是反向代理服务器,可以做七层的转发

区别:

  • LVS由于是基于四层的转发所以只能做端口的转发
  • 而基于URL的、基于目录的这种转发LVS就做不了

工作选择:

  • HAproxy和Nginx由于可以做七层的转发,所以URL和目录的转发都可以做在很大并发量的时候我们就要选择LVS,像中小型公司的话并发量没那么大选择HAproxy或者Nginx足已,由于HAproxy由是专业的代理服务器配置简单,所以中小型企业推荐使用HAproxy

Nginx

优点

1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
3、配置简单:Nginx安装和配置比较简单,测试起来比较方便,
4、高并发:可以承担高负载压力稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载
度比LVS相对小些。
5、端口检测:Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态
码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支 持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现
故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一
个很大的文件或者很重要的文件的话,用户可能会因此而不满。
6、静态文件:Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应
用服务器,可作为静态网页和图片服务器。
7、反向代理:Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可考虑用其作为反向代理加速器

缺点

1、协议支持少:Nginx能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点

2、不支持URL健康检测:对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测;不支持Session的直接保持,但能通过ip_hash来解决
LVS:使用Linux内核集群实现一个高性能、高可用的负载均衡服务器,它具有很好的可
伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)

LVS

优点

1、抗负载能力强、是工作在网络4层之上仅作分发之用,对内存和cpu资源消耗比较低
2、配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不
需要太多接触,大大减少了人为出错的几率
3、工作稳定,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中
用得最多的还是LVS/DR+Keepalived
4、没有流量的产生,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO
的性能不会收到大流量的影响。
5、应用范围较广,因为LVS工作在4层,所以它几乎可对所有应用做负载均衡,包括
http、数据库、在线聊天室等

缺点

1、不支持动静分离:软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较
强的需求,这个是Nginx/HAProxy+Keepalived的优势所在
2、如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

Haproxy

优点
2、HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持Cookie的引导,同时支持通过获取指定的url来检测后端服务器的状态
3、HAProxy跟LVS类似,本身就只是一款负载均衡软件,单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的

4、HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡
5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:
①roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;

②static-rr,表示根据权重,建议关注;

③leastconn,表示最少连接者先处理,建议关注;

④ source,表示根据请求源IP,这个跟Nginx的IP_hash机制类似 我们用其作为解决session问题的一种方法,建议关注;

⑤ri,表示根据请求的URI;

⑥rl_param,表示根据请求的URl参数’balance url_param’ requires an URL parameter name;

⑦hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求;

⑧rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。

缺点

:Nginx采用了异步非阻塞事件驱动架构,而Apache采用了多进程模型。这意味着Nginx在处理高并发请求时,具有更好的性能和资源利用率。 2. 高并发处理能力:Nginx不需要每一次连接都创建一个线程,更好的利用系统资源,并同时处理大量的并发连接。而Apache使用的是多进程模型,意味着,每当一个请求过来时都会创建一个线程处理请求。 3. 静态文件服务:Nginx可以高效地提供静态文件的访问,支持 Sendfile 技术,可以直接将文件从磁盘发送到客户端,减少了 CPU 和内存的开销。 4. 配置和易用性:Apache的配置比较复杂,需要更多的时间和精力来学习和理解。而Nginx的配置相对简单明了,易于上手和管理。 4. PHP`:Nginx 配置简洁, Apache 复杂 ,Nginx 静态处理性能比 Apache 高 3倍以上 ,Apache 对 PHP 支持比较简单,Nginx 需要配合其他后端用 ,Apache 的组件比 Nginx 多 ,现在 Nginx 才是 Web 服务器的首选

综上所述,Nginx在处理高并发、节约内存以及处理静态内容方面表现优秀,适用于构建高性能的Web服务器。而Apache则具有更多的灵活性和功能扩展性,适用于复杂的Web应用场景。选择哪个Web服务器软件要根据具体需求和项目情况来决定。

Nginx VS Lvs

  1. 功能定位

    • Nginx:Nginx是一款高性能的Web服务器反向代理服务器,主要用于处理HTTP和HTTPS请求。它支持负载均衡、静态文件服务、反向代理、动态缓存、SSL/TLS加密等功能。
    • LVS:LVS是一组基于Linux系统的负载均衡方案,通过修改数据包的目标MAC地址和IP地址来实现负载均衡。它可以应用于多种协议,如TCP、UDP,支持四层负载均衡。
  2. 层次不同

    • Nginx:Nginx是一个应用层负载均衡器,工作在传输层(第四层)和应用层(第七层),通过反向代理方式实现请求的转发和负载均衡。七层负载均衡除了具有四层负载均衡的功能外,还能根据应用层特征进行更复杂的负载分发,如会话保持、内容缓存、SSL加速等
    • Lvs:LVS是一个网络层负载均衡器,工作在传输层(第四层),负责将数据包从客户端直接转发到后端服务器。四层负载均衡主要关注网络传输的连接性和数据传输的可靠性,不关心应用层协议和内容。
  3. 静态文件处理

    • Nginx:支持动静分离的操作
    • lvs:不支持
  4. 大文件处理

    • Nginx:而处理该上传的节点刚好在上传过程中出现故障,Nginx 会把上传切到另一台服务器重新处理
  • lvs:而 LVS 就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满
  1. 正则表达式
    • Nginx:支持
    • Lvs:不支持

2、关系型数据库和非关系性数据库的区别?

数据存储方式不同,扩展方式不同,对事物的支持不同

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织。

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

3、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

  • LVS:是基于四层的转发
  • HAproxy:是基于四层和七层的转发,是专业的代理服务器
  • Nginx:是WEB服务器,缓存服务器,又是反向代理服务器,可以做七层的转发

区别:

  • LVS由于是基于四层的转发所以只能做端口的转发
  • 而基于URL的、基于目录的这种转发LVS就做不了

工作选择:

  • HAproxy和Nginx由于可以做七层的转发,所以URL和目录的转发都可以做在很大并发量的时候我们就要选择LVS,像中小型公司的话并发量没那么大选择HAproxy或者Nginx足已,由于HAproxy由是专业的代理服务器配置简单,所以中小型企业推荐使用HAproxy

Nginx

优点

1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
3、配置简单:Nginx安装和配置比较简单,测试起来比较方便,
4、高并发:可以承担高负载压力稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载
度比LVS相对小些。
5、端口检测:Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态
码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支 持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现
故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一
个很大的文件或者很重要的文件的话,用户可能会因此而不满。
6、静态文件:Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应
用服务器,可作为静态网页和图片服务器。
7、反向代理:Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可考虑用其作为反向代理加速器

缺点

1、协议支持少:Nginx能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点

2、不支持URL健康检测:对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测;不支持Session的直接保持,但能通过ip_hash来解决
LVS:使用Linux内核集群实现一个高性能、高可用的负载均衡服务器,它具有很好的可
伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)

LVS

优点

1、抗负载能力强、是工作在网络4层之上仅作分发之用,对内存和cpu资源消耗比较低
2、配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不
需要太多接触,大大减少了人为出错的几率
3、工作稳定,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中
用得最多的还是LVS/DR+Keepalived
4、没有流量的产生,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO
的性能不会收到大流量的影响。
5、应用范围较广,因为LVS工作在4层,所以它几乎可对所有应用做负载均衡,包括
http、数据库、在线聊天室等

缺点

1、不支持动静分离:软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较
强的需求,这个是Nginx/HAProxy+Keepalived的优势所在
2、如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

Haproxy

优点
2、HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持Cookie的引导,同时支持通过获取指定的url来检测后端服务器的状态
3、HAProxy跟LVS类似,本身就只是一款负载均衡软件,单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的

4、HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡
5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种:
①roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;

②static-rr,表示根据权重,建议关注;

③leastconn,表示最少连接者先处理,建议关注;

④ source,表示根据请求源IP,这个跟Nginx的IP_hash机制类似 我们用其作为解决session问题的一种方法,建议关注;

⑤ri,表示根据请求的URI;

⑥rl_param,表示根据请求的URl参数’balance url_param’ requires an URL parameter name;

⑦hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求;

⑧rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。

缺点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值