暂时未有相关云产品技术能力~
如何选择一块真正“好用的、性能高”的远程控制软件@[TOC]无论是开发人员、运维人员、测试人员,还是非从事互联网工作的其他人员,在工作中肯定会存在需要远程控制其他电脑的需求。比如下面几个经常会遇到的场景:例如今天开会使用的报表是昨日在家中加班完成的,但是忘记拷贝到U盘,马上就要开会了,文件却不在手里,从而影响工作。当平台出现了故障,而运维却不在工位,也不在家中,手里没有电脑办公。开发人员在公司、家写了某个功能的代码, 但是没有把代码传到正在使用的电脑上。远程办公,家里有电脑,公司的电脑不想带回去,太麻烦。我们都是知识类博主,当粉丝按照我们写的文章学习时,遇到了问题需要我们的支持。基于以上这些场景,我们可以实现准备有一款好用的远程控制软件,只要双方电脑都能上网,无论在何时何地,都可以轻松的连接被控端,根据需要去操作电脑。在选择一款远程工具时,需要从一些几个方面去考虑:远程速度使用过程中是否卡顿清晰度是否高延迟速度如何远程软件随着市场的发展,产品越来越多,且都有手机客户端,可以保证我们随时随地都能远程控制,例如常见的向日葵,好几年前就有了,之前我也使用向日葵,但是近2年体验过程中,发现非常卡顿,几乎操作不了被控端,久而久之换成了todesk,但是todesk的app客户端使用起来较为别扭。绕了这么一圈,就不卖关子了,今天就是要给大家推荐一款“好用且性能高”的远程控制软件,它就是Splashtop ,一款非常好用的远程控制软件,性能方面非常强悍。用户评价画风基本是:“画面清晰,延迟很低,价格合理。”影视、游戏、设计行业远程办公,对于远程画面的清晰度和流畅度要求很高,就特别喜欢 Splashtop。Splashtop远程控制软件的特性Splashtop远程软件的数据传输由 AES-256 和 TLS 加密;具备双因素验证、单点登录、设备认证等安全功能;符合 SOC2、GDPR、CCPA、HIPAA、PCI 等行业标准或法规要求。Splashtop远程软件支持跨平台、跨设备、跨系统远程互联,随心所欲;支持 Windows、Mac、Linux、iOS、安卓等主流平台进行远程控制。Splashtop远程软件的画面清晰、快速流畅,画质高达4K 60帧,低延迟、不卡顿。高性能引擎让用户可以流畅运行视频编辑、图形设计、动画、编码等专业软件。在低带宽的网络环境下,也能维持稳定连接。无论是运维、开发、传输文件、远程控制玩游戏,Splashtop软件绝对是最强的体现,极高的画质,流畅的运行,在远程控制过程中也会大大提升我们的效率,节约部分时间。Splashtop远程控制软件与其他主流远程软件的区别主要与Teamviewer、向日葵进行对比。一、产品对比Teamviewer 来自德国,成立于2005年,在全球各大洲都有分部,客户遍及全球。用户3.2亿,妥妥的行业龙头。特点是性能好,价格贵,企业用户比较多。Splashtop 来自美国,成立于2006年,在全球各大洲都有分部,客户遍及全球。用户量3000万,在欧美日很流行,国内知名度相对低一点。特点是性能好,价格不贵,经常会被作为 Teamviewer 的平替。向日葵来自中国,成立于2006年,主要在中国范围经营。客户量5000万,号称国货之光,在国内耕耘的比较好。特点是免费个人版比较好用,操作方便;很多个人用户都是向日葵和 Teamviewer 换着用。二、性能对比性能这块,Teamviewer 和 Splashtop 都很强,画面清晰度、流畅度都很好。巧的是它们的某些核心算法也比较接近,用了一个比较讨巧的算法,节省带宽提高流畅度,因此在远程办公、远程运维的场景下很给力。向日葵在性能方面算是弱项,在网上被诟病的也比较多。三、安全性对比这三个都是行业里面的老品牌、大品牌,整体上还是值得信赖的。Teamviewer、向日葵都曾爆出过安全漏洞,Splashtop 目前新闻上没怎么看到过安全漏洞。Splashtop 在安全方面做的比较好,数据传输由 AES-256 和 TLS 加密;具备双因素验证、单点登录、设备认证等安全功能。Splashtop 控制端和被控端都是独立软件,连接需要设备验证、两步验证,虽然麻烦了点,但是安全性更有保障。Splashtop远程软件的最后说明Splashtop远程控制软件可以用于企业使用,官网地址:https://www.splashtop.cn/cn/。Splashtop Inc. 成立于2006年,总部位于硅谷,在杭州、台北、东京、新加坡、阿姆斯特丹等地设有分支机构。Splashtop 为全球的跨国企业和中小型企业、教育机构、托管服务供应商(MSP)和个人提供安全且易于管理的远程控制和远程支持软件及服务。经过17年的发展,Splashtop 现在拥有3000万全球用户、20万企业用户,支持会话超过8亿次。浪桥科技(杭州)有限公司成立于2007年,是 Splashtop Inc. 在中国的全资子公司。
MySQL数据库主从复制集群原理概念以及搭建流程1.MySQL主从复制集群的核心概念1.1.什么是主从复制集群主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。MySQL 复制的优点主要包含以下三个方面:主库出现问题,可以快速切换到从库提供服务。实现读写分离,降低主库的访问压力。可以在从库中执行备份,以避免备份期间影响主库服务。1.2.主从复制集群中的专业术语在MySQL主从复制集群中,主要分为两大部分:文件、线程。文件:主库Binlog:二进制日志。从库relay-log:中继日志,主库推送过来的Binlog日志都存放在中继日志中。master.info:从库复制主库的信息文件,记录着主库的地址、用户、Binlog等信息。relay-log.info:中继日志的信息文件,该文件记录了上次执行relay-log的位置等信息。线程:主库binlog_dump_thread:二进制日志投递线程,主要将二进制日志发送给从库的线程。从库IO_Thread:从库的IO线程,用于请求和接收主库的Binlog二进制日志。SQL_Thread:从库的SQL线程,用于将主库发来的二进制日志在数据库中进行数据复制。1.3.主从复制集群工作原理MySQL主从复制集群的工作原理主要围绕前面提到的文件和线程。MySQL主从复制集群的原理:1)首先从库执行change master to将连接主库的配置信息记录到master.info文件中,此时从库上会开启两个线程:I/O线程和SQL线程。2)从库上的I/O线程会从master.info文件中读取主库的连接信息。3)从库I/O线程获取到主库的信息后,会与主库进行身份认证,然后建立连接。4)当从库I/O线程成功连接到主库后,主库会立即给从库分配一个binlog_dump_thread线程,用于推送Binlog日志到从库。5)从库I/O线程会根据master.info中记录的Binlog信息(Binlog日志文件、标识位号)与主库的binlog_dump_thread线程请求最新的Binlog日志。6)这时主库的binlog_dump_thread线程就会去查询是否产生了新的Binlog日志,如果产生了新的Binlog日志,会截取最新的Binlog日志然后推送给从库的I/O线程。7)从库的I/O线程接收到主库推送的Binlog日志后,会现将其存放在内存的TCP/IP缓存中,然后告知主库的binlog_dump_thread线程,Binlog日志已收到。8)此时从库的I/O线程会去更新master.info文件中的Binlog位置点信息,记录最新的Binlog标识号。9)然后从库的I/O线程会将主库推送的Binlog日志写入到磁盘上的relay-log文件中。10)最后由从库的SQL线程读取relay-log.ifno文件,获取relay-log最新的位置点,然后根据的位置点去relay-log中执行最新的Binlog日志,执行完成后会再次更新relay-log.info文件中记录的relay-log位置点。这就是完整的主从复制工作原理。简单来说MySQL主从复制的原理就是,从库的I/O线程读取连接主库的配置信息,然后去连接主库开始主从同步,当I/O线程连接上主库后,主库会立即给I/O线程分配一个Dump线程,用于推送Binlog日志到从库,此时I/O线程会根据master.info文件中记录的Binlog信息,向主库的Dump线程请求最新的BInlog,Dump线程查询到有最新的Binlog产生,会将最新的Binlog截取,然后推送给从库的I/O线程,I/O线程收到Binlog日志后,将其存放在内存的TCP/IP缓存中,然后更新master.info文件中最新的Binlog信息,紧接着将Binlog日志写入到relay-log中,最后由从库的SQL线程从relay-log.info中读取relay-log的位置号,然后执行relay-log中最新的Binlog日志,执行完成后,再次更新relay-log.info中的relay-log位置号,以便于下次再relay-log中读取最新的Binlog日志。relay-log日志会通过MySQL中的其他线程定期清理。1.4.主从复制中的小细节从上面说的主从复制原理来看,好像每次都是从库向主库去请求新数据,那么什么时候从库才应该向主库请求呢?请求的频率如何?其实是这样的:当主库上产生了新的事务,更新到Binlog日之后,会给binlog_dump_thread线程发送一个“信号”,binlog_dump_thread线程会与从库的I/O线程一直建立连接,binlog_dump_thread线程就会通知从库的I/O线程有新数据产生了,这时从库的I/O线程就带着master.info中记录的最新Binlog标识位号,向binlog_dump_thread线程请求最新的Binlog,然后完成数据同步。MySQL主从复制第一次复制时,是按照上面说到的10步完成的,第二次复制时,只需要等待主库的binlog_dump_thread线程向从库的I/O线程发送信号,然后I/O线程去请求最新的Binlog,最后由SQL线程复制数据即可。1.5.搭建主从复制集群的前提条件搭建MySQL主从复制集群的前提条件如下:首先需要准备多个MySQL实例,最少两个MySQL实例,能够实现一主一从的架构,可以在多个服务器中分布部署独立的MySQL节点,也可以在一台服务器中部署多个MySQL实例。每个MySQL实例都需要由单独的sever_id。身为主库角色的MySQL实例需要开启二进制日志,从库在特定场景下需要开启。主库需要授权一个专门的用户作为主从复制的用户。如果主库是一个运行很多年的数据库,突然要升级为主从复制集群,最好先将主库的数据同步一份到从库中。开启专用的复制线程。1.6.MySQL主从复制集群的架构信息本次主从复制的架构是一主两从的结构。IP主机名端口角色server_id192.168.20.11mysql-13306主库1192.168.20.12mysql-23306从库2192.168.20.12mysql-23307从库32.搭建MySQL多实例环境再搭建MySQL主从复制集群之前,首先搭建出多个MySQL实例,由于服务器有限,因此通过两台机器模拟出一主两从的环境。主从复制集群中有一个节点开启了gtid,所有的节点都需要开启gtid,否则主从将不能同步。2.1.在mysql-1中搭建身为主库的MySQL实例mysql-1服务器中的3306端口的MySQL实例再前面已经搭建完成了,就是我们一直在使用的数据库实例,里面有数据,更加方便演示主从集群,下面只是提供一下搭建过程的步骤。注意每个MySQL节点的server_id都要设置成不同的,如果你的一主两从都是单独在不同服务器中部署的,那么直接参考本小结的数据库实例安装即可,不用再看多实例的步骤了。 1.解压MySQL [root@mysql-1 ~]# tar xf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ [root@mysql-1 ~]# mv /usr/local/mysql-5.7.36-linux-glibc2.12-x86_64 /usr/local/mysql 2.设置MySQL的环境变量 [root@mysql-1 ~]# vim /etc/profile export MYSQL_HOME=/usr/local/mysql export PATH=$MYSQL_HOME/bin:$PATH export LD_LIBRARY_PATH=:/usr/local/mysql/lib 3.创建mysql用户 [root@mysql-1 ~]# groupadd -r mysql [root@mysql-1 ~]# useradd -M -r -s /sbin/nologin -g mysql mysql 4.准备数据目录 [root@mysql-1 ~]# mkdir /data/mysql [root@mysql-1 ~]# chown -R mysql. /data/mysql 5.初始化数据库 [root@mysql-1 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql 6.准备mysql配置文件 [root@mysql-1 ~]# vim /etc/my.cnf [mysqld] user=mysql port=3306 server_id=1 #每个MySQL数据库的server_id都设置成不同的 basedir=/usr/local/mysql datadir=/data/mysql log_bin=mysql-bin gtid-mode=on enforce-gtid-consistency=true socket=/tmp/mysql.sock log_error=/data/mysql/mysql_err.log character-set-server=utf8 [mysql] socket=/tmp/mysql.sock 7.准备服务管理脚本 [root@mysql-1 ~]# vim /etc/systemd/system/mysqld.service [Unit] Description=MySQL Server Documentation=man:mysqld(8) Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf LimitNOFILE = 5000 8.启动数据库 [root@mysql-1 ~]# systemctl daemon-reload [root@mysql-1 ~]# systemctl start mysqld 9.设置root密码 [root@mysql-1 ~]# mysqladmin -u root -P 3306 password '123456' 10.登陆数据库 [root@mysql-1 ~]# mysql -uroot -p123456 mysql>2.2.在mysql-2中搭建MySQL多实例由于服务器数量有限,在mysql-2这台服务器中分别搭建两个从库。2.2.1.安装数据库软件 1.解压MySQL [root@mysql-2 ~]# tar xf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ [root@mysql-2 ~]# mv /usr/local/mysql-5.7.36-linux-glibc2.12-x86_64 /usr/local/mysql 2.设置MySQL的环境变量 [root@mysql-2 ~]# vim /etc/profile export MYSQL_HOME=/usr/local/mysql export PATH=$MYSQL_HOME/bin:$PATH export LD_LIBRARY_PATH=:/usr/local/mysql/lib 3.创建mysql用户 [root@mysql-2 ~]# groupadd -r mysql [root@mysql-2 ~]# useradd -M -r -s /sbin/nologin -g mysql mysql2.2.1.搭建第一个3306从库的MySQL实例搭建第一个从库实例,端口号为3306,server_id为2,数据路径为/data/mysql3306。 1.创建3306从库的数据目录 [root@mysql-2 ~]# mkdir /data/mysql3306 [root@mysql-2 ~]# chown -R mysql.mysql /data/mysql3306/ 2.准备3306从库的配置文件 [root@mysql-1 ~]# vim /etc/my3306.cnf [mysqld] user=mysql port=3306 server_id=2 #每个MySQL数据库的server_id都设置成不同的 basedir=/usr/local/mysql datadir=/data/mysql3306 log_bin=/data/mysql3306/mysql-bin gtid-mode=on enforce-gtid-consistency=true socket=/data/mysql3306/mysql.sock log_error=/data/mysql3306/mysql_err.log character-set-server=utf8 [mysql] socket=/data/mysql3306/mysql.sock 3.初始化3306从库 [root@mysql-2 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql3306 4.准备服务管理脚本 [root@mysql-1 ~]# vim /etc/systemd/system/mysqld3306.service [Unit] Description=MySQL Server Documentation=man:mysqld(8) Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3306.cnf LimitNOFILE = 5000 5.启动数据库 [root@mysql-1 ~]# systemctl daemon-reload [root@mysql-1 ~]# systemctl start mysqld3306 6.设置root密码 [root@mysql-2 ~]# mysqladmin -u root -P 3306 -S /data/mysql3306/mysql.sock password '123456' 7.登陆数据库 [root@mysql-2 ~]# mysql -uroot -p123456 -P3306 -S /data/mysql3306/mysql.sock mysql>2.2.2.搭建第二个3307从库的MySQL实例搭建第一个从库实例,端口号为3306,server_id为2,数据路径为/data/mysql3306。 1.创建3307从库的数据目录 [root@mysql-2 ~]# mkdir /data/mysql3307 [root@mysql-2 ~]# chown -R mysql.mysql /data/mysql3307/ 2.准备3307从库的配置文件 [root@mysql-1 ~]# vim /etc/my3307.cnf [mysqld] user=mysql port=3307 server_id=3 #每个MySQL数据库的server_id都设置成不同的 basedir=/usr/local/mysql datadir=/data/mysql3307 log_bin=/data/mysql3307/mysql-bin gtid-mode=on enforce-gtid-consistency=true socket=/data/mysql3307/mysql.sock log_error=/data/mysql3307/mysql_err.log character-set-server=utf8 [mysql] socket=/data/mysql3307/mysql.sock 3.初始化3307从库 [root@mysql-2 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql3307 4.准备服务管理脚本 [root@mysql-1 ~]# vim /etc/systemd/system/mysqld3307.service [Unit] Description=MySQL Server Documentation=man:mysqld(8) Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3307.cnf LimitNOFILE = 5000 5.启动数据库 [root@mysql-1 ~]# systemctl daemon-reload [root@mysql-1 ~]# systemctl start mysqld3307 6.设置root密码 [root@mysql-2 ~]# mysqladmin -u root -P 3307 -S /data/mysql3307/mysql.sock password '123456' 7.登陆数据库 [root@mysql-2 ~]# mysql -uroot -p123456 -P3307 -S /data/mysql3307/mysql.sock mysql>2.3.MySQL多个节点搭建完毕MySQL多个节点已经搭建完毕了,下面来查询每个实例的server_id。3.配置MySQL主从复制集群MySQL数据库的多个实例节点已经搭建完成了,下面将这些搭建的数据库实例配置成主从复制集群(一主两从)。IP主机名端口角色192.168.20.11mysql-13306主库192.168.20.12mysql-23306从库192.168.20.12mysql-23307从库配置MySQL主从复制集群的大致步骤:主库开启Binlog日志,从库复制主库数据要通过Binlog进行复制。主库创建专门用作主从复制的用户。将主库数据进行备份,再从库中恢复。配置从库连接主库的复制信息。启动主从复制集群。3.1.在主库开启Binlog二进制日志主库已经开启了Binlog二进制日志,我们来查一下。 mysql> show variables like '%log_bin%'; +---------------------------------+-----------------------------+ | Variable_name | Value | +---------------------------------+-----------------------------+ | log_bin | ON | | log_bin_basename | /data/mysql/mysql-bin | | log_bin_index | /data/mysql/mysql-bin.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | | sql_log_bin | ON | +---------------------------------+-----------------------------+ 6 rows in set (0.01 sec)从库复制主库数据,都是通过Binlog进行传输和恢复的。3.2.在主库上创建主从复制的用户 mysql> grant replication slave on *.* to replicas@'192.168.20.%' identified by '123456';3.3.将主库数据备份并在从库中进行还原如果是运行很久的主库,要升级为主从复制集群,那么建议将主库上的数据备份还原到从库上,避免从库一次性同步很多数据,浪费性能。 [root@mysql-1 ~]# mysqldump -uroot -p123456 -A --master-data=2 -R -E --triggers --single-transaction > all_db.sql在192.168.20.12的两个从库中还原主库的备份数据。 1.将备份上传到从库的服务器上 [root@mysql-1 ~]# scp -rp all_db.sql root@192.168.20.12:/root 2.3306从库还原主库备份数据 [root@mysql-2 ~]# mysql -uroot -p123456 -P3306 -S /data/mysql3306/mysql.sock mysql> set sql_log_bin=0; mysql> source /root/all_db.sql; 3.3307从库还原主库备份数据 [root@mysql-2 ~]# mysql -uroot -p123456 -P3307 -S /data/mysql3307/mysql.sock mysql> set sql_log_bin=0; mysql> source /root/all_db.sql;3.4.配置从库连接主库的复制信息接下来我们需要配置从库连接主库的信息,包括让从库知道主库的IP、端口号、复制的用户密码、Binlog相关的信息。1)获取主库Binlog的信息从库是通过Binlog复制主库数据的,首先要获取主库Binlog日志的一些信息,包括主库的Binlog日志使用的是哪个、要从Binlog日志中的哪一个事件标识号处开始复制数据。从Binlog的哪一个事件标识号处开始复制数据,尤为关键,因为主库可能运行的时间长了,也有很多的数据,一定要从合适的位置处开始复制数据,要不然也会产生很大的资源浪费。我们是用主库头一天的全库备份,然后还原到从库上的,在主库的备份文件中就记录了从库应该从哪一个Binlog事件标识位处开始复制数据。 vim all_db.sql -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=452;从备份文件中得知,我们应该让从库从主库Binlog事件标识位号452处,开始复制数据。如果主库不是运行很久的,不需要备份数据还原到从库,而是直接搭建的主从复制集群,那么直接可以从主库状态信息那里,获取Binlog的标识位号,在配置主从时,一定要指对Binlog标识位号,否则主从将会失败。 mysql> show master status; +------------------+----------+--------------+------------------+----------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+----------------------------------------+ | mysql-bin.000001 | 452 | | | 4f87bad8-fc67-11ec-be7b-005056b791aa:1 | +------------------+----------+--------------+------------------+----------------------------------------+ 1 row in set (0.00 sec)2)配置从库连接主库进行复制的参数信息配置从库连接主库进行复制的参数有很多,不过只需要记住这一条命令:help change master to即可,在MySQL交互式下执行此命令可以打印出从库连接主库的所有配置参数。 1.3306从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3306 -S /data/mysql3306/mysql.sock mysql> CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_USER='replicas', MASTER_PASSWORD='123456', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=452, MASTER_CONNECT_RETRY=10; 1.3307从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3307 -S /data/mysql3307/mysql.sock mysql> CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_USER='replicas', MASTER_PASSWORD='123456', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=452, MASTER_CONNECT_RETRY=10; 参数解释:参数含义MASTER_HOST主库的地址MASTER_USER主从复制的专用用户MASTER_PASSWORD主从复制用户的密码MASTER_PORT主库的端口号MASTER_LOG_FILE主库的Binlog日志名MASTER_LOG_POS从主库BInlog日志的哪一个标识位处开始复制MASTER_CONNECT_RETRY主从连接失败的重试时间间隔3.5.启动主从复制线程 1.3306从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3306 -S /data/mysql3306/mysql.sock mysql> start slave; 1.3307从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3307 -S /data/mysql3307/mysql.sock mysql> start slave;4.查看主从复制集群状态 1.3306从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3306 -S /data/mysql3306/mysql.sock mysql> show slave status\G; 1.3307从库配置 [root@mysql-2 ~]# mysql -uroot -p123456 -P3307 -S /data/mysql3307/mysql.sock mysql> show slave status\G;当每个从库的IO线程和SQL线程的状态都是Yes,就表示主从复制集群搭建完毕了。MySQL主从配置过程中从库连接主库的配置写错了应该如何解决?只要不执行start slave,再执行一次change master to会覆盖上一次配置。 1.停止主从复制 mysql>stop slave; 2.清空从库连接主库的信息 mysql> reset slave all; 3.重新设置 mysql> CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_USER='replicas', MASTER_PASSWORD='123456', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=452, MASTER_CONNECT_RETRY=10;
[TOC]一、阿里云ECS云主机产品的购买与使用1.ECS云主机产品介绍1.1.ECS简介ECS是阿里云提供的云服务产品(Elastic Compute Service 简称ECS),是一种简单高效、可弹性伸缩的计算服务。当程序在物理服务器运行负荷不够时,通常的做法都是增加服务器,那么增加一台服务器首先要购买硬件、快递设备、安装硬件设备、部署系统、部署应用、接入集群等等一系列流程,完成这些流程通常需要1-2天时间,而我们如果使用云主机,可以实现自动化感知、自动化扩展集群,当我们需要增加机器时,直接购买即可。1.2.ECS服务器配置选型WEB节点:4c X 16GBweb集群节点一般都是4核CPU+16GB的内存。DB节点:4c X 64GB 4c X 32GB数据库节点一般都是4核CPU+64GB内存或者是32GB内存,数据库节点主要是看磁盘。K8S节点:8c X 128GBK8S容器节点,对于内存要求是很高的,内存越大越好。磁盘的选型包括高效云盘、SSD云盘、ESSD云盘,不同云盘的价格、IOPS不同。其中高效云盘的价格最低,经过市场调研,高效云盘是由一些性能不怎么好的磁盘组成的一个存储资源池,高效云盘的IOPS也是较低的。如下图可以看到,同等容量的磁盘,高效云盘的IOPS只有5000,价格为415元,SSD云盘IOPS为16800,相较于高效云盘多了一万多的IOPS,IOPS值越高,磁盘的读写速率就越强,仅仅比高效云盘多了一百多块钱,而ESSD云盘就比较贵了,不过ESSD云盘可以根据性能级别选择不同的IOPS配置,价格也都不一样,ESSD的云盘相对于其他云盘价格偏高。作为数据存储的服务建议采用SSD磁盘。磁盘故障案例:我们在物理机环境运行的MySQL数据库服务器,配置为4c X 64GB,磁盘为SATA读写速率400Mbps,迁移到云主机之后,服务器配置为4c X 64GB,磁盘为高效云盘,读写速率为100Mbps,可以看到云主机和物理机的配置基本上是一样的,只不过是磁盘类型不一样,我们选择的是高效云盘,当MySQL运行之后,会发现服务器的IO_WAIT指标特别高从而影响数据库的性能。物理机原来的磁盘读写速率为400Mbps,迁移到云主机后读写速率为100Mbps,足足差了4倍,肯定会影响磁盘的读写性能。解决方案就是将高效云盘替换成SSD云盘,提高磁盘的IOPS值。dd | hdparm -t /dev/vda1使用此命令查询磁盘的读写速率可以看到如下图,我们再物理机上的磁盘读写速率为600多兆,磁盘为SSD。这个是云主机高效云盘的读写速率,可以看到仅有100多兆。2.使用阿里云控制台访问https://www.aliyun.com/登陆阿里云,点击右上角的控制台。在控制台中可用将我们常用的云产品,点击收藏添加到导航栏,方便我们使用。3.购买ECS云服务器购买ECS云服务器的大致步骤:1.设置ECS的基础设置,包括产品的付费模式、所在地域和可用区、资源配置;2.创建ECS所在地域的VPC网络及交换机设备;3.设置ECS的网络和安全组,指定ECS使用的VPC和交换机,以及开放的端口号;4.设置ECS的系统配置,指定服务器密码、实例的名称;5.设置ECS的分组配置,将ECS服务器放到对应的资源组中,方便查询;6.确认订单信息。3.1.创建ECS云服务实例点击控制台的中的ECS云服务器,进入ECS产品的管理页面。点击实例--->创建实例。3.2.设置ECS的基础配置1)设置ECS的付费模式及地域可用区付费模式设置为按量付费。地域选择为距离我们最近的地域,我们选择华北2也就是北京,可用区任意,我们选择为可用区A。2)设置主机架构及资源配置架构选择x86计算。分类为共享型,共享型中找到共享基本型主机,这个机器比较便宜,我们选择一个1核1G配置的主机。3)设置系统版本以及磁盘配置在镜像这里设置服务器的系统版本,我们使用的操作系统为CentOS,版本为7.9。在存储这里去设置云主机的磁盘,我们选择高效云盘,空间为40GB。到此基础配置已经完成,可以看到价钱是很便宜的,我们可以点击下一步开始配置网络和安全组3.3.设置ECS的网络和安全组3.3.1.创建VPC网络和交换机进入第二网络和安全组的设置后,首先是去配置专有网络,阿里云会为我们选择的地域和可用区默认分配一个VPC网络,如果我们不想使用默认的VPC,就点击图中的前往控制台创建去创建VPC网络,在创建VPC时也会让我们创建交换机,我们也可以点击图中交换机位置的前往控制台创建,单独创建交换机。1)点击创建专有网络2)配置VPC网络VPC所在的地域默认会与ECS的地域进行关联。VPC网络的名称我们就设置为:VPC-HuaBei2-BeijingIPV4的网段配置有注意的点:1、VPC设置的网络一定要尽可能的大,有利于我们后期的扩展,VPC网络设置的IPV4网段相当于设置一个网络范围,用于给不同可用区的交换机分配地址网段。2、每个可用区都有自己的交换机设备,交换机中也需要配置当前可用区的IPV4网段,交换机中设置的网段是最终接入到交换机上的ECS服务器的IP网段地址。3、如果我们在VPC网络中配置的网段很小,比如24位的掩码,24位的掩码只能修改第四位IP段,相当于网段仅有一个,而每个可用区的交换机都要设置成不同的网段,此时就无法为其他可用区的交换机分配网段了,VPC创建时设置的网段是无法修改的,因此我们在配置VPC网络的IPV4网段时一定要尽可能的大,避免后期增加可用区增加很多服务器时无法分配地址。IPV4网络我们设置为:10.0.0.0/8 8位掩码的网络可容纳的主机数是非常庞大的,足够为每一个可用区的交换机分配地址段。2)配置可用区的交换机设置交换机的名称为:SW-Area-A选择交换机所在的可用区:选择可用区A,ECS在可用区A中配置IPV4网络,由于我们在VPC中设置的网络范围很大,因此在交换机这里配置IPV4网段时,就可以设置很多个网段,根据自己的需求,为可用区A的交换机设置一个网段,VPC网络中尽管我们设置的掩码为8,但是在交换机这里设置网段时也最多只能将掩码设置为16个,可以提供65532个IP数,足够我们去使用了。我们将IPV4网段设置为10.1.1.0/24,C类IP地址,即可用区A的交换机可以分配252个IP数,也就是说我们可以在可用区A中创建252台ECS,足够使用了,如果ECS数量更多,我们就可以缩小掩码范围,可以灵活配置。配置完成后点击确定就可以创建VPC专有网络了。3)为可用区B创建交换机刚刚我们在创建VPC时直接为可用区A创建了交换机,交换机可以针对每个可用区去创建,我们来创建可用区B的交换机。点击交换机--->创建交换机专有网络选择为刚刚创建的VPC。设置交换机的名称为SW-Area-B,选择交换机所在的可用区为可用区B。最后设置该交换机的IPV4网段,不同的交换机网段不能一样,设置为10.1.2.0/24,最后点击确定即可。4)查看创建的专有网络和交换机点击专有网络可以看到创建的VPC,点击交换机可以看到创建的交换机3.3.2.配置ECS的网络和安全组1)设置ECS的网络,选择我们创建的VPC网络和交换机。2)不为ECS分配公网IP,公网IP的流量是非常贵的。3)设置安全组,开放需要的端口,3389不属于Linux的端口,我们可以不开放。4)弹性网卡会为我们自动分配IP,选择交换机为我们创建的交换机。3.4.设置CES的系统配置1)设置登录凭据为密码方式,我们选择创建后再设置。2)设置ECS实例的名称,就叫做Web-01。3)添加ECS的描述。4)主机名可以不设置。配置完成后点击下一步进入分组配置。3.5.设置ECS的分组配置分组设置主要为不同的ECS设置不同的资源组,方便我们查询主机。1)点击图中的去创建资源组,为ECS分配一个资源组。2)点击资源组--->创建资源组3)设置资源组的标识和名称。4)为ECS选择资源组,点击下一步进入确认订单。3.6.确认订单信息购买ECS服务器在配置清单里可以看到我们所选的配置,价格还是可以接受的,点击创建实例。ECS实例创建成功。可以在控制台中的云服务器ECS的实例列表中查看我们购买的云服务器,可以在图中看到ECS的内网地址为10.1.1.153,这个地址是随机分配的,我们无法控制。4.管理ECS云服务器4.1.设置ECS服务器的密码点击更多--->密码/密钥--->重置实例密码填写实例密码,然后点击提交。重置完密码后会要求我们重启服务器。4.2.通过阿里云控制台远程连接ECS服务器点击远程连接,使用WorkBench远程连接服务器。选择要远程的ECS实例,输入服务器的账号及密码即可远程登录。此时就已经连接到ECS的终端了,可以执行相应命令。4.3.为ECS绑定公网IP通过Xshell连接云服务器4.3.1.创建弹性公网IP1)在控制台这里搜索弹性公网IP,进入产品管理页面。2)点击创建弹性公网IP3)配置弹性公网IP商品类型选择按量计费,地域和地区一定要选择ECS所在的地域和地区,带宽峰值直接拉满,流量类型选择按使用流量计费。4)确认订单信息然后点击立即开通购买成功后可以在控制台的弹性公网IP这里看到。4.3.2.为ESC实例绑定公网IP点击更多--->网络和安全组--->绑定弹性IP选择购买好的弹性公网IP。弹性IP绑定完成后可以看到ECS的IP地址增加了一个弹性地址,并且弹性公网IP的状态也已经是已分配。4.3.3.使用xshell连接ECS云主机4.4.通过VNC连接服务器VNC就相当于我们VM虚拟机中的操作界面,用于调试服务器,当服务器出问题后就可以在这里进行操作。1)首先来设置VNC的密码2)重启ECS实例ECS重启是非常慢的,大概10-15分钟,也可以在终端中输入reboot进行重启。3)通过VNC连接ECS远程连接方式选择VNC登陆。输入VNC的密码。成功进入。4.5.禁止ping公网IP找到ECS管理页面--->安全组--->找到ECS对应的安全组列表点击手动添加,授权策略为拒绝,设置优先级,协议类型为全部ICMP,设置范围-1/-1,授权对象为0.0.0.0/0,表示禁止所有主机使用ICMP协议请求主机。协议添加成功。已经无法ping公网地址,保护内网安全。5.ECS云服务器磁盘扩容ECS云服务在实际工作中,需要有一个系统盘和一个数据盘,我们刚购买的ECS服务器并没有数据盘,我们可以购买一块云盘,挂载到ECS服务器中,当ECS服务器的数据盘空间不够时,也可以灵活的扩容磁盘容量。5.1.购买一块云盘1)在ECS管理界面找到云盘--->创建云盘2)设置云盘的基本信息及存储空间是否挂载,选择暂不挂载,稍后手动挂载到对应的ECS服务器中。云盘的地域和可用区要和ECS保持一致。云盘的付费方式设置为按量付费。存储选择高效云盘,空间为20GB。勾选云服务器ECS服务条款。3)设置云盘的名称信息当我们有很多ECS实例,并且有很多云盘时,为了方便区分云盘属于哪个ECS,我们需要为云盘起一个具有意义的名称。名称为Web-01-data云盘,描述信息为Web-01实例的data数据盘。将云盘与ECS放在同一个资源组中,最后点击确认订单。4)确认创建5.2.将云盘挂载到ECS1)找到购买好的云盘,点击更多--->挂载。2)选择对应的ECS实例然后执行挂载。3)成功挂载到ECS。5.3.初始化新的云盘并进行挂载阿里云中的云盘挂载到虚拟机中都是vdx,物理机的都是sdx。1.先将磁盘进行分区 [root@iZ2ze7rto8oqydzzemi1enZ ~]# fdisk /dev/vdb Command (m for help): n Select (default p): p Partition number (1-4, default 1): 1 First sector (2048-41943039, default 2048): Command (m for help): w [root@iZ2ze7rto8oqydzzemi1enZ ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 40G 0 disk └─vda1 253:1 0 40G 0 part / vdb 253:16 0 20G 0 disk └─vdb1 253:17 0 20G 0 part 2.格式化分区 [root@iZ2ze7rto8oqydzzemi1enZ ~]# mkfs.xfs /dev/vdb1 3.将分区挂载到/data目录 [root@iZ2ze7rto8oqydzzemi1enZ ~]# mkdir /data [root@iZ2ze7rto8oqydzzemi1enZ ~]# mount /dev/vdb1 /data 4.将分区与目录写入到开机自动挂载的文件中 [root@iZ2ze7rto8oqydzzemi1enZ ~]# vim /etc/fstab /dev/vdb1 /data xfs defaults 0 05.4.为现有云盘扩容1)点击更多--->云盘扩容。2)勾选在线扩容,设置扩容后的容量为30GB,最后勾选扩容须知,确认扩容即可。3)可以看到云盘以及扩容成功,并且ECS挂载的云盘容量也已经是扩容后的空间,但是分区并没有变化。5.5.在ECS中刷新扩容后的云盘容量步骤:首先将云盘取消挂载,然后将现有云盘的分区删除,重新为云盘分区,最后刷新磁盘即可。删除分区是不会清空磁盘中的数据的,数据是保存在磁道并不是分区。1.在/data目录生成数据,测试扩容前后数据是否会丢失 [root@iZ2ze7rto8oqydzzemi1enZ ~]# mkdir /data/{123.txt,456.txt} 2.查看磁盘的大小是否是扩容后的容量 [root@iZ2ze7rto8oqydzzemi1enZ ~]# fdisk -l /dev/vdb Disk /dev/vdb: 32.2 GB, 32212254720 bytes, 62914560 sectors #可以看到容量已经是扩容后的容量了,只是分区没有变。 3.将分区取消挂载 [root@iZ2ze7rto8oqydzzemi1enZ ~]# umount /data/ 4.重新将/dev/vdb1进行分区,获取磁盘全部容量 [root@iZ2ze7rto8oqydzzemi1enZ ~]# fdisk /dev/vdb Command (m for help): d Command (m for help): n Select (default p): p Partition number (1-4, default 1): First sector (2048-62914559, default 2048): Command (m for help): w 5.查看分区容量是否发生变化 [root@iZ2ze7rto8oqydzzemi1enZ ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 253:0 0 40G 0 disk └─vda1 253:1 0 40G 0 part / vdb 253:16 0 30G 0 disk └─vdb1 253:17 0 30G 0 part 6.挂载分区 [root@iZ2ze7rto8oqydzzemi1enZ ~]# mount -a 7.刷新分区空间 [root@iZ2ze7rto8oqydzzemi1enZ ~]# xfs_growfs /data/ 8.验证数据是否丢失 [root@iZ2ze7rto8oqydzzemi1enZ ~]# ll /data/ total 0 drwxr-xr-x 2 root root 6 Jan 13 15:04 123.txt drwxr-xr-x 2 root root 6 Jan 13 15:04 456.txt二、在ESC云服务器中部署KodCloud云盘系统1.KodCloud云盘简介KodaCloud云盘代码下载地址:https://static.kodcloud.com/update/download/kodbox.1.15.zipKodcloud可道云应用程序是一种云盘存储系统,有这Windows操作系统一样的操作界面,最主要的是Kodcloud程序可以根据需求去配置MySQL、Redis、存储设备等等,非常适合我们后面将Kodcloud接入到阿里云的RDS服务以及OSS存储服务。2.部署KodCloud云盘系统2.1.在ECS中安装基本软件1.安装依赖软件 [root@iZ2ze7rto8oqydzzemi1enZ ~]# yum -y install wget vim unzip lrzsz 2.下载Kodcloud源码 [root@iZ2ze7rto8oqydzzemi1enZ ~]# wget https://static.kodcloud.com/update/download/kodbox.1.15.zip2.2.部署Nginx和php-fpm组件1.安装nginx并修改启动用户 [root@iZ2ze7rto8oqydzzemi1enZ ~]# yum -y install nginx [root@iZ2ze7rto8oqydzzemi1enZ ~]# vim /etc/nginx/nginx.conf user nginx; 2.安装php并修改启动用户 [root@iZ2ze7rto8oqydzzemi1enZ ~]# wget http://cdn.xuliangwei.com/php.zip [root@iZ2ze7rto8oqydzzemi1enZ ~]# unzip php.zip [root@iZ2ze7rto8oqydzzemi1enZ ~]# yum -y localinstall php/*.rpm [root@iZ2ze7rto8oqydzzemi1enZ ~]# vim /etc/php-fpm.d/www.conf user = nginx group = nginx2.3.部署云盘系统1.将云盘代码放到指定代码目录 [root@iZ2ze7rto8oqydzzemi1enZ ~]# mkdir /data/code [root@iZ2ze7rto8oqydzzemi1enZ ~]# unzip kodbox.1.15.zip -d /data/code [root@iZ2ze7rto8oqydzzemi1enZ ~]# chown -R nginx.nginx /data/code/ 2.配置Nginx [root@iZ2ze7rto8oqydzzemi1enZ ~]# vim /etc/nginx/conf.d/kodcloud.jiangxl.com.cn.conf server { listen 80; server_name kodcloud.jiangxl.com.cn; location / { root /data/code; index index.php; } location ~ \.php$ { root /data/code; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 3.启动nginx [root@iZ2ze7rto8oqydzzemi1enZ ~]# nginx -t [root@iZ2ze7rto8oqydzzemi1enZ ~]# systemctl start nginx [root@iZ2ze7rto8oqydzzemi1enZ ~]# systemctl enable nginx 4.启动php-fpm [root@iZ2ze7rto8oqydzzemi1enZ ~]# systemctl start php-fpm [root@iZ2ze7rto8oqydzzemi1enZ ~]# systemctl enable php-fpm3.页面安装KodCloud云盘系统3.1.安装并配置云盘系统首先配置hosts文件将域名解析写入到文件中,然后在浏览器中访问http://kodcloud.jiangxl.com.cn/。1)环境检测2)数据库配置数据库可以配置MySQL和Redis,我们现在还没有购买RDS服务,因此先设置为本地。3)设置管理员账号及密码3.2.登陆云盘系统首页如下云盘也有自己的桌面系统阿里云ECS云服务器快照操作1.快照的概念1.1.什么是快照阿里云快照FAQ文档:https://help.aliyun.com/document_detail/25391.html快照就是在某一个时间点,对于云盘的状态做得数据备份,当有天服务器故障时,我们就可以通过快照快速还原系统。阿里云快照服务相当于一种数据备份手段,可以为所有类型的ECS云盘创建快照,用于备份或者恢复云盘的数据,是一种高效的数据容灾手段。我们可以某一个ECS实例的云盘创建快照,然后将快照制作成系统镜像,通过镜像去创建ECS云服务器。阿里云快照分为手动快照和自动快照,快照可以在购买ECS时就进行设置,快照数据也是要花钱的。快照的功能如下图所示:基于云盘创建快照,当云盘故障时快速恢复,可以在同地域和不同的地域将快照制作成系统镜像,从而去创建相同的ECS云服务器,也可以通过快照创建新的云盘,从而去分析问题,也可以将快照复制到其他地域进行使用。1.2.云盘增量快照阿里云的云盘快照第一份快照是全量快照,不备份空数据块,例如我们的云盘有200G存储控制,但是我们只使用了100G,那么第一次快照只会备份使用的100G存储空间的数据,没有使用的空数据块不会备份,当后面每一次进行快照备份时都是增量快照,备份自上一次快照以来变化的数据。创建每一份快照时,文件系统分块检查云盘的数据,只有发生变化的数据块才会被备份到快照中。快照1是第一份快照,备份了该云盘上某一时刻的所有数据。快照2只备份有变化的数据块B1和C1。数据块A和D引用快照1中的A和D。快照3只备份有变化的数据块B2。数据块A和D引用快照1中的A和D,数据块C1引用快照2中的C1。当云盘需要恢复到快照3的状态时,回滚磁盘功能将数据块A、B2、C1和D备份到云盘上,恢复云盘到快照3的状态。假如您需要删除快照2,则快照中的数据块B1被删除,不会删除存在引用关系的数据块C1。当云盘恢复到快照3的状态时,仍可以恢复数据块C1。2.为云盘手动创建快照2.1.创建快照1)在ECS实例管理页面中找到存储与快照--->云盘--->选择要做快照的云盘(根据实际需求对系统盘和数据盘分别做快照备份)--->创建快照。我们对系统盘创建快照。2)设置快照的名称,名称要具有意义,方便查询。我们就设置为Web-01-Kodcloud-第一次快照,然后点击创建。3)快照这里就可以看到我们创建的快照信息。可以看到快照的创建时间、进度和状态,在操作一栏可以对快照进行回滚、创建镜像、复制快照(可以将快照复制到其他地域)等等功能。2.3.模拟ECS服务器故障直接将ECS服务器的/目录删掉。[root@iZ2ze7rto8oqydzzemi1enZ ~]# rm -rf / --no-preserve-root此时ECS云服务器中提供的服务就不可用了。2.3.根据快照回滚磁盘恢复ECS我们刚刚已经创建了快照,下面进行回滚操作。1)首先将ECS实例关机,停止的时间可能会比较长。2)找到ECS对应的快照--->回滚磁盘。3)确认回滚。4)回滚成功后ECS服务器会自动开机2.4.登陆ECS查看系统是否正常系统恢复正常。3.为云盘设置自动创建快照3.1.创建自动快照策略1)点击快照--->自动快照策略--->创建策略。2)设置策略的名称,设置创建快照的时间点,设置创建快照的周期,设置快照的保留时间。名称为快照自动化备份,备份周期为周一到周日的5:00/12:00/22:00,保留时长为7天。3)策略创建成功3.2.为云盘设置自动快照策略1)点击设置自动快照策略2)开启自动快照策略--->关联创建的快照自动备份策略。3.3.在购买时ECS就为云盘设置自动快照策略在基础配置中的快照服务这里,选择我们的自动快照策略,要先创建快照策略。3.4.自动快照已生效
1.环境规划日志系统架构图nginx—>filebeat—>kafka—>logstash—>elasticsearch—>kibana2.部署elasticsearch集群2.1.配置es-1节点1.下载elasticsearch7.6 [root@elk-1 ~]# wget https://mirrors.huaweicloud.com/elasticsearch/7.6.0/elasticsearch-7.6.0-x86_64.rpm [root@elk-1 ~/soft]# rpm -ivh elasticsearch-7.6.0-x86_64.rpm 2.编辑配置文件,配置集群模式 [root@elk-1 ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: elk-application node.name: elk-1 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.210,127.0.0.1 http.port: 9200 cluster.initial_master_nodes: ["elk-1"] discovery.zen.ping.unicast.hosts: ["192.168.81.210","192.168.81.220","192.168.81.230"] discovery.zen.fd.ping_timeout: 120s discovery.zen.fd.ping_retries: 6 discovery.zen.fd.ping_interval: 30s http.cors.enabled: true http.cors.allow-origin: "*" 3.创建数据目录 [root@elk-1 ~]# mkdir /data/elasticsearch/ -p [root@elk-1 ~]# chown -R elasticsearch.elasticsearch /data/elasticsearch/ 4.配置内存锁定 [root@elk-1 ~]# mkdir /etc/systemd/system/elasticsearch.service.d/ [root@elk-1 ~]# vim /etc/systemd/system/elasticsearch.service.d/override.conf [Service] LimitMEMLOCK=infinity 5.启动elasticsearch [root@elk-1 ~]# systemctl daemon-reload [root@elk-1 ~]# systemctl start elasticsearch [root@elk-1 ~]# systemctl enable elasticsearch2.2.配置es-2节点只是配置文件中node.name和network.host不同,其他操作方式一致[root@elk-2 ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: elk-application node.name: elk-2 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.220,127.0.0.1 http.port: 9200 cluster.initial_master_nodes: ["elk-1"] discovery.zen.ping.unicast.hosts: ["192.168.81.210","192.168.81.220","192.168.81.230"] discovery.zen.fd.ping_timeout: 120s discovery.zen.fd.ping_retries: 6 discovery.zen.fd.ping_interval: 30s http.cors.enabled: true http.cors.allow-origin: "*"2.3.配置es-3节点只是配置文件中node.name和network.host不同,其他操作方式一致[root@elk-2 ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: elk-application node.name: elk-3 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.230,127.0.0.1 http.port: 9200 cluster.initial_master_nodes: ["elk-1"] discovery.zen.ping.unicast.hosts: ["192.168.81.210","192.168.81.220","192.168.81.230"] discovery.zen.fd.ping_timeout: 120s discovery.zen.fd.ping_retries: 6 discovery.zen.fd.ping_interval: 30s http.cors.enabled: true http.cors.allow-origin: "*"2.4.使用es-head插件查看集群状态3.部署kibana1.下载kibana rpm包 [root@elk-1 ~]# rpm -ivh kibana-7.6.0-x86_64.rpm 2.配置kibana [root@elk-1 ~]# vim /etc/kibana/kibana.yml server.port: 5601 server.host: "192.168.81.210" server.name: "elk-application" elasticsearch.hosts: ["http://192.168.81.210:9200"] i18n.locale: "zh-CN" [root@elk-1 ~]# systemctl restart kibana [root@elk-1 ~]# systemctl enable elasticsearchkibana部署成功4.部署zookeeper4.1.配置zookeeper-1节点1.下载软件 [root@elk-1 ~]# wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz 2.解压并移动zookeeper [root@elk-1 ~]# tar xf soft/zookeeper-3.4.13.tar.gz -C /data/ [root@elk-1 ~]# mv /data/zookeeper-3.4.13/ /data/zookeeper 3.创建数据目录和日志目录 [root@elk-1 ~]# mkdir /data/zookeeper/{data,logs} 4.准备配置文件 [root@elk-1 ~]# cd /data/zookeeper/conf [root@elk-1 /data/zookeeper/conf]# cp zoo_sample.cfg zoo.cfg [root@elk-1 /data/zookeeper/conf]# vim zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/data DataLogDir=/data/zookeeper/logs clientPort=2181 server.1=192.168.81.210:2888:3888 server.2=192.168.81.220:2888:3888 server.3=192.168.81.230:2888:3888 5.生成节点id文件 #节点id只能保护数字 [root@elk-1 /data/zookeeper]# echo 1 > /data/zookeeper/data/myid4.2.配置zookeeper-2节点与zookeeper-1节点只有配置文件和节点id文件有点不同,其余全一样[root@elk-2 /data/zookeeper/conf]# cat zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/data DataLogDir=/data/zookeeper/logs clientPort=2181 server.1=192.168.81.210:2888:3888 server.2=192.168.81.220:2888:3888 server.3=192.168.81.230:2888:3888 [root@elk-2 /data/zookeeper/conf]# echo 2 > /data/zookeeper/data/myid4.3.配置zookeeper-3节点[root@elk-3 /data/zookeeper/conf]# cat zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/data DataLogDir=/data/zookeeper/logs clientPort=2181 server.1=192.168.81.210:2888:3888 server.2=192.168.81.220:2888:3888 server.3=192.168.81.230:2888:3888 [root@elk-3 /data/zookeeper/conf]# echo 3 > /data/zookeeper/data/myid4.4.启动所有节点zookeeper集群必须保证有两个节点存活,也就是说必须同时要启动两个节点,否则集群将启动不成功,因此要都修改好配置文件后,再统一启动[root@elk-1 /data/zookeeper]# ./bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /data/zookeeper/bin/../conf/zoo.cfg Mode: follower [root@elk-2 /data/zookeeper]# ./bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /data/zookeeper/bin/../conf/zoo.cfg Mode: follower [root@elk-3 /data/zookeeper]# ./bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /data/zookeeper/bin/../conf/zoo.cfg Mode: leader5.部署kafka注意:不要使用kafka2.11版本,有严重的bug,filebeat无法写入数据到kafka集群,写入的协议版本不同,存在问题5.1.配置kafka-1节点1.下载二进制包 [root@elk-1 ~]# wget https://archive.apache.org/dist/kafka/2.0.0/kafka_2.11-2.0.0.tgz 2.安装kafka [root@elk-1 ~/soft]# tar xf kafka_2.13-2.4.0.tgz -C /data/ [root@elk-1 ~]# mv /data/kafka_2.13-2.4.0 /data/kafka 3.修改配置文件 [root@elk-1 ~]# cd /data/kafka [root@elk-1 /data/kafka]# vim config/server.properties broker.id=1 listeners=PLAINTEXT://192.168.81.210:9092 host.name=192.168.81.210 advertised.listeners=PLAINTEXT://192.168.81.210:9092 advertised.host.name=192.168.81.210 num.network.threads=3 num.io.threads=8 socket.send.buffer.bytes=102400 socket.receive.buffer.bytes=102400 socket.request.max.bytes=104857600 log.dirs=/data/kafka/data num.partitions=3 delete.topic.enable=true auto.create.topics.enable=true replica.fetch.max.bytes=5242880 num.recovery.threads.per.data.dir=1 offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3 message.max.byte=5242880 log.cleaner.enable=true log.retention.hours=48 log.segment.bytes=1073741824 log.retention.check.interval.ms=15000 zookeeper.connect=192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 zookeeper.connection.timeout.ms=60000 group.initial.rebalance.delay.ms=0 4.创建数据目录 [root@elk-3 ~]# mkdir /data/kafka/data5.2.配置kafka-2节点只是配置文件不同,其余与kafka-1节点操作一致配置文件需要改的地方:broker.id改成2,表示第二个节点 listeners host.name advertised.listeners advertised.host.name改成本机ip地址[root@elk-2 /data/kafka]# cat config/server.properties broker.id=2 listeners=PLAINTEXT://192.168.81.220:9092 host.name=192.168.81.220 advertised.listeners=PLAINTEXT://192.168.81.220:9092 advertised.host.name=192.168.81.220 num.network.threads=3 num.io.threads=8 socket.send.buffer.bytes=102400 socket.receive.buffer.bytes=102400 socket.request.max.bytes=104857600 log.dirs=/data/kafka/data num.partitions=3 delete.topic.enable=true auto.create.topics.enable=true replica.fetch.max.bytes=5242880 num.recovery.threads.per.data.dir=1 offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3 message.max.byte=5242880 log.cleaner.enable=true log.retention.hours=48 log.segment.bytes=1073741824 log.retention.check.interval.ms=15000 zookeeper.connect=192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 zookeeper.connection.timeout.ms=60000 group.initial.rebalance.delay.ms=05.3.配置kafka-3节点只是配置文件不同,其余与kafka-1节点操作一致配置文件需要改的地方:broker.id改成3,表示第三个节点 listeners host.name advertised.listeners advertised.host.name改成本机ip地址[root@elk-3 /data/kafka]# cat config/server.properties broker.id=3 listeners=PLAINTEXT://192.168.81.230:9092 host.name=192.168.81.230 advertised.listeners=PLAINTEXT://192.168.81.230:9092 advertised.host.name=192.168.81.230 num.network.threads=3 num.io.threads=8 socket.send.buffer.bytes=102400 socket.receive.buffer.bytes=102400 socket.request.max.bytes=104857600 log.dirs=/data/kafka/data num.partitions=3 delete.topic.enable=true auto.create.topics.enable=true replica.fetch.max.bytes=5242880 num.recovery.threads.per.data.dir=1 offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3 message.max.byte=5242880 log.cleaner.enable=true log.retention.hours=48 log.segment.bytes=1073741824 log.retention.check.interval.ms=15000 zookeeper.connect=192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 zookeeper.connection.timeout.ms=60000 group.initial.rebalance.delay.ms=05.4.启动kafka[root@elk-1 ~]# /data/kafka/bin/kafka-server-start -daemon /data/kafka/config/server.properties [root@elk-2 ~]# /data/kafka/bin/kafka-server-start -daemon /data/kafka/config/server.properties [root@elk-3 ~]# /data/kafka/bin/kafka-server-start -daemon /data/kafka/config/server.properties6.测试kafka与zookeeper连接kafka能够产生数据并消费,整个集群就可以使用了1.创建一个topic [root@elk-1 /data/kafka]# ./bin/kafka-topics.sh --create --zookeeper 192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 --replication-factor 1 --partitions 1 --topic testpic Created topic "testpic". 2.查看topic [root@elk-1 /data/kafka]# ./bin/kafka-topics.sh --list --zookeeper 192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 testpic 3.查看topic的描述信息 [root@elk-1 /data/kafka]# ./bin/kafka-topics.sh --describe --zookeeper 192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 --topic testpic 4.使用kafka-console-producer控制台生产数据 [root@elk-1 /data/kafka]# ./bin/kafka-console-producer.sh --broker-list 192.168.81.210:9092,192.168.81.220:9092,192.168.81.230:9092 --topic testpic >test1 >test2 >test3 >test4 >test5 >test6 >test7 >test8 >test9 >test10 5.使用kafka-console-consumer控制台消费数据 [root@elk-1 /data/kafka]# ./bin/kafka-console-consumer.sh --bootstrap-server 192.168.81.210:9092,192.168.81.220:9092,192.168.81.230:9092 --topic testpic --from-beginning test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 #删除一个topic [root@elk-1 /data/kafka]# ./bin/kafka-topics.sh --delete --zookeeper 192.168.81.210:2181 --topic testpic7.配置filebeat收集nginx、tomcat日志并存储到kafka中7.1.安装并配置nginx服务1.安装nginx [root@elk-3 ~]# yum -y install nginx 2.配置nginx日志格式 [root@elk-3 ~]# vim /etc/nginx/nginx.conf http { ·············· log_format main '{"时间":"$time_iso8601",' '"客户端外网地址":"$http_x_forwarded_for",' '"客户端内网地址":"$remote_addr",' '"状态码":$status,' '"传输流量":$body_bytes_sent,' '"跳转来源":"$http_referer",' '"URL":"$request",' '"浏览器":"$http_user_agent",' '"请求响应时间":$request_time,' '"后端地址":"$upstream_addr"}'; access_log /var/log/nginx/access.log main; ·············· } 2.启动nginx [root@elk-3 ~]# systemctl start nginx [root@elk-3 ~]# systemctl enable nginx 4.访问产生日志查看效果 [root@elk-3 ~]# curl 127.0.0.1 [root@elk-3 ~]# tail /var/log/nginx/access.log {"时间":"2021-07-12T11:29:33+08:00","客户端外网地址":"-","客户端内网地址":"127.0.0.1","状态码":200,"传输流量":4833,"跳转来源":"-","URL":"GET / HTTP/1.1","浏览器":"curl/7.29.0","请求响应时间":0.000,"后端地址":"-"}7.2.安装tomcat服务[root@elk-3 ~]# tar xf apache-tomcat-8.5.12.tar.gz -C /data/ [root@elk-3 ~]# mv /data/apache-tomcat-8.5.12/ /data/tomcat [root@elk-3 ~]# /data/tomcat/bin/startup.sh Using CATALINA_BASE: /data/tomcat Using CATALINA_HOME: /data/tomcat Using CATALINA_TMPDIR: /data/tomcat/temp Using JRE_HOME: /usr Using CLASSPATH: /data/tomcat/bin/bootstrap.jar:/data/tomcat/bin/tomcat-juli.jar Tomcat started.7.3.安装filebeat服务[root@elk-3 ~]# rpm -ivh filebeat-7.6.0-x86_64.rpm ```7.4.配置filebeat收集应用日志并存储到kafka1.配置filebeat [root@elk-3 ~]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log #类型为log enabled: true paths: #指定日志所在的路径 - /var/log/nginx/access.log json.keys_under_root: true #支持json格式的日志输出 json.overwriite_keys: true fields: #在日志中增加一个字段,字段为log_topic,值为nginx_access,logstash根据带有这个字段的日志存储到指定的es索引库 log_topic: nginx-access tail_files: true #开启日志监控,从日志的最后一行开始收集 - type: log enabled: true paths: - /data/tomcat/logs/catalina.out multiline.pattern: '^20' #收集tomcat错误日志,从第一个20到下一个20之间的日志整合在一行中显示 multiline.negate: true multiline.match: after fields: log_topic: tomcat-cata tail_files: true output.kafka: #输出到kafka系统 enabled: true hosts: ["192.168.81.210:9092","192.168.81.220:9092","192.168.81.230:9092"] #kafka的地址 topic: '%{[fields][log_topic]}' #指定将日志存储到kafka集群的哪个topic中,这里的topic值是引用在inputs中定义的fields,通过这种方式可以将不同路径的日志分别存储到不同的topic中 partition.round_robin: reachable_only: false required_acks: 1 compression: gzip max_message_bytes: 1000000 2.启动filebeat [root@elk-3 ~]# systemctl start filebeat [root@elk-3 ~]# systemctl enable filebeat7.5.产生程序日志数据观察数据是否存储kafka1.产生程序日志1.产生nginx日志 [root@elk-3 ~]# ab -n 1000 -c 100 http://127.0.0.1/index.html 2.产生tomcat日志 [root@elk-3 ~]# /data/tomcat/bin/shutdown.sh [root@elk-3 ~]# /data/tomcat/bin/startup.sh 2.观察kafka中是否创建对应的topic[root@elk-1 /data/kafka]# ./bin/kafka-topics.sh --list --zookeeper 192.168.81.210:2181,192.168.81.220:2181,192.168.81.230:2181 __consumer_offsets nginx-access testpic tomcat-cata #nginx-access以及tomcat-cata的topic已经创建成功3.观察kafka日志的输出[root@elk-1 /data/kafka]# tail -f logs/kafkaServer.out8.配置logstash从kafka中读取数据并存储到es集群部署logstash,配置logstash从kafka中读取topic数据并存储到es集群8.1.部署logstash服务1.安装logstash [root@elk-3 ~]# rpm -ivh logstash-7.6.0.rpm8.2.配置logstash从kafka读取数据存储到es集群[root@elk-3 ~]# cat /etc/logstash/conf.d/in_kafka_to_es.conf #从kafka中读取日志数据 input { #数据源端 kafka { #类型为kafka bootstrap_servers => ["192.168.81.210:9092,192.168.81.220:9092,192.168.81.230:9092"] #kafka集群地址 topics => ["nginx-access","tomcat-cata"] #要读取那些kafka topics codec => "json" #处理json格式的数据 auto_offset_reset => "latest" #只消费最新的kafka数据 } } #处理数据,去掉没用的字段 filter { if[fields][log_topic] == "nginx-access" { #如果log_topic字段为nginx-access则进行以下数据处理 json { #json格式数据处理 source => "message" #source等于message的 remove_field => ["@version","path","beat","input","log","offset","prospector","source","tags"] #删除指定的字段 } mutate { #修改数据 remove_field => ["_index","_id","_type","_version","_score","referer","agent"] #删除没用的字段 } } if[fields][log_topic] == "tomcat-cata" { #如果log_topic字段为tomcat-cata grok { #解析格式 match => { "message" => "(?<时间>20[0-9]{2}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) \[(?<线程名称>[^\s]{0,})\] (?<日志等级>\w+) (?<类名称>[^\s]{0,}) (?<日志详情>[\W\w]+)" #将message的值增加上一些格式 } } mutate { #修改数据 remove_field => ["_index","_id","_type","_version","_score","referer","agent"] #删除没用的字段 } } } #数据处理后存储es集群 output { #目标端 if[fields][log_topic] == "nginx-access" { #如果log_topic的字段值为nginx-access就存到下面的es集群里 elasticsearch { action => "index" #类型为索引 hosts => ["192.168.81.210:9200","192.168.81.220:9200","192.168.81.230:9200"] #es集群地址 index => "nginx-access-%{+YYYY.MM.dd}" #存储到es集群的哪个索引里 codec => "json" #处理json格式的解析 } } if[fields][log_topic] == "tomcat-cata" { #如果log_topic的字段值为tomcat-cata就存到下面的es集群里 elasticsearch { action => "index" #类型为索引 hosts => ["192.168.81.210:9200","192.168.81.220:9200","192.168.81.230:9200"] #es集群地址 index => "tomcat-cata-%{+YYYY.MM.dd}" #存储到es集群的哪个索引里 codec => "json" #处理json格式的解析 } } }8.3.启动logstash并观察日志[root@elk-3 ~]# nphup /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/in_kafka_to_es.conf &观察日志的输出,已经从nginx-access、tomcat-cata topic中读取了数据并存到了es集群中8.4.查看elasticsearch集群是否增加了对应的索引库es集群已经生成了tomcat-cata以及nginx-access索引库到此为止logstash已经成功从kafka集群读取到日志数据,然后传入到elasticsearch集群不同的索引库9.在kibana上关联elasticsearch索引库浏览日志数据9.1.在kibana上添加nginx-access索引模式1)点击创建索引2)填写索引名采用通配符的方式,填写完点击下一步完成创建即可3)添加一个时间筛选字段4)创建成功9.2.同样方法添加tomcat-cata索引模式9.3.查询nginx-access索引日志数据9.4.查看tomcat-cata索引日志数据10.报错合集10.1.es启动时报错无法指定被请求的地址报错内容如下解决方法:仔细检查配置文件,肯定是某个地址配置错了,我的就是监听地址的ip写错了10.2.filebeat写入数据到kafka api版本报错报错如下:分析解决思路:初步判定为kafka2.11版本问题导致的,换成2.13问题解决
利用zabbix api批量添加监控主机在公司规模很庞大的时候,每次都手动添加监控主机将会很麻烦,我们可以利用zabbix的api去批量添加监控主机本次我们将实现用一台主机虚拟出100台主机,并通过api的方式自动添加监控主机掌握本次方法,无需要了解python,也不需要写python脚本1.获取批量添加主机的api可以从官网取到https://www.zabbix.com/documentation/4.0/zh/manual/api/reference/host/create{ "jsonrpc": "2.0", "method": "host.create", "params": { "host": "192.168.81.180", "interfaces": [ { "type": 1, "main": 1, "useip": 1, "ip": "192.168.81.180", "dns": "", "port": "10050" } ], "groups": [ { "groupid": "15" } ], "templates": [ { "templateid": "10271" } ] }, "auth": "'$token'", "id": 1 }api必要字段说明解释:“host”: “192.168.81.160”, #主机名称“interfaces”: [{undefined“type”: 1, #使用agent客户端“main”: 1, #默认“useip”: 1, #ip地址“ip”: “192.168.81.160”, #agent的地址“dns”: “”,“port”: “10050” #agent端口}],“groups”: [{undefined“groupid”: “15” #主机群组的id}],“templates”: [{“templateid”: “10271” #模板id}]2.创建一百台服务器我们虽然没有一百台服务器,但是我们可以创建100个网卡,且都在一台机器上,有一百个ip即可[root@k8s-master ~]# for i in {100..200} do ifconfig ens33:$i 192.168.81.$i ifconfig ens33 up done3.编写批量添加主机的脚本3.1.将一百台机器的ip写到文件中[root@k8s-master ~]# echo 192.168.81.{100..200} | xargs -n1 > /root/host.txt3.2.在机器上安装zabbix-agent[root@k8s-master ~]# yum -y install zabbix-agent [root@k8s-master ~]# vim /etc/zabbix/zabbix_agentd.conf Server=192.168.81.250 [root@k8s-master ~]# systemctl restart zabbix-agent3.3.编写批量添加主机的脚本[root@k8s-master ~]# vim zabbix_host_creates.sh #!/bin/bash #批量添加zabbix主机 #登陆 token=`echo $json | grep result | awk -F'"' '{print $10}'` #批量添加主机 for ip in `cat /root/host.txt` do curl -s -X POST -H 'Content-Type: application/json' -d ' { "jsonrpc": "2.0", "method": "host.create", "params": { "host": "'$ip'", "interfaces": [ { "type": 1, "main": 1, "useip": 1, "ip": "'$ip'", "dns": "", "port": "10050" } ], "groups": [ { "groupid": "15" } ], "templates": [ { "templateid": "10271" } ] }, "auth": "'$token'", "id": 1 }' http://192.168.81.250/zabbix/api_jsonrpc.php | python -m json.tool done 3.4.执行脚本[root@k8s-master ~]# chmod a+x zabbix_host_creates.sh [root@k8s-master ~]# sh zabbix_host_creates.sh • 1 • 2脚本输出3.5.查看监控主机是否批量创建成功全部为有效状态
1、检测到目标X-Content-Type-Options响应头缺失X-Content-Type-Options HTTP 消息头相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为,换句话说,也就是意味着网站管理员确定自己的设置没有问题。 X-Content-Type-Options响应头的缺失使得目标URL更易遭受跨站脚本攻击。location / { add_header X-Content-Type-Options nosniff; }2、检测到目标X-XSS-Protection响应头缺失HTTP X-XSS-Protection 响应头是 Internet Explorer,Chrome 和 Safari 的一个特性,当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。 X-XSS-Protection响应头的缺失使得目标URL更易遭受跨站脚本攻击。location / { add_header X-XSS-Protection 1; }3、检测到目标Content-Security-Policy响应头缺失HTTP 响应头Content-Security-Policy允许站点管理者控制用户代理能够为指定的页面加载哪些资源。除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。 Content-Security-Policy响应头的缺失使得目标URL更易遭受跨站脚本攻击。location / { add_header Content-Security-Policy "default-src 'self'; style-src * 'unsafe-inline'; img-src * data:; object-src 'self'; script-src * 'unsafe-eval' 'unsafe-inline'; font-src * data:; worker-src * blob:;"; }4、检测到目标Referrer-Policy响应头缺失Web 服务器对于 HTTP 请求的响应头中缺少 Referrer-Policy,这将导致浏览器提供的安全特性失效。 当用户在浏览器上点击一个链接时,会产生一个 HTTP 请求,用于获取新的页面内容,而在该请求的报头中,会包含一个 Referrer,用以指定该请求是从哪个页面跳转页来的,常被用于分析用户来源等信息。但是也成为了一个不安全的因素,所以就有了 Referrer-Policy,用于过滤 Referrer 报头内容,其可选的项有: no-referrer no-referrer-when-downgrade origin origin-when-cross-origin same-origin strict-origin strict-origin-when-cross-origin unsafe-url 漏洞危害: Web 服务器对于 HTTP 请求的响应头中缺少 Referrer-Policy,这将导致浏览器提供的安全特性失效,更容易遭受 Web 前端黑客攻击的影响。location / { add_header Referrer-Policy value; }5、检测到目标X-Permitted-Cross-Domain-Policies响应头缺失Web 服务器对于 HTTP 请求的响应头中缺少 X-Permitted-Cross-Domain-Policies,这将导致浏览器提供的安全特性失效。 当一些在线的 Web Flash 需要加载其他域的内容时,很多 Web 会通过设置一个 crossdomain.xml 文件的方式来控制其跨域方式。很有可能有些开发者并没有修改 crossdomain.xml 文件的权限,但是又有和跨域的 Flash 共享数据的需求,这时候可以通过设置 X-Permitted-Cross-Domain-Policies 头的方式来替代 crossdomain.xml 文件,其可选的值有: none master-only by-content-type by-ftp-filename all 漏洞危害: Web 服务器对于 HTTP 请求的响应头中缺少 X-Permitted-Cross-Domain-Policies,这将导致浏览器提供的安全特性失效,更容易遭受 Web 前端黑客攻击的影响。location / { add_header X-Permitted-Cross-Domain-Policies value; }6、检测到目标X-Download-Options响应头缺失Web 服务器对于 HTTP 请求的响应头中缺少 X-Download-Options,这将导致浏览器提供的安全特性失效。 漏洞危害: Web 服务器对于 HTTP 请求的响应头中缺少 X-Download-Options,这将导致浏览器提供的安全特性失效,更容易遭受 Web 前端黑客攻击的影响。location / { add_header X-Download-Options value; }7、点击劫持:X-Frame-Options未配置点击劫持(ClickJacking)是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。 HTTP 响应头信息中的X-Frame-Options,可以指示浏览器是否应该加载一个 iframe 中的页面。如果服务器响应头信息中没有X-Frame-Options,则该网站存在ClickJacking攻击风险。网站可以通过设置 X-Frame-Options 阻止站点内的页面被其他页面嵌入从而防止点击劫持。location / { add_header X-Frame-Options SAMEORIGIN; }
报错内容:[root@ceph-1 ~]# mount /dev/rbd0 /prod mount: 文件系统类型错误、选项错误、/dev/rbd0 上有坏超级块、 缺少代码页或助手程序,或其他错误 有些情况下在 syslog 中可以找到一些有用信息- 请尝试 dmesg | tail 这样的命令看看。解决方法:mkfs.ext4 /dev/rbd0
zabbix持续频繁的发送历史的告警消息,一晚上告警内容高达1.7w条,严重影响查看真正出现问题的告警信息。产生此问题的原因:告警消息积压堆积,一直处于重试状态。触发器的确存在,但是目标监控主机的状态是正常的,只要触发器触发的问题存在,那么就会一直发生告警。解决方案:如果是触发器问题的确存在,但是目标主机状态是正常的,还在频繁发生告警,如果是这种情况,那么手动将问题点击关闭和确认,即可解决,如果触发器是在模板中配置的,那么直接修改模板,最后手动关闭问题。如果是消息积压,那么就去数据库中将异常状态的告警删除或者修改状态,即可解决问题。mysql> delete from zabbix.alerts where status=2; or mysql> update zabbix.alerts set status = 1 where status = 2;status=2:发送失败status=1:发送成功status=0:正在发送
1.Redis6.2.6简介以及环境规划在Redis6.x版本中主要增加了多线程的新特性,多线性对于高并发场景是非常有必要的。Redis6.x新特性如下:多线程IO重新设计了客户端缓存功能RESP3协议支持SSLACL权限控制提升了RDB日志加载速度发布官方的Redis集群代理模块 Redis Cluster proxyRedis Cluster集群原理可以查看之前发布的文章。环境规划:架构图:Reids集群采用三主三从交叉复制架构,由于服务器数量有限,在一台机器中模拟出集群的效果,在实际生产环境中,需要准备三台机器,每台机器中分别部署两台Redis节点,一主一从,交叉备份。2.二进制安装Redis程序2.1.二进制安装redis6.2.61.下载reids [root@redis-cluster /data/]# wget https://download.redis.io/releases/redis-6.2.6.tar.gz 2.解压并安装redis [root@redis-cluster /data/]# tar xf redis-6.2.6.tar.gz [root@redis-cluster /data/]# cd redis-6.2.6 [root@redis-cluster /data/redis-6.2.6]# make2.2.创建Reids Cluster集群目录1.创建Redis Cluster各集群节点的配置文件存放路径 [root@k8s-master ~]# mkdir /data/redis-6.2.6-cluster/{bin,conf,data,var,logs} -p [root@k8s-master ~]# ll /data/redis-6.2.6-cluster/ 总用量 0 drwxr-xr-x 2 root root 6 3月 31 15:36 bin #可执行文件 drwxr-xr-x 2 root root 6 3月 31 15:36 conf #配置文件 drwxr-xr-x 2 root root 6 3月 31 15:36 data #数据文件 drwxr-xr-x 2 root root 6 3月 31 15:36 log #日志文件 drwxr-xr-x 2 root root 6 3月 31 15:36 var #pid文件 2.准备redis可执行命令 [root@redis-cluster /data/redis-6.2.6]# cp src/redis-benchmark /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-check-aof /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-check-rdb /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-cli /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-sentinel /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-server /data/redis-6.2.6-cluster/bin [root@redis-cluster /data/redis-6.2.6]# cp src/redis-trib.rb /data/redis-6.2.6-cluster/bin3.配置Redis Cluster三主三从交叉复制集群3.1.准备六个节点的redis配置文件redis6.2.6版本配置文件所有内容如下,主要配置带注释的行。bind 0.0.0.0 protected-mode no #关闭保护模式 port 6701 #端口号 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6701.pid #pid存放 loglevel notice logfile /data/redis-6.2.6-cluster/logs/redis_6701.log #日志存放路径 databases 16 always-show-logo yes #是否显示总日志 set-proc-title yes proc-title-template "{title} {listen-addr} {server-mode}" stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename redis_6701.rdb #持久化数据文件名称 rdb-del-sync-files no dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 replica-serve-stale-data yes replica-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-diskless-load disabled repl-disable-tcp-nodelay no replica-priority 100 acllog-max-len 128 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no lazyfree-lazy-user-del no lazyfree-lazy-user-flush no oom-score-adj no oom-score-adj-values 0 200 800 disable-thp yes appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes lua-time-limit 5000 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6701.conf #集群模式配置文件名称 cluster-node-timeout 15000 #集群超时时间 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes jemalloc-bg-thread yes1.复制二进制中的配置文件[root@k8s-master redis-6.2.6]# cp redis.conf /data/redis-6.2.6-cluster/conf/2.Reids 6701节点配置文件内容[root@k8s-master conf]# vim redis_6701.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6701 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6701.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6701.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6701.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6701.conf #集群模式配置文件名称 cluster-node-timeout 15000 #集群超时时间3.Reids 6702节点配置文件内容[root@k8s-master conf]# vim redis_6702.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6702 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6702.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6702.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6702.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6702.conf #集群模式配置文件名称 cluster-node-timeout 15000 #集群超时时间4.Reids 6703节点配置文件内容[root@k8s-master conf]# vim redis_6702.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6703 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6703.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6703.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6703.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6703.conf #集群模式配置文件名称 cluster-node-timeout 15000 5.Reids 6704节点配置文件内容[root@k8s-master conf]# vim redis_6702.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6704 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6704.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6704.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6704.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6704.conf #集群模式配置文件名称 cluster-node-timeout 15000 6.Reids 6705节点配置文件内容[root@k8s-master conf]# vim redis_6702.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6705 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6705.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6705.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6705.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6705.conf #集群模式配置文件名称 cluster-node-timeout 15000 7.Reids 6706节点配置文件内容[root@k8s-master conf]# vim redis_6702.conf bind 0.0.0.0 #监听地址 protected-mode no #关闭保护模式 port 6706 #端口号 daemonize yes #后台运行 pidfile /data/redis-6.2.6-cluster/var/redis_6706.pid #pid存放路径 logfile /data/redis-6.2.6-cluster/logs/redis_6706.log #日志存放路径 always-show-logo yes #是否显示总日志 dbfilename redis_6706.rdb #持久化数据文件名称 dir /data/redis-6.2.6-cluster/data #持久化数据文件存放路径 cluster-enabled yes #开启集群模式 cluster-config-file nodes_6706.conf #集群模式配置文件名称 cluster-node-timeout 15000 3.2.将六个节点全部启动1)启动redis各个节点[root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6701.conf [root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6702.conf [root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6703.conf [root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6704.conf [root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6705.conf [root@k8s-master ~]# /data/redis-6.2.6-cluster/bin/redis-server /data/redis-6.2.6-cluster/conf/redis_6706.conf2)查看启动的进程[root@k8s-master ~]# ps aux | grep redis root 22166 0.2 0.0 164964 3208 ? Ssl 16:17 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6701 [cluster] root 22179 0.2 0.0 164964 3212 ? Ssl 16:17 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6702 [cluster] root 22235 0.2 0.0 164964 3216 ? Ssl 16:17 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6703 [cluster] root 23748 0.1 0.0 164964 3220 ? Ssl 16:18 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6704 [cluster] root 24093 0.1 0.0 164964 3224 ? Ssl 16:19 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6705 [cluster] root 24513 0.0 0.0 164964 3212 ? Ssl 16:19 0:00 /data/redis-6.2.6-cluster/bin/redis-server 0.0.0.0:6706 [cluster]3)查看各个节点生成的文件3.3.配置集群节点之间相互发现在任意一个节点中操作即可。[root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6701 127.0.0.1:6701> CLUSTER MEET 192.168.20.10 6702 OK 127.0.0.1:6701> CLUSTER MEET 192.168.20.10 6703 OK 127.0.0.1:6701> CLUSTER MEET 192.168.20.10 6704 OK 127.0.0.1:6701> CLUSTER MEET 192.168.20.10 6705 OK 127.0.0.1:6701> CLUSTER MEET 192.168.20.10 6706 OK 127.0.0.1:6701> CLUSTER NODES 1de9d406a489e3aedc2f7743114f21700de5d151 192.168.20.10:6702@16702 master - 0 1648715495901 1 connected f1d6f55a4a66fb97b3be2dff70cf0b8984a9de42 192.168.20.10:6704@16704 master - 0 1648715494000 0 connected 14bd716bdc2726bfbf39eb14c88f072970059676 192.168.20.10:6706@16706 master - 0 1648715494894 5 connected 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc 192.168.20.10:6701@16701 myself,master - 0 1648715494000 2 connected b7e93e3f3925c6db664afc59cb08c2abced2933d 192.168.20.10:6703@16703 master - 0 1648715494000 3 connected c502c900224a0ae6173631746de92d012bd43da3 192.168.20.10:6705@16705 master - 0 1648715494000 4 connected操作完成后会同步各节点的集群配置文件中。3.4.为集群中的充当Master的节点分配槽位1)分配槽位[root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6701 cluster addslots {0..5461} OK [root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6703 cluster addslots {5462..10922} OK [root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6705 cluster addslots {10923..16383} OK2)查看集群状态分配完槽位之后集群的状态就会处于ok。[root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6701 127.0.0.1:6701> CLUSTER INFO cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:5 cluster_my_epoch:2 cluster_stats_messages_ping_sent:248 cluster_stats_messages_pong_sent:246 cluster_stats_messages_meet_sent:5 cluster_stats_messages_sent:499 cluster_stats_messages_ping_received:246 cluster_stats_messages_pong_received:253 cluster_stats_messages_received:4993)查看集群中的节点信息虽然现在槽位已经分配完毕,但是当下集群中所有的节点都处于Master角色,还是无法使用。127.0.0.1:6701> CLUSTER NODES 1de9d406a489e3aedc2f7743114f21700de5d151 192.168.20.10:6702@16702 master - 0 1648715802089 1 connected f1d6f55a4a66fb97b3be2dff70cf0b8984a9de42 192.168.20.10:6704@16704 master - 0 1648715802000 0 connected 14bd716bdc2726bfbf39eb14c88f072970059676 192.168.20.10:6706@16706 master - 0 1648715802000 5 connected 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc 192.168.20.10:6701@16701 myself,master - 0 1648715803000 2 connected 0-5461 b7e93e3f3925c6db664afc59cb08c2abced2933d 192.168.20.10:6703@16703 master - 0 1648715803095 3 connected 5462-10922 c502c900224a0ae6173631746de92d012bd43da3 192.168.20.10:6705@16705 master - 0 1648715804100 4 connected 10923-16383接下来去配置三主三从交叉复制模式,让没有槽位的节点复制有槽位的节点,也就是主从关系。3.5.配置三主三从交叉复制模式1)获取集群主节点的信息[root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6701 cluster nodes | egrep '6701|6703|6705' | awk '{print $1,$2}' 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc 192.168.20.10:6701@16701 b7e93e3f3925c6db664afc59cb08c2abced2933d 192.168.20.10:6703@16703 c502c900224a0ae6173631746de92d012bd43da3 192.168.20.10:6705@16705 2)配置交叉复制1.配置6702节点复制6705节点,充当6705 master节点的slave [root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6702 127.0.0.1:6702> CLUSTER REPLICATE c502c900224a0ae6173631746de92d012bd43da3 OK 2.配置6704节点复制6701节点,充当6701 master节点的slave [root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6704 127.0.0.1:6704> CLUSTER REPLICATE 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc OK 3.配置6706节点复制6703节点,充当6703 master节点的slave [root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6706 127.0.0.1:6706> CLUSTER REPLICATE b7e93e3f3925c6db664afc59cb08c2abced2933d OK3)查看集群节点信息已经是三主三从交叉复制集群模式了。[root@redis-cluster ~]# /data/redis-6.2.6-cluster/bin/redis-cli -p 6701 127.0.0.1:6701> CLUSTER NODES 1de9d406a489e3aedc2f7743114f21700de5d151 192.168.20.10:6702@16702 slave c502c900224a0ae6173631746de92d012bd43da3 0 1648716239215 4 connected f1d6f55a4a66fb97b3be2dff70cf0b8984a9de42 192.168.20.10:6704@16704 slave 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc 0 1648716236175 2 connected 14bd716bdc2726bfbf39eb14c88f072970059676 192.168.20.10:6706@16706 slave b7e93e3f3925c6db664afc59cb08c2abced2933d 0 1648716238000 3 connected 7eb4466a8558ab389a9d92d115d5b420fa2a8ffc 192.168.20.10:6701@16701 myself,master - 0 1648716237000 2 connected 0-5461 b7e93e3f3925c6db664afc59cb08c2abced2933d 192.168.20.10:6703@16703 master - 0 1648716238192 3 connected 5462-10922 c502c900224a0ae6173631746de92d012bd43da3 192.168.20.10:6705@16705 master - 0 1648716237184 4 connected 10923-163834.快速搭建Redis Cluster集群前提条件需要先将6个节点搭建起来,再使用下面的命令快速将三主三从集群部署起来。[root@redis-cluster redis-6.2.6-cluster]# /data/redis-6.2.6-cluster/bin/redis-cli --cluster create 192.168.20.10:6701 192.168.20.10:6702 192.168.20.10:6703 192.168.20.10:6704 192.168.20.10:6705 192.168.20.10:6706 --cluster-replicas 1 Can I set the above configuration? (type 'yes' to accept): yes #--cluster起到的作用就是省掉了节点发现、分配槽位、交叉复制的过程,自动替我们分配。从输出信息中我们清晰的看到主从的复制关系以及分配的槽位。>>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.20.10:6705 to 192.168.20.10:6701 Adding replica 192.168.20.10:6706 to 192.168.20.10:6702 Adding replica 192.168.20.10:6704 to 192.168.20.10:67036701、6702、6703节点为主节点,6704、6705、6706节点为从节点。6704复制6703的主节点、6705复制6701的主节点、6706复制6702的主节点。架构图如下:
1.Windows11操作系统简介Windows 11是由微软公司(Microsoft)开发的操作系统,应用于计算机和平板电脑等设备 [1] 。于2021年6月24日发布 [3] ,2021年10月5日发行 [29] 。2.在VMware中创建一个新的虚拟机2.1.下载Windows 11系统镜像网址:https://next.itellyou.cn/Identity/Account/Login?ReturnUrl=%2FOriginal%2F#cbp=Product?ID=42e87ac8-9cd6-eb11-bdf8-e0d4e850c9c6登陆后点击windows11,然后复制ED2K名称,打开迅雷即可下载。2.2.新建一个windows虚拟机1)点击创建虚拟机。2)类型选择典型。3)稍后选择操作系统镜像。4)选择windows 10 x64就可以满足windows 11的安装。5)设置虚拟机的名称并选择虚拟机的安装位置。6)选择虚拟机的磁盘容量,一定要大于64GB。2.3.配置虚拟机资源设置1)首先将虚拟机的内存和CPU都选成4G4核,否则是会安装失败的。2)设置虚拟机加密。3)点击高级设置uefi启动。4)添加一个可信模块。2.4.将虚拟机开机选择blos启动1)开机启动后显示如下,手动摁一下ESC键。3)选择EFI第二项。4)弹出以下按钮后迅速敲回车键进入系统安装页面。5)如下所示。3.安装Windows11操作系统3.1.安装操作系统1)点击现在安装windows。2)选择windows11专业版。3)同意许可。4)选择自定义安装。5)选择系统安装的位置。6)等待windows安装即可。3.2.设置系统1)选择国家和地区。2)选择输入法,然后等待更新即可。3)设置系统名称。4)以下保持默认即可。5)登陆系统账号,点击其他登陆方式,选择脱机登陆。6)输入姓名。7)输入密码并配置密保。8)等待系统调配即可。4.Windows11安装完成administrator
报错内容如下/usr/bin/ld: cannot find -latomic collect2: error: ld returned 1 exit status make: *** [Makefile:228: redis-server] Error 1排查过程/usr/bin/ld: cannot find -latomic主要观察这句报错内容,一般出现这种报错,都是缺少了一些函式库文件导致,编译不同的软件,报错错也是都不一样的,相同的一定就是有这句话:/usr/bin/ld: cannot find。常见的报错有一下几种:/usr/bin/ld: cannot find -lc/usr/bin/ld: cannot find -lltdl/usr/bin/ld: cannot find –lXtst/usr/bin/ld: cannot find -latomic其中-l后面的字符表示的是函式库文件名称,如上例的:libc.so、libltdl.so、libXtst.so、libatomic.so。其命名规则是:lib+库名(即xxx)+.so。解决方法如下:使用yum安装缺少的函式库即可。yum -y install libatomic-dev
shell脚本配合zabbix实现tomcat的故障自愈1.背景及实现方式方法Tomcat运行JAVA类的程序代码经常会导致内存溢出,往往都是收到告警后再去处理,收到报警再处理就会拖延故障解决的时间,因此就需要靠故障自愈的机制来解决人为干预的成本。服务实现自愈的方式有很多种:通过shell脚本+定时任务的方式通过shell脚本检测应用程序的状态,状态为1表示异常为0表示正常,当检测到状态为1时就触发自愈脚本,完成程序的故障自愈。通过脚本来检测需要配合定时任务来实现,存在一定的弊端,可能需要每隔5分钟就要检测一次,多多少少会影响服务器性能。蓝鲸Pass故障自愈平台蓝鲸自动化运维平台有故障自愈模块,可以轻松获取zabbix告警信息然后实现故障自愈。如果只是为了实现自愈而使用蓝鲸平台,就有点小材大用了,蓝鲸平台搭建非常复杂,并且需要的服务器数量也居多,不建议使用此种方式。蓝鲸实现JAVA程序故障自愈的文章:https://jiangxl.blog.csdn.net/article/details/118731222shell脚本+zabbix触发器动作最为推荐的一种故障自愈方式。在zabbix中添加服务状态的监控项,并配置触发器,然后通过配置zabbix的动作功能,当收到服务状态异常的触发器告警时,再远程服务器中执行自愈脚本,实现程序的故障自愈。此方式也并不是十全十美,例如一个服务器上有10个tomcat,端口都不相同,无法通过zabbix触发器告警获取故障服务的端口号,因此一个tomcat就需要配置一个zabbix动作。shell+zabbix实现故障自愈大致实现步骤:1、在zabbix中添加服务的状态监控以及触发器。2、编写故障自愈恢复脚本,不同端口的服务都需要编写单独的脚本。3、配置zabbix动作功能,为每一个需要故障自愈的tomcat镜像配置。2.编写故障自愈脚本#!/bin/bash java_node=java-7180 java_dir=/data/tomcat/${java_node} java_port=`grep 'protocol="HTTP/1.1"' ${java_dir}/conf/server.xml |awk -F'"' '{if(NR==1){print $2}}'` host_ip=192.168.10.100 dtime=`date +%F" "%H:%M:%S` day=`date +%F` selflheal_logdir=/var/log/java_selflheal echo "${dtime} ${java_node} 开始自愈..." >>${selflheal_logdir}/selflheal-${day}.log #关闭tomcat ps aux | grep $java_dir | grep -v grep | awk '{print $2}' |xargs kill -9 #启动服务 su - www -c "${java_dir}/bin/startup.sh" if [ $? -eq 0 ];then sleep 10s for i in {1..20} do sleep 3s echo "第$i次尝试" ava=`curl -s http://${host_ip}:${java_port}/check` if [[ "$ava" = "true" ]];then echo "${dtime} ${java_node} 自愈成功!!!" >>${selflheal_logdir}/selflheal-${day}.log echo "=====================================================" >>${selflheal_logdir}/selflheal-${day}.log break fi if [ $i -ge 20 ];then echo "${dtime} ${java_node} 自愈不成功!!!" >>${selflheal_logdir}/selflheal-${day}.log echo "=====================================================" >>${selflheal_logdir}/selflheal-${day}.log exit 1 fi done fi3.配置zabbix动作机制实现Tomcat故障自愈实现目标:实现故障自愈的同时还要发送消息提醒。3.1.创建动作填写动作的名称,并关联服务状态异常的触发器。3.2.配置故障自愈消息内容以及执行自愈脚本1)故障自愈告警信息如下-----------故障自愈事件触发------- 故障:{TRIGGER.STATUS},服务器:{HOSTNAME1} 故障_触发器名称: {EVENT.NAME} IP地址:{HOST.CONN} 故障 时间: {EVENT.DATE} {EVENT.TIME} 故障 事件: {ITEM.NAME}:{ITEM.VALUE}2)添加执行远程命令的动作zabbix实现自愈就是通过在远程主机上执行命令进行自愈的。操作类型选择远程命令—>在目标列表中填写tomcat所在的服务器—填写执行故障自愈脚本的命令。3.3.动作创建完成4.观察故障自愈
1.在Docker Hub上创建镜像库首先到到官网注册账号:https://hub.docker.com/点击Repositories---->Create填写镜像的名字即可,在右边可以看到推送镜像的命令2.将本地镜像推送到Docker Hub2.1.登陆Docker Hubdocker login -ujiangxlrepo Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded2.2.将本地镜像打标签成Docker Hub的仓库路径docker tag kube-state-metrics:v1.8.0 jiangxlrepo/kube-state-metrics:v1.8.02.3.推送镜像# docker push jiangxlrepo/kube-state-metrics:v1.8.0 The push refers to repository [docker.io/jiangxlrepo/kube-state-metrics] a76865c920eb: Mounted from lizhenliang/kube-state-metrics 932da5156413: Mounted from lizhenliang/addon-resizer v1.8.0: digest: sha256:0581aa6fd5945aa0b1786ec81d0584a80873bade7375ce4d224dbb7b712bf3f6 size: 738
1、MongoDB数据库学习大纲2、MongoDB数据格式3、MongoDB数据库特点4、MongoDB数据库应用场景5、MongoDB数据库单节点部署5、MongoDB数据库常用操作指令6、MongoDB数据库增删改查数据查询7、MongoDB数据库运维工具8、MongoDB授权登陆安全模式9、MongoDB副本集集群10、MongoDB数据备份恢复机制11.MongoDB数据误删除恢复流程
elasticsearch分片lock锁无法分配报错内容如下所示出现这个问题的原因是原有分片未正常关闭或者清理,所以当分片要重新分配回出问题节点时就会没办法获取分片锁,这不会导致数据丢失,只需要重新出发一下分配分片的操作即可failed to obtain in-memory shard lockcurl -XPOST "http://192.168.10.10:9200/_cluster/reroute?retry_failed" 或者 curl -XPOST "http://192.168.10.10:9200/_cluster/reroute?retry_failed=true"
MongoDB数据库核心概念1.NoSQL数据库介绍NoSQL意思是不仅仅是sql。NoSQL指的是菲关系型数据库,NoSQL有时称作Not Only SQL的缩写,是对不同于传统的关系型数据的统称。NoSQL就是非关联形式的数据库,数据存储是key value形式。NoSQL类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。2.MongoDB数据库介绍MongoDB由C++语言编写,是一个基于分布式文件存储的开源数据库系统,是专为可扩展性、高性能和高可用性设计的数据库,是非关系型数据库中功能最丰富,最像关系型数据库,MongoDB的数据结构是json和bjson格式。MongoDB是可以应用于各种规模的企业,各个行业以及各类应用程序的开源数据库,作为一个适用于敏捷开发的数据库,MongoDB的数据模式可以随着应用程序的发展灵活的更新。随着应用程序的更新,数据库某张表可能需要增加一个或多个字段,而mysql这种关系型数据库需要修改表结构,并且在更新成千上万条数据,这个过程可能会导致数据库死锁,这种更新字段放到了非关系型数据库mongodb中,就会变得非常简单,只需要添加新字段后,新数据进来时应用即可,旧数据不会有变动,大大减少了数据库的压力。MongoDB是一种叫做BSON(二进制JSON)的存储形式作为数据存储。3.MongoDB支持的数据格式3.1.JSON格式的数据类型JSON是一种轻量级的数据交换格式,json采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯,这些特性使json成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成。MongoDB使用json文档存储记录。json格式:{ "id": "f274ef35-05a2-40c6-9b84-ff1e97702300", "version": "7.6.2", "hostname": "nginx-6b949875bc-hrzrp", "ephemeral_id": "1025c85b-df07-4c4b-98d4-f5593293ef0e", "type": "filebeat" }json格式解析网站:https://www.bejson.com/3.2.BSON格式BSON是一种类JSON的二进制形式的存储格式,简称Binary JSON,它和json一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,比如Date和BinData类型。BSON的优点是灵活性高,但它的缺点就是空间利用率不是很理想。BSON的特点:轻量性、可遍历性、高效性。4.MongoDB数据库的特性高性能MongoDB提供高性能的数据持久化,尤其是支持嵌入式数据模型减少数据库系统上的I/O操作。MySQL需要查询10张表,MongoDB一张表就可以搞定。丰富的语言查询,MongoDB支持丰富的查询语言来进行读写操作以及数据汇总。高可用性MongoDB的复制工具是副本集,提供自动故障转移和数据冗余。MongoDB之前有主从复制,后来的主从复制集群称之为副本集。水平可扩展性MongoDB提供可扩展性,作为其核心功能的一部分,分片是将数据分散在一组机器上。MongoDB副本集扩容也无需像redis需要迁移槽位,MongoDB可以直接扩容支持多种存储引擎WiredTiger存储引擎、MMAPv1存储引擎和InMemory引擎。5.MongoDB程序MOngoDB Derives:客户端程序MongoDB Stitch:API服务MongoDB Atlas:云上部署MongoDBMongoDB Cloud Manager:管理MongoDB的软件包MongoDB Charts:可视化图表6.MongoDB应用场景游戏场景使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新。物流场景使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。社交场景使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。物联网场景使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。视频直播使用 MongoDB 存储用户信息、礼物信息等,用户评论。电商场景商城上衣和裤子两种商品,除了有共同属性,如产地、价格、材质、颜色等外,还有各自有不同的属性集,如上衣的独有属性是肩宽、胸围、袖长等,裤子的独有属性是臀围、脚口和裤长等。
1.Cluster集群收缩概念当项目压力承载力过高时,需要增加节点来提高负载,当项目压力不是很大时,也希望能够将集群收缩下来,给其他项目使用,这就要用到集群收缩了集群收缩操作和集群扩容是一样的,只需要把方向反过来即可。扩容的时候执行一次命令就可以实现槽位迁移成功,而收缩的时候有几个主节点就需要执行多少次,比如除去要下线的节点,还有3个主节点,那么就需要执行三次,填写迁移出槽位的数量也需要除以3,每个节点也需要平均分配。收缩的时候首先要填写分出多少个槽位,然后填写要分给谁,最后填写从哪分出槽位,一般分多少个槽位,就需要看要下线的主机上有多少个槽位,然后除以集群主节点数,使每一个主机点分到的槽位都是相同的,填写要分配给谁的时候,第一次填写第一个主节点的ID,第二次填写第二个主节点的ID,最后填写提供槽位的节点ID,就是下线节点的ID号。集群收缩扩容槽位的时候不会影响数据的使用。集群收缩的源端就是要下线的主节点,目标端就是在线的主节点(分配给谁的节点)。咱们要清楚一点,只有主节点是有槽位的,因此呢需要将主节点的槽位分配给其他主节点,当槽位清空后,这个主机节点就可以下线了收缩集群前后对比图集群收缩操作步骤: 1.执行reshard命令将需要下线的主节点进行槽位分散。 2.有几个主节点就需要执行几次reshard命令,首先填写要分出的槽位数,然后填写分给谁,最后填写从哪里分。 3.当槽位分散完成后,要下线的主节点没有任何数据时,将节点从集群中删除。集群信息目前集群时四主四从共8个节点,我们需要将集群改为三主三从,收缩出两个节点给其他程序使用。2.将6390主节点从集群中收缩2.1.计算需要分给每一个节点的槽位数可以看到6390节点上有4096个槽位,删除要下线的6390节点后,我们还有3个主节点,4096除3得到1365,分配槽位的时候给每个节点分配1365个槽位即可均匀。2.2.分配1365个槽位给192.168.81.210的6380节点我们需要将192.168.81.240的6390节点分出1365个槽位给192.168.81.210的6380节点。只需要把What is the receiving node ID填写成192.168.81.210的6380节点ID即可,指的是分配出来的槽位要给谁。然后source node填写192.168.81.240的6390节点的ID,这里指的是从哪个节点上分出1365个槽位,填写ID后,回车后会提示还要从哪个节点上分配槽位,因为只有6390需要分出槽位,所以在这里填写done,表示只有这个一个节点分出1365个槽位给其他节点。[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb reshard 192.168.81.210:6380 How many slots do you want to move (from 1 to 16384)? 1365 #分配出多少个槽位 What is the receiving node ID? 80e256579658eb256c5b710a3f82c439665794ba #将槽位分给那个节点 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:6bee155f136f40e28e1f60c8ddec3b158cd8f8e8 #从哪个节点分出槽位 Source node #2:done Do you want to proceed with the proposed reshard plan (yes/no)? yes #输入yes继续 下面是收缩节点的过程截图。数据迁移过程。槽位分出迁移成功。2.3.分配1365个槽位给192.168.81.220的6380节点[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb reshard 192.168.81.210:6380 How many slots do you want to move (from 1 to 16384)? 1365 #分配出多少个槽位 What is the receiving node ID? 10dc7f3f9a753140a8494adbbe5a13d0026451a1 #将槽位分给那个节点 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:6bee155f136f40e28e1f60c8ddec3b158cd8f8e8 #从哪个节点分出槽位 Source node #2:done Do you want to proceed with the proposed reshard plan (yes/no)? yes #输入yes继续收缩过程截图展示。2.4.分配1365个槽位给192.168.81.230的6380节点[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb reshard 192.168.81.210:6380 How many slots do you want to move (from 1 to 16384)? 1366 #分配出多少个槽位 What is the receiving node ID? a4381138fdc142f18881b7b6ca8ae5b0d02a3228 #将槽位分给那个节点 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:6bee155f136f40e28e1f60c8ddec3b158cd8f8e8 #从哪个节点分出槽位 Source node #2:done Do you want to proceed with the proposed reshard plan (yes/no)? yes #输入yes继续 收缩过程截图展示。当最后一个节点迁移完数据后,6390主节点槽位数变为0。2.5.查看当前集群槽位分配槽位及数据已经从6390即将下线的主机迁移完毕,可以看下当前集群三个主节点的槽位数。可以非常清楚的看到,现在每个主节点的槽位数为5461。如果觉得槽位重新分配后顺序不太满意,那么在执行一下reshard,把其它节点的槽位都分给192.168.81.210的6380上,这样一来,210的6380拥有的槽位就是0-16383,然后在将210的槽位一个节点分给5461个,分完之后,各节点的顺序就一致了。3.验证数据迁移过程是否导致数据异常多开几个窗口,一个执行数据槽位迁移,一个不断创建key,一个查看key的创建进度,一个查看key的数据。持续测试,发现没有任何数据异常,全部显示ok。4.将下线的主节点从集群中删除4.1.删除节点使用redis-trib删除一个节点,如果这个节点存在复制关系,有节点在复制当前节点或者当前节点复制别的节点的数据,redis-trib会自动处理复制关系,然后将节点删除,节点删除后会把对应的进程也停止运行。删除节点之前必须确保该节点没有任何槽位和数据,否则会删除失败。命令:./redis-trib.rb del-node 节点IP:端口 ID[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb del-node 192.168.81.240:6390 6bee155f136f40e28e1f60c8ddec3b158cd8f8e8 >>> Removing node 6bee155f136f40e28e1f60c8ddec3b158cd8f8e8 from cluster 192.168.81.240:6390 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb del-node 192.168.81.240:6391 f6b9320dfbc929ad5a31cdb149360b0fd8de2e60 >>> Removing node f6b9320dfbc929ad5a31cdb149360b0fd8de2e60 from cluster 192.168.81.240:6391 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. 4.2.调整主从交叉复制删掉192.168.81.240服务器上的两个redis节点后,192.168.81.210服务器上的6380就没有了复制关系,我们需要把192.168.81.230的6381节点复制192.168.81.210的6380节点。[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 192.168.81.230:6381> CLUSTER REPLICATE 80e256579658eb256c5b710a3f82c439665794ba OK4.3.当节点存在数据无法删除[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb del-node 192.168.81.220:6380 10dc7f3f9a753140a8494adbbe5a13d0026451a1 >>> Removing node 10dc7f3f9a753140a8494adbbe5a13d0026451a1 from cluster 192.168.81.220:6380 [ERR] Node 192.168.81.220:6380 is not empty! Reshard data away and try again. 5.将下线主机清空集群信息redis-trib虽然能够将节点在集群中删除,但是无法将其的集群信息清空,如果集群信息还有保留,那么该接地那就无法加入其它集群。在下线的redis节点上使用cluster reset删除集群信息即可。192.168.81.240:6390> CLUSTER reset OK
1.监控Tomcat的方式简单命令现成脚本通过zabbix自定义监控自定义监控 只要是用命令能得到的东西都能去监控通过jmx 对java进行监控其他监控通过ipmi 监控硬件的通过snmp 监控网络设备的,只要支持snmp都能监控2.Java自带的监控命令jps 导出java相关的进程格式:jps -lvm参数选项:-lvm最详细[root@localhost ~]# jps -lvm 7457 org.apache.catalina.startup.Bootstrap start start -Djava.util.logging.config.file=/application/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/application/tomcat -Dcatalina.home=/application/tomcat -Djava.io.tmpdir=/application/tomcat/temp 7525 org.apache.catalina.startup.Bootstrap start start -Djava.util.logging.config.file=/application/tomcat_8082/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/application/tomcat_8082 -Dcatalina.home=/application/tomcat_8082 -Djava.io.tmpdir=/application/tomcat_8082/temp 9144 sun.tools.jps.Jps -lvm -Denv.class.path=.:/application/jdk/lib:/application/jdk/jre/lib:/application/jdk/lib/tools.jar -Dapplication.home=/application/jdk1.8.0_60 -Xms8m 7482 org.apache.catalina.startup.Bootstrap start start -Djava.util.logging.config.file=/application/tomcat_8081/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/application/tomcat_8081 -Dcatalina.home=/application/tomcat_8081 -Djava.io.tmpdir=/application/tomcat_8081/temp jmap 导出jvm信息,常用于自定义监控格式:jmap pid参数:-heap[root@localhost ~]# jmap -heap 7457 Attaching to process ID 7457, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.60-b23 using thread-local object allocation. Mark Sweep Compact GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 255852544 (244.0MB) NewSize = 5570560 (5.3125MB) MaxNewSize = 85262336 (81.3125MB) OldSize = 11206656 (10.6875MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: #监控的话关注这一列 New Generation (Eden + 1 Survivor Space): capacity = 12779520 (12.1875MB) used = 11689352 (11.147834777832031MB) free = 1090168 (1.0396652221679688MB) 91.46941356169872% used Eden Space: #监控的话关注这一列 capacity = 11403264 (10.875MB) used = 11059616 (10.547271728515625MB) free = 343648 (0.327728271484375MB) 96.98640669899426% used From Space: #监控的话关注这一列 capacity = 1376256 (1.3125MB) used = 629736 (0.6005630493164062MB) free = 746520 (0.7119369506835938MB) 45.75718470982143% used To Space: #监控的话关注这一列 capacity = 1376256 (1.3125MB) used = 0 (0.0MB) free = 1376256 (1.3125MB) 0.0% used tenured generation: #监控的话关注这一列 capacity = 28164096 (26.859375MB) used = 18313224 (17.46485137939453MB) free = 9850872 (9.394523620605469MB) 65.02329774760035% used 21146 interned Strings occupying 1882520 bytes. jstatck 导出java的进程信息,常用于java程序故障,需要导出线程信息与开发一起研究格式:jstack -l pid[root@localhost ~]# jstack -l 74573.Tomcat故障案例系统负载高,tomcat占用CPU较高1.jps/top/htop精确确定哪个java进程导致2.jstack导出java线程3.catalina.out日志分析4.jmap导出jvm信息,可以通过mat工具进行分析10.4.配置Tomcat JMX监控自定义监控:直接在tomcat服务器上写好脚本,在zabbix配置文件写好就行首先需要在zabiix服务端安装zabbix-java-gateway然后在tomcat服务器开启监控功能tomcat开启jmx监控功能#修改bin/catalina.sh [root@localhost tomcat]# vim bin/catalina.sh #注意不能分行写会报错找不到命令,要写在一行上 CATALINA_OPTS="$CATALINA_OPTS" -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jxmremote.ssl=false -Djava.rmi.server.hostname="192.168.81.210" #正确写法 CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jxmremote.ssl=false -Djava.rmi.server.hostname=192.168.81.210" #说明 CATALINA_OPTS="$CATALINA_OPTS" #修改tomcat启动参数 -Dcom.sun.management.jmxremote #开启tomcat远程管理功能 -Dcom.sun.management.jmxremote.port=12345 #远程管理功能,除了12345端口,还会生成2个随机端口,我们可以开放所有端口 Dcom.sun.management.jmxremote.authenticat=false #是否在监控时需要认证 -Dcom.sun.management.jmxremote.ssl=false #是否开启ssl连接 -Djava.rmi.server.hostname="192.168.81.210" #设置tomcat所在服务器的ip 配置完成后重启tomcat即可 使用ps命令可以看到输出的信息多了我们写入的几行 [root@localhost tomcat]# ps aux | grep java root 17786 5.7 10.6 2306592 105860 pts/1 Sl 15:52 0:08 /application/jdk/bin/java -Djava.util.logging.config.file=/application/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jxmremote.ssl=false -Djava.rmi.server.hostname=192.168.81.210 -Dignore.endorsed.dirs= -classpath /application/tomcat/bin/bootstrap.jar:/application/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/application/tomcat -Dcatalina.home=/application/tomcat -Djava.io.tmpdir=/application/tomcat/temp org.apache.catalina.startup.Bootstrap start 使用ss/netstat 命令可以看到多出啦的三个端口 [root@localhost tomcat]# ss -lnptu | grep java tcp LISTEN 0 100 :::8080 :::* users:(("java",pid=17786,fd=56)) #我们制定的 tcp LISTEN 0 50 :::12345 :::* users:(("java",pid=17786,fd=22)) #随机的1 tcp LISTEN 0 50 :::46272 :::* users:(("java",pid=17786,fd=21)) #随机的2 tcp LISTEN 0 50 :::46081 :::* users:(("java",pid=17786,fd=24)) tcp LISTEN 0 1 ::ffff:127.0.0.1:8005 :::* users:(("java",pid=17786,fd=65)) 5.使用Jsconsole连接JMX查看监控数据
Tomcat安全优化1.Tomcat启动端口优化1)8005端口优化8005端口是tcp的管理端口,修改默认的8005端口为不易猜测的端口,可以是大于1024的任意端口。<Server port="8527" shutdown="SHUTDOWN">2)8009端口优化8009端口为Ajp协议连接保护端口,针对8009端口的优化可以分为两部分。1.修改默认8009端口为不易猜测的大于1024的端口。2.通过iptables规则限制ajp端口访问的权限。<Connector port="8528" protocol="AJP/1.3" redirectPort="8443" secretRequired=""/>2.Tomcat管理端优化关于管理端的优化主要在3个点1.删除默认的{tocmat安装目录}/conf/tomcat-users.xml文件,重启tomcat会自动生成新的文件。2.删除{tocmat安装目录}/webapps/下所有目录和文件3.将tomcat的启动用户设置成普通用户<Context path="" docBase="/usr/local/tomcat_webvapps" debug="0" reloadable="false" crossContext="true"/>3.Tomcat降权启动Tomcat启动用户权限必须为非root权限,尽量降低tomcat启动用户对目录的访问权限,避免一旦tomcat服务器被入侵,黑客直接获取高级用户权限危害整个服务器4.关闭文件列表功能conf/web.xml文件中default部分的listings必须配置为false <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param>5.隐藏Tomcat版本信息tomcat报错后会有版本提示,定义一个error-code1.修改conf/web.xml,重定向403/404以及500等错误页面的url2.修改程序目录下的WEB-INF/web.xml配置页面重定向 <error-page> <error-code>404</error-code> <location>/WEB-INF/jsp/errors/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/jsp/errors/error.jsp</location> </error-page> 6.Tomcat响应头重写修改http响应头中的服务端名称server="webserver"7.Tomcat设置访问限制通过配置限定访问的IP来源<context path=”/myapp” reloadable=”true” docBase=”/var/www/myapp”> <value className=”org.apache.catalina.values.RemoteAddrValue” allow=”192.168.[1-5].*,192.168.[10-15].*” deny=”″ /> </context >8Tomcat日志设置开启tomcat默认访问日志中的referer和user-agent记录<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
1.Cluster集群扩容概念当redis数据量日渐增长,当内存不够用的时候,这时候就需要集群扩容了,cluster集群扩容可以增加内存也可以增加节点,因为redis数据都是存在内存中redis cluster增加节点进行扩容步骤: 1.在新的服务器上部署redis cluster 2.使用工具将新部署的节点加到集群中 3.使用工具将集群槽位重新分配 4.将主从复制关系调整成交叉模式扩容原理: 原来的节点算好要拿出多少的槽位给新加的节点,新加的节点准备导入的槽位,准备的前提条件就是加入集群,一切准备就绪后,主节点将划分出来的槽位分配给新节点,然后将相关槽位的数据迁移到新的节点4个节点的redis cluster,每个节点的槽位时16384/4,一个节点4096个槽位扩容前后的架构图对比图新增节点后,主从复制就变成了四主四从,只需要变动192.168.81.230的从库关系即可,192.168.81.230节点从库复制192.168.81.240节点的主库,192.168.81.240从库复制192.168.81.210的主库环境准备2.在新节点部署redis cluster1.将redis管理工具从redis-1拷贝到redis-4并安装 [root@redis-1 ~]# scp -rp /data/redis_cluster root@192.168.81.240:/data [root@redis-4 ~]# cd /data/redis_cluster/redis-3.2.9 [root@redis-4 /data/redis_cluster/redis-3.2.9]# make install 2.创建部署路径 [root@redis-4 ~]# mkdir -p /data/redis_cluster/redis_{6390,6391}/{conf,data,logs,pid} 2.准备配置文件 [root@redis-4 ~]# cat > /data/redis_cluster/redis_6390/conf/redis_6390.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6390 daemonize yes logfile /data/redis_cluster/redis_6390/logs/redis_6390.log pidfile /data/redis_cluster/redis_6390/pid/redis_6390.log dbfilename "redis_6390.rdb" dir /data/redis_cluster/redis_6390/data cluster-enabled yes cluster-config-file node_6390.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF [root@redis-4 ~]# cat > /data/redis_cluster/redis_6391/conf/redis_6391.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6391 daemonize yes logfile /data/redis_cluster/redis_6391/logs/redis_6391.log pidfile /data/redis_cluster/redis_6391/pid/redis_6391.log dbfilename "redis_6391.rdb" dir /data/redis_cluster/redis_6391/data cluster-enabled yes cluster-config-file node_6391.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF 3.启动redis [root@redis-4 ~]# ./redis_shell.sh start 6390 [root@redis-4 ~]# ./redis_shell.sh start 6391 3.使用工具将redis-4加入集群在原来集群的任意一台机器安装了ruby环境即可操作3.1.安装ruby环境//安装ruby管理工具 [root@redis-1 ~]# yum -y install rubygems //移除官网源 [root@redis-1 ~]# gem sources --remove https://rubygems.org/ https://rubygems.org/ removed from sources //增加阿里云源 [root@redis-1 ~]# gem sources -a http://mirrors.aliyun.com/rubygems/ http://mirrors.aliyun.com/rubygems/ added to sources //更新缓存 [root@redis-1 ~]# gem update --system ruby2.3.0以下版本执行会报错 //安装ruby支持redis的插件 [root@redis-1 ~]# gem install redis -v 3.3.5 Fetching: redis-3.3.5.gem (100%) Successfully installed redis-3.3.5 Parsing documentation for redis-3.3.5 Installing ri documentation for redis-3.3.5 1 gem installed3.2.将redis-4加入集群需要将redis-4的6390和6391端口都加入到集群,可以使用工具进行添加命令:./redis-trib.rb add-node 新节点:端口 现有集群:端口[root@redis-1 ~]# cd /data/redis_cluster/redis-3.2.9/src/ [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb add-node 192.168.81.240:6390 192.168.81.210:6380 [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb add-node 192.168.81.240:6391 192.168.81.210:6380 查看集群信息,已经有8个节点[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd 192.168.81.220:6380 master - 0 1612424799243 2 connected 5461-10922 9b7641253ea66073d865accdd4460d2877f9ff5d 192.168.81.220:6381 master - 0 1612424801262 8 connected 10923-16383 b19722a1d3d482a2c6eaaec15e5e72018600389f 192.168.81.240:6391 master - 0 1612424797227 0 connected 6b6ca5d58187ecbf0bff15d71a5789f4aa78cfa2 192.168.81.240:6390 master - 0 1612424796216 9 connected bdd20b03b573b2def6a9ee5053a75867709fc908 192.168.81.210:6381 slave ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd 0 1612424796721 4 connected 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a 192.168.81.230:6380 slave 9b7641253ea66073d865accdd4460d2877f9ff5d 0 1612424800253 8 connected 904a0109976cae38e5a3059fd70ce2727a0ed8fb 192.168.81.230:6381 slave b61b8d0421b94b9de7267dda6c6f401a42622047 0 1612424798232 6 connected b61b8d0421b94b9de7267dda6c6f401a42622047 192.168.81.210:6380 myself,master - 0 0 1 connected 0-5460 4.将槽位重新分配当新节点加入集群后,需要重新分配槽位,否则整个集群是无法使用的命令格式./redis-trib.rb reshard 集群任意一个主库的ip:端口分配的时候可以选择all,直接将所有节点分出一部分槽位迁移给新节点也可以指定某个节点迁移出一部分槽位给新节点4.1.所有节点分出槽位给新节点[root@redis-1 ~]# cd /data/redis_cluster/redis-3.2.9/src [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb reshard 192.168.81.210:6380 How many slots do you want to move (from 1 to 16384)? 4096 //需要迁移的槽位数量,也就是要拿出多少个槽位给新节点,我们输入4096,因为16384除4刚好是4096 What is the receiving node ID? 6b6ca5d58187ecbf0bff15d71a5789f4aa78cfa2 //迁移给目标节点的ID号,也就是新节点的6390ID号,6390作为新节点的主库 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:all //迁移方式:all将所有主节点分出一部分槽位给新节点 Do you want to proceed with the proposed reshard plan (yes/no)? yes //是否继续分配 设置要迁移的槽位数量,填写4096填写要迁移到目标节点的ID号,也就是要迁移给谁,这里我们要迁移给新加的节点,我们要让新机器的6390节点成为主库,因此就填写6390节点的ID号设置要从哪个节点上迁移槽位,可以一台一台的迁移,也可以填写all,all的意思是从所有节点上一共取出4096个槽位分给新机器,如果使用all迁移,会把所有主节点迁移出一部分槽位给新节点,执行完all直接就退出工具我们使用all自动将所有主节点进行迁移,直接输入all即可自动迁移,一般都使用all提示我们是否继续分配,我们选择yes迁移完成自动退出程序4.2.迁移指定节点的槽位给新节点前面步骤一致,只需要在source node选择指定节点即可填写要迁移的主节点ID,填写完主机节点ID后,输入done,回车之后开始迁移数据提示我们是否继续,我们输入yes开始数据迁移4.3.查看集群信息及状态当6390分配完槽位后,可以看下集群信息是否分配成功[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes可以看到6390上有3段槽位号,说明是从三个节点上分出来的,正好也验证了之前说的一句话,槽位顺序不一定要存在,只要槽位数量够就可以再次使用reshard命令即可看到都是4096个槽位查看集群状态[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:8 #节点数已经是8个了 cluster_size:4 cluster_current_epoch:11 cluster_my_epoch:1 cluster_stats_messages_sent:67364 cluster_stats_messages_received:67293 5.配置四主四从交叉复制目前是5个主节点3个从节点,显然是不合理的,我们要手动配置一些交叉复制实现四主四从只需要操作192.168.81.230的6381端口和192.168.81.240的6391端口即可192.168.81.230的6381端口作为192.168.81.240的6390端口的从库192.168.81.240的6391作为192.168.81.210的6380端口的从库再配置与新节点交叉复制的时候,建议先操作192.168.81.230,这样192.168.81.210的主库就没有需要传输rdb文件到从库了,也可以减轻主库的压力,如果先让192.168.81.240配置交叉,这样一来192.168.81.210的主库就有2份复制了,主库就需要一次传输2份rdb文件,压力也就大了注意:先做192.168.81.230的交叉在做192.168.81.240的交叉5.1.配置四主四从交叉复制1.将master主库的所有ID获取下来 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes | grep 'master' | awk '{print $1,$2}' ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd 192.168.81.220:6380 6b6ca5d58187ecbf0bff15d71a5789f4aa78cfa2 192.168.81.240:6390 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a 192.168.81.230:6380 b61b8d0421b94b9de7267dda6c6f401a42622047 192.168.81.210:6380 2.建议在记事本里准备好命令 redis-3同步redis-4 192.168.81.230:6381> CLUSTER REPLICATE 6b6ca5d58187ecbf0bff15d71a5789f4aa78cfa2 redis-4同步redis-3 192.168.81.240:6391> CLUSTER REPLICATE b61b8d0421b94b9de7267dda6c6f401a42622047 5.2.查看集群信息及状态[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:8 cluster_size:4 cluster_current_epoch:11 cluster_my_epoch:1 cluster_stats_messages_sent:69698 cluster_stats_messages_received:69627 [root@redis-1 ~]# 已经是三主三从了,并且集群状态也是ok
手动搭建集群便于理解集群创建的流程和细节,不过手动搭建集群需要很多步骤,当集群节点众多时,必然会加大搭建集群的复杂度和运维成本,因此官方提供了 redis-trib.rb的工具方便我们快速搭建集群。redis-trib.rb是采用 Ruby 实现的 redis 集群管理工具,内部通过 Cluster相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用前要安装 ruby 依赖环境redis-trib.rb无法实现所有节点都交叉复制,总会有一个节点不交叉,因此在安装完cluster以后,需要手动调整交叉环境准备1.安装ruby环境只在使用redis-trib的机器上安装即可//安装ruby管理工具 [root@redis-1 ~]# yum -y install rubygems //移除官网源 [root@redis-1 ~]# gem sources --remove https://rubygems.org/ https://rubygems.org/ removed from sources //增加阿里云源 [root@redis-1 ~]# gem sources -a http://mirrors.aliyun.com/rubygems/ http://mirrors.aliyun.com/rubygems/ added to sources //更新缓存 [root@redis-1 ~]# gem update --system ruby2.3.0以下版本执行会报错 //安装ruby支持redis的插件 [root@redis-1 ~]# gem install redis -v 3.3.5 Fetching: redis-3.3.5.gem (100%) Successfully installed redis-3.3.5 Parsing documentation for redis-3.3.5 Installing ri documentation for redis-3.3.5 1 gem installed 2.使用redis-trib自动部署cluster集群2.1.所有节点安装redis1.创建部署路径 mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid} 2.准备配置文件 cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6381 daemonize yes logfile /data/redis_cluster/redis_6381/logs/redis_6381.log pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log dbfilename "redis_6381.rdb" dir /data/redis_cluster/redis_6381/data cluster-enabled yes cluster-config-file node_6381.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF 3.启动redis ./redis_shell.sh start 6380 ./redis_shell.sh start 63812.2.使用redis-trib部署cluster集群语法格式:./redis-trib.rb create --replicas 每个主节点的副本数量(从库数量) cluster节点地址create //创建–replicas //指定主库的副本数量,也就是从库数量使用redis-trib安装的cluster集群,总会有一个节点不是交叉复制的,需要手动调整,因为trib也是根据节点地址交叉对应,到了最后一个机器已经没有第二个可以与它交叉的机器,它只能和自己去复制[root@redis-1 ~]# cd /data/redis_cluster/redis-3.2.9/src [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb create --replicas 1 192.168.81.210:6380 192.168.81.220:6380 192.168.81.230:6380 192.168.81.210:6381 192.168.81.220:6381 192.168.81.230:6381 安装完查看集群准备已经是可用的 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> CLUSTER info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_sent:1618 cluster_stats_messages_received:16182.3.手动调整三主三从交叉复制由于只有redis-3的复制不是交叉的,如果直接让redis-3去交叉复制某一个节点,那么就没有节点去复制redis-3的6380了,因此我们要手动调整所有节点之间的交叉入职举个例子:redis-3的6381要成为redis-1的6380的主库,需要去redis-3的6381redis交互式操作1.获取主节点的信息 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes | grep 6380 | awk '{print $1.$2}' 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a192.168.81.230:6380 ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd192.168.81.220:6380 b61b8d0421b94b9de7267dda6c6f401a42622047192.168.81.210:6380 2.配置三主三从交叉复制 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 192.168.81.210:6381> CLUSTER REPLICATE ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd OK [root@redis-2 ~]# redis-cli -h 192.168.81.220 -p 6381 192.168.81.220:6381> CLUSTER REPLICATE 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a OK [root@redis-3 ~]# redis-cli -h 192.168.81.230 -p 6381 192.168.81.230:6381> CLUSTER REPLICATE b61b8d0421b94b9de7267dda6c6f401a42622047 OK 3.查看集群信息已经交叉复制 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a 192.168.81.230:6380 master - 0 1612342768677 3 connected 10923-16383 bdd20b03b573b2def6a9ee5053a75867709fc908 192.168.81.210:6381 myself,slave ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd 0 0 4 connected 9b7641253ea66073d865accdd4460d2877f9ff5d 192.168.81.220:6381 slave 812ae8ccf55d8994f1f9d30a20f6cff42fb24b4a 0 1612342767669 5 connected ce75dacf45d3ad4f852b7fb4d359a295b8a2bcdd 192.168.81.220:6380 master - 0 1612342766658 2 connected 5461-10922 904a0109976cae38e5a3059fd70ce2727a0ed8fb 192.168.81.230:6381 slave b61b8d0421b94b9de7267dda6c6f401a42622047 0 1612342769686 3 connected b61b8d0421b94b9de7267dda6c6f401a42622047 192.168.81.210:6380 master - 0 1612342770189 1 connected 0-5460 2.4.查看集群完整性如果集群没问题会输出ok[root@redis-1 ~]# cd /data/redis_cluster/redis-3.2.9/src [root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb check 192.168.81.210:63802.5.验证hash分配是否均匀1.首先插入1000条数据 [root@redis-1 ~]# for i in {1..1000} do redis-cli -c -h 192.168.81.210 -p 6380 set key_${i} value_${i} done 2.查看每个节点的数据量 [root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6380 dbsize (integer) 334 [root@redis-1 ~]# redis-cli -c -h 192.168.81.220 -p 6380 dbsize (integer) 336 [root@redis-1 ~]# redis-cli -c -h 192.168.81.230 -p 6380 dbsize (integer) 330 2.6.查看集群分配的误差值[root@redis-1 /data/redis_cluster/redis-3.2.9/src]# ./redis-trib.rb rebalance 192.168.81.210:6380 >>> Performing Cluster Check (using node 192.168.81.210:6380) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. *** No rebalancing needed! All nodes are within the 2.0% threshold.
redis运维脚本1.设计思路redis经常需要去管理,而编译安装的redis没有启动脚本以及运维相关的脚本,我们可以自己设计一个脚本需求: 1.可以启动、关闭、重启redis 启动:当redis没有运行的时候直接启动并输出启动成功,运行了就输出已经启动,避免重复进程 关闭:如果进程存在就关闭并输出已经关闭,没有进程则直接输出redis没有启动 重启:当进程存在就先执行关闭再启动,并输出重启成功,如果进程不存在直接执行启动 2.可以查看redis进程 3.可以登录redis 4.可以查看redis日志 5.由于redis是多端口实例,因此需要能够实现指定一个端口就能够启动这个端口的进程实现思路: 1.将所有的功能都做成函数 2.通过判断$1输入的是什么指令,并执行对应的脚本2.编写脚本2.1.定义各种变量将redis部署路径、端口号、配置文件、主机IP都定义成变量redis_port=$2 #redis端口 redis_name="redis_${redis_port}" #redis节点所在目录名称,即redis_6379 redis_home=/data/redis_cluster/${redis_name} #redis节点所在万年竹路径 redis_conf=${redis_home}/conf/${redis_name}.conf #redis配置文件路径 redis_host=`ifconfig ens33 | awk 'NR==2{print $2}'` #主机ip redis_pass=$3 #redis密码,用到了在登陆那边加个-a参数 red="\e[031m" green="\e[032m" yellow="\e[033m" black="\e[0m" 2.2.编写使用模块主要实现如何使用这个脚本Usage(){ echo "usage: sh $0 {start|stop|restart|login|ps|logs|-h} PORT" }2.3.编写启动模块思路:首先判断指定端口的redis是否存在,如果不存在就执行启动命令,启动后输出启动成功,然后将开启的端口列出来这里还需要判断一下state的值是不是空的,因为到重启模块需要判断,在重启模块会定义一个state值,这里检测到state的值为空就输出echo的内容,到了restart的时候如果进程一开始是没有的无需输出echo内容,主要是为了重启的时候不输出这些echo启动后echo的时候,也会判断state的值,如果不为空就表示是重启了,就提示重启成功Start(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -eq 0 ];then redis-server ${redis_conf} if [ -z $state ];then echo -e "${green}redis ${redis_port}实例启动成功!${black}" else echo -e "${green}redis ${redis_port}实例重启成功!${black}" fi netstat -lnpt | grep ${redis_port} else if [ -z $state ];then echo -e "${yellow}redis "${redis_port}"实例已经是启动状态!${black}" netstat -lnpt | grep ${redis_port} fi fi }2.4.编写关闭模块思路:首先判断进程是否存在,如果存在就执行关闭命令,不存在就直接输出没有启动这里还需要判断一下state的值是不是空的,因为到重启模块需要判断,在重启模块会定义一个state值,这里检测到state的值为空就输出echo的内容,到了restart的时候如果进程一开始是没有的无需输出echo内容,主要是为了重启的时候不输出这些echoStop(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port shutdown if [ -z $state ];then echo -e "${green}redis ${redis_port}实例关闭成功!" fi else if [ -z $state ];then echo -e "${red}redis "${redis_port}"实例没有启动!${black}" fi fi } 2.5.编写重启模块思路:重启模块直接调用Stop模块和Start模块即可重启模块一开始要增加一个state的变量,当执行stop模块的时候就去判断state的值,如果不为空即使是没有进程也不需要输出stop模块的echo命令,直接执行start,属于跳过某个命令的实现吧Restart(){ state=restart Stop Start } 2.7.编写登陆模块思路:首先判断redis有没有启动,如果没有启动就询问是否启动,按y启动,按n就退出Login(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port else echo -e "${red}redis ${redis_port}实例没有启动!${black}" echo -en "${yellow}是否要启动reis? [y/n]${black}" read action case $action in y|Y) Start Login ;; n|N) exit 1 ;; esac fi }2.8.编写查看进程模块思路:直接用ps查即可Ps(){ ps aux | grep redis } 2.9.编写查看日志模块思路:配合各种变量去找到指令路径的日志即可Logs(){ tail -f ${redis_home}/logs/${redis_name}.log } 2.10编写帮助信息模块思路:通过echo输出提示信息Help(){ Usage echo "+-------------------------------------------------------------------------------+" echo "| start 启动redis |" echo "| stop 关闭redis |" echo "| restart 重启redis |" echo "| login 登陆redis |" echo "| ps 查看redis的进程信息,不需要加端口号 |" echo "| logs 查看redis日志持续输出 |" echo "| 除ps命令外,所有命令后面都需要加端口号 |" echo "+-------------------------------------------------------------------------------+" } 2.11编写判断脚本参数模块思路:判断脚本的参数是否不等于2,如果传入的参数不是两个的时候(因为很多模块都需要传入指令和端口这俩参数),再判断$1传入的值是不是ps和-h,因为ps和-h只需要一个参数即可,如果不是ps和-h,那么久输出使用方法,然后退出脚本if [ $# -ne 2 ];then if [ "$1" != "ps" ] && [ "$1" != "-h" ];then Usage exit 1 fi fi 2.12编写指令判断模块思路:通过case实现,根据不同的指令执行不同的函数case $1 in start) Start ;; stop) Stop ;; restart) Restart ;; login) Login ;; ps) Ps ;; logs) Logs ;; -h) Help ;; *) Help ;; esac 3.整合脚本内容#!/bin/bash #redis控制脚本 redis_port=$2 redis_name="redis_${redis_port}" redis_home=/data/redis_cluster/${redis_name} redis_conf=${redis_home}/conf/${redis_name}.conf redis_host=`ifconfig ens33 | awk 'NR==2{print $2}'` redis_pass=$3 red="\e[031m" green="\e[032m" yellow="\e[033m" black="\e[0m" Usage(){ echo "usage: sh $0 {start|stop|restart|login|ps|logs|-h} PORT" } Start(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -eq 0 ];then redis-server ${redis_conf} if [ -z $state ];then echo -e "${green}redis ${redis_port}实例启动成功!${black}" else echo -e "${green}redis ${redis_port}实例重启成功!${black}" fi netstat -lnpt | grep ${redis_port} else if [ -z $state ];then echo -e "${yellow}redis "${redis_port}"实例已经是启动状态!${black}" netstat -lnpt | grep ${redis_port} fi fi } Stop(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port shutdown if [ -z $state ];then echo -e "${green}redis ${redis_port}实例关闭成功!" fi else if [ -z $state ];then echo -e "${red}redis "${redis_port}"实例没有启动!${black}" fi fi } Restart(){ state=restart Stop Start } Login(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port else echo -e "${red}redis ${redis_port}实例没有启动!${black}" echo -en "${yellow}是否要启动reis? [y/n]${black}" read action case $action in y|Y) Start Login ;; n|N) exit 1 ;; esac fi } Ps(){ ps aux | grep redis } Logs(){ tail -f ${redis_home}/logs/${redis_name}.log } Help(){ Usage echo "+-------------------------------------------------------------------------------+" echo "| start 启动redis |" echo "| stop 关闭redis |" echo "| restart 重启redis |" echo "| login 登陆redis |" echo "| ps 查看redis的进程信息,不需要加端口号 |" echo "| logs 查看redis日志持续输出 |" echo "| 除ps命令外,所有命令后面都需要加端口号 |" echo "+-------------------------------------------------------------------------------+" } if [ $# -ne 2 ];then if [ "$1" != "ps" ] && [ "$1" != "-h" ];then Usage exit 1 fi fi case $1 in start) Start ;; stop) Stop ;; restart) Restart ;; login) Login ;; ps) Ps ;; logs) Logs ;; -h) Help ;; *) Help ;; esac4.使用redis运维脚本4.1.查看帮助信息[root@redis-1 ~]# sh redis_shell.sh -h usage: sh redis_shell.sh {start|stop|restart|login|ps|logs|-h} PORT +-------------------------------------------------------------------------------+ | start 启动redis | | stop 关闭redis | | restart 重启redis | | login 登陆redis | | ps 查看redis的进程信息,不需要加端口号 | | logs 查看redis日志持续输出 | | 除ps命令外,所有命令后面都需要加端口号 | +-------------------------------------------------------------------------------+ 4.2.启动redis第一次启动会提示启动成功,第二次在启动提示已经启动[root@redis-1 ~]# sh redis_shell.sh start 6379 redis 6379实例启动成功! tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 101765/redis-server tcp 0 0 192.168.81.210:6379 0.0.0.0:* LISTEN 101765/redis-server [root@redis-1 ~]# sh redis_shell.sh start 6379 redis 6379实例已经是启动状态! tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 101765/redis-server tcp 0 0 192.168.81.210:6379 0.0.0.0:* LISTEN 101765/redis-server [root@redis-1 ~]# 4.3.关闭redis[root@redis-1 ~]# sh redis_shell.sh stop 6379 redis 6379实例关闭成功! [root@redis-1 ~]# [root@redis-1 ~]# sh redis_shell.sh stop 6379 redis 6379实例没有启动!4.4.重启redis[root@redis-1 ~]# sh redis_shell.sh restart 6379 redis 6379实例重启成功! tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 102654/redis-server tcp 0 0 192.168.81.210:6379 0.0.0.0:* LISTEN 102654/redis-server 4.5.登陆redis启动了redis进行登陆[root@redis-1 ~]# sh redis_shell.sh login 6379 192.168.81.210:6379> DBSIZE (integer) 0没有启动redis进行登陆,首先询问是否启动,启动即可进入,不启动就退出[root@redis-1 ~]# sh redis_shell.sh login 6379 redis 6379实例没有启动! 是否要启动reis? [y/n]y redis 6379实例启动成功! tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN - tcp 0 0 192.168.81.210:6379 0.0.0.0:* LISTEN - 192.168.81.210:6379> DBSIZE (integer) 0 192.168.81.210:6379> exit [root@redis-1 ~]# sh redis_shell.sh stop 6379 redis 6379实例关闭成功! [root@redis-1 ~]# sh redis_shell.sh login 6379 redis 6379实例没有启动! 是否要启动reis? [y/n]n 4.6.查看进程无需跟端口号[root@redis-1 ~]# sh redis_shell.sh ps avahi 6935 0.0 0.1 62272 2296 ? Ss 1月29 0:04 avahi-daemon: running [redis-1.local] root 79457 0.1 0.4 136972 7720 ? Ssl 2月01 1:43 redis-server 192.168.81.210:6380 [cluster] root 79461 0.1 0.4 136972 7688 ? Ssl 2月01 1:44 redis-server 192.168.81.210:6381 [cluster] root 101261 0.0 0.3 151888 5648 pts/2 S+ 13:10 0:01 vim redis_shell.sh root 102767 0.0 0.0 113176 1412 pts/0 S+ 13:51 0:00 sh redis_shell.sh ps root 102772 0.0 0.0 112728 968 pts/0 R+ 13:51 0:00 grep redis4.7.查看日志持续输出日志信息[root@redis-1 ~]# sh redis_shell.sh logs 6379
部署三主三从redis cluster集群架构图环境准备1.redis运维脚本使用这个脚本管理redis#!/bin/bash #redis控制脚本 redis_port=$2 redis_name="redis_${redis_port}" redis_home=/data/redis_cluster/${redis_name} redis_conf=${redis_home}/conf/${redis_name}.conf redis_host=`ifconfig ens33 | awk 'NR==2{print $2}'` redis_pass=$3 red="\e[031m" green="\e[032m" yellow="\e[033m" black="\e[0m" Usage(){ echo "usage: sh $0 {start|stop|restart|login|ps|logs|-h} PORT" } Start(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -eq 0 ];then redis-server ${redis_conf} if [ -z $state ];then echo -e "${green}redis ${redis_port}实例启动成功!${black}" else echo -e "${green}redis ${redis_port}实例重启成功!${black}" fi netstat -lnpt | grep ${redis_port} else if [ -z $state ];then echo -e "${yellow}redis "${redis_port}"实例已经是启动状态!${black}" netstat -lnpt | grep ${redis_port} fi fi } Stop(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port shutdown if [ -z $state ];then echo -e "${green}redis ${redis_port}实例关闭成功!" fi else if [ -z $state ];then echo -e "${red}redis "${redis_port}"实例没有启动!${black}" fi fi } Restart(){ state=restart Stop Start } Login(){ redis_cz=`netstat -lnpt | grep redis | grep "${redis_port}" | wc -l` if [ $redis_cz -gt 0 ];then redis-cli -h $redis_host -p $redis_port else echo -e "${red}redis ${redis_port}实例没有启动!${black}" echo -en "${yellow}是否要启动reis? [y/n]${black}" read action case $action in y|Y) Start Login ;; n|N) exit 1 ;; esac fi } Ps(){ ps aux | grep redis } Logs(){ tail -f ${redis_home}/logs/${redis_name}.log } Help(){ Usage echo "+-------------------------------------------------------------------------------+" echo "| start 启动redis |" echo "| stop 关闭redis |" echo "| restart 重启redis |" echo "| login 登陆redis |" echo "| ps 查看redis的进程信息,不需要加端口号 |" echo "| logs 查看redis日志持续输出 |" echo "| 除ps命令外,所有命令后面都需要加端口号 |" echo "+-------------------------------------------------------------------------------+" } if [ $# -ne 2 ];then if [ "$1" != "ps" ] && [ "$1" != "-h" ];then Usage exit 1 fi fi case $1 in start) Start ;; stop) Stop ;; restart) Restart ;; login) Login ;; ps) Ps ;; logs) Logs ;; -h) Help ;; *) Help ;; esac2.部署redis节点三个主机都执行,共部署两个redis节点,一个6380一个6381端口1.创建部署路径 mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid} 2.准备配置文件 cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6381 daemonize yes logfile /data/redis_cluster/redis_6381/logs/redis_6381.log pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log dbfilename "redis_6381.rdb" dir /data/redis_cluster/redis_6381/data cluster-enabled yes cluster-config-file node_6381.conf cluster-node-timeout 15000 save 60 10000 save 300 10 save 900 1 EOF 3.启动 [root@redis-1 ~]# ./redis_shell.sh start 6380 redis 6380实例启动成功! tcp 0 0 192.168.81.210:6380 0.0.0.0:* LISTEN 127999/redis-server tcp 0 0 192.168.81.210:16380 0.0.0.0:* LISTEN 127999/redis-server [root@redis-1 ~]# ./redis_shell.sh start 6381 redis 6381实例启动成功! tcp 0 0 192.168.81.210:6381 0.0.0.0:* LISTEN 128014/redis-server tcp 0 0 192.168.81.210:16381 0.0.0.0:* LISTEN 128014/redis-server 3.配置集群节点之间相互发现互相发现只需要在一个节点上操作即可[root@redis-2 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> CLUSTER MEET 192.168.81.210 6381 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.220 6380 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.220 6381 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.230 6380 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.230 6381 OK 192.168.81.210:6380> CLUSTER NODES 34e698b929948c3c61c4ba40c129161b736ee5cc 192.168.81.230:6381 master - 0 1612334628247 5 connected 4827ff5cbc7122a4459b1d91bd15a89e0661a91b 192.168.81.220:6381 master - 0 1612334624212 2 connected 8d918c708db4a9fbe6b08d9f707d501eb328885e 192.168.81.230:6380 master - 0 1612334625222 0 connected 4e99bc582fede8e359fb25d163e7267f616409ff 192.168.81.210:6381 master - 0 1612334626229 1 connected 5f19db5c04ccaea18270819f5af37cacbf41a800 192.168.81.210:6380 myself,master - 0 0 3 connected 454fe9862588f97f969c181b3f8c5e24f6135265 192.168.81.220:6380 master - 0 1612334627241 4 connected 6个redis节点已经全部发现4.配置cluster分配槽位在redis-1上操作即可1.分配槽位 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0..5461} OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster addslots {5462..10922} OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380 cluster addslots {10923..16383} OK 2.查看集群状态 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:1 cluster_current_epoch:5 cluster_my_epoch:3 cluster_stats_messages_sent:488 cluster_stats_messages_received:488 5.配置三主三从集群1.获取集群信息 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes | grep 6380 | awk '{print $1,$2}' 454fe9862588f97f969c181b3f8c5e24f6135265 192.168.81.220:6380 5f19db5c04ccaea18270819f5af37cacbf41a800 192.168.81.210:6380 8d918c708db4a9fbe6b08d9f707d501eb328885e 192.168.81.230:6380 2.配置交叉复制 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 192.168.81.210:6381> CLUSTER REPLICATE 454fe9862588f97f969c181b3f8c5e24f6135265 OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6381 192.168.81.220:6381> CLUSTER REPLICATE 8d918c708db4a9fbe6b08d9f707d501eb328885e OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 192.168.81.230:6381> CLUSTER REPLICATE 5f19db5c04ccaea18270819f5af37cacbf41a800 OK [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster nodes 454fe9862588f97f969c181b3f8c5e24f6135265 192.168.81.220:6380 master - 0 1612336046339 4 connected 5462-10922 4827ff5cbc7122a4459b1d91bd15a89e0661a91b 192.168.81.220:6381 slave 8d918c708db4a9fbe6b08d9f707d501eb328885e 0 1612336049371 2 connected 5f19db5c04ccaea18270819f5af37cacbf41a800 192.168.81.210:6380 myself,master - 0 0 3 connected 0-5461 8d918c708db4a9fbe6b08d9f707d501eb328885e 192.168.81.230:6380 master - 0 1612336047350 0 connected 10923-16383 34e698b929948c3c61c4ba40c129161b736ee5cc 192.168.81.230:6381 slave 5f19db5c04ccaea18270819f5af37cacbf41a800 0 1612336045330 5 connected 4e99bc582fede8e359fb25d163e7267f616409ff 192.168.81.210:6381 slave 454fe9862588f97f969c181b3f8c5e24f6135265 0 1612336048360 4 connected已经交叉复制,到此三主三从redis cluster集群部署完成6.快速删除一个redis cluster集群方式两种方法:将所有redis节点的数据文件全部删除包括rdb、node_6380.conf登陆每一个节点,执行cluster reset
1.redis cluster原理概念1.1.cluster架构概念redis cluster是redis的分布式解决方案,在3.0版本正式推出,如果公司的redis是2.x版本,就需要升级了redis哨兵集群不足之处:资源利用率低,只有一台主库对外提供服务假如哨兵模式有3个节点,只有其中一个节点对外提供服务,其他两个节点都处于备份状态,这样就会造成资源的浪费,redis将数据都写在内存中,只有主节点工作,那么内存只有主节点上的那点内存,从节点上的内存也就造成了浪费主库压力比较大,性能有瓶颈只有主库在工作,所有的写都是主节点完成,这样就会造成主节点的压力比较大,从节点几乎没有压力哨兵的不足之处就在于集群不是分布式存储,只是单节点去处理,如果集群时分布式存储,那么单点和压力的问题也就解决了redis cluster适用场景:当redis遇到单机、内存、并发、流量等瓶颈时,可以采用cluster架构方案达到负载均衡的目的redis cluster之前的分布式方案:客户端分区方案,优点分区逻辑可控,缺点是需要自己处理数据路由,高可用和故障转移等。代理方案,优点是简化客户端分布式逻辑和升级维护便利,缺点加重架构部署和性能消耗。redis cluster的数据分布方式: 所有分布式数据库首先要解决把整个数据库集安装分区规则映射到多个节点的问题,也就是把数据集划分到多个节点上,redis cluster采用哈希分片规则,这样就能保证每个节点存储的数据量大致相同redis cluster原理:redis cluster会将数据自动进行分片,然后通过hash算法均匀的存放在集群中的每个节点,cluster架构在每台机器上都有一个或多个主节点和从节点,当一个节点上的master挂掉,会自动将这台机器上的某个slave切换为mastercluster架构的redis集群,可以横向扩容,由于cluster是分布式架构,单个机器的内存是32G,那么10个节点就是320G内存的存储cluster架构数据分片是由hash来进行分配的,均匀的分散在各个节点cluster架构槽位概念:每个cluster集群都有16384个槽位,这个槽位就是用来存储hash分配的分片,每一个槽位都需要分配到位,有一个槽位没有分配,整个集群都将无法使用,每一个槽位都有一个序号,它们不是顺序存放的,而是在节点一上比如有10-20序列槽位,节点二上有60-70序列的槽位,这两个节点都是10个槽位,序号不一定要顺序,但是数量一定要差不多,允许2%的误差cluster集群架构图通过hash分配数据分片到不同的redis主机在应用端配置redis cluster地址时需要将所有节点的ip和端口都添加上使用cluster集群创建的key,在哪个节点上创建的只能是自身节点可以查到数据,其他节点看不到1.2.redis cluster不合理的架构图不太合理的架构图cluster集群每个机器上都有多个master和slave,如果master节点的数据备份都在自己主机的slave上,那么当服务器1坏掉后,这个机器上的数据就丢失了,数据丢失整个应用就崩溃了合理的架构图每个节点slave都存放在别的主机,即使当前主机挂掉,另一台直接还原数据即可1.3.部署一个cluster三主三从集群具体步骤1.在三台主机上部署redis,分别启动两个不同端口的redis,一个主库一个从库2.配置cluster集群自动发现,使得集群中各个主机都知道其他主机上的redis节点3.配置集群hash分配槽位,有了槽位才可以存储数据4.使用cluster replicate使多出来的三个主库变成从库,这样就实现了三主三从1.4.环境准备2.部署redis cluster节点搭建一个三主三从的redis cluster集群配置文件中的bind也可以写成如下样子,自动识别bind地址bind $(ifconfig | awk 'NR==2{print $2}')配置文件含义port 6380 //redis端口 daemonize yes //后台启动 logfile /data/redis_cluster/redis_6380/logs/redis_6380.log //日志路径 pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log //pid存放路径 dbfilename "redis_6380.rdb" //数据文件名称 dir /data/redis_cluster/redis_6380/data //数据文件存放目录 cluster-enabled yes //开启集群模式 cluster-config-file node_6380.conf //集群数据文件路径,保存集群信息的文件 cluster-node-timeout 15000 //集群故障转移时间,多长时间无响应就切换环境准备2.1.redis-1配置配置文件自动识别bind地址1.创建节点配置文件路径 [root@redis-1 ~]# mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid} 2.准备两个配置文件一个6380,一个6381 [root@redis-1 ~]# cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 EOF [root@redis-1 ~]# cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6381 daemonize yes logfile /data/redis_cluster/redis_6381/logs/redis_6381.log pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log dbfilename "redis_6381.rdb" dir /data/redis_cluster/redis_6381/data cluster-enabled yes cluster-config-file node_6381.conf cluster-node-timeout 15000 EOF 3.启动rediscluster [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf 4.查看进程和端口 [root@redis-1 ~]# ps aux | grep redis [root@redis-1 ~]# netstat -lnpt | grep redis2.2.redis-2配置配置文件自动识别bind地址[root@redis-2 ~]# mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid} [root@redis-2 ~]# cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 EOF [root@redis-2 ~]# cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 6381 daemonize yes logfile /data/redis_cluster/redis_6381/logs/redis_6381.log pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log dbfilename "redis_6381.rdb" dir /data/redis_cluster/redis_6381/data cluster-enabled yes cluster-config-file node_6381.conf cluster-node-timeout 15000 EOF [root@redis-2 ~]# [root@redis-2 ~]# redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf [root@redis-2 ~]# redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf [root@redis-2 ~]# [root@redis-2 ~]# ps aux | grep redis [root@redis-2 ~]# netstat -lnpt | grep redis2.3.redis-3配置手动填写bind ip地址[root@redis-3 ~]# mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid} [root@redis-3 ~]# cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf <<EOF bind 192.168.81.230 port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 EOF [root@redis-3 ~]# cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF bind 192.168.81.230 port 6381 daemonize yes logfile /data/redis_cluster/redis_6381/logs/redis_6381.log pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log dbfilename "redis_6381.rdb" dir /data/redis_cluster/redis_6381/data cluster-enabled yes cluster-config-file node_6381.conf cluster-node-timeout 15000 EOF [root@redis-3 ~]# [root@redis-3 ~]# redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf [root@redis-3 ~]# redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf [root@redis-3 ~]# [root@redis-3 ~]# ps aux | grep redis [root@redis-3 ~]# netstat -lnpt | grep redis 2.4.查看redis cluster进程每个节点启动了cluster后,进程名上会增加cluster每个redis节点会开放两个端口,服务端口6380,集群通信端口16380(在服务端口基础上增加10000)4.查看进程 [root@redis-1 ~]# ps aux | grep redis avahi 6935 0.0 0.1 62272 2296 ? Ss 1月29 0:02 avahi-daemon: running [redis-1.local] root 31846 0.3 0.5 141068 10800 ? Ssl 1月30 10:13 redis-server 192.168.81.210:6379 root 31859 0.3 0.4 136972 7744 ? Ssl 1月30 11:43 redis-sentinel 192.168.81.210:26379 [sentinel] root 78126 0.2 0.4 136972 7584 ? Ssl 14:40 0:00 redis-server 192.168.81.210:6380 [cluster] root 78130 0.4 0.4 136972 7588 ? Ssl 14:40 0:00 redis-server 192.168.81.210:6381 [cluster] root 78136 0.0 0.0 112728 988 pts/2 R+ 14:40 0:00 grep --color=auto redis [root@redis-1 ~]# netstat -lnpt | grep redis tcp 0 0 192.168.81.210:26379 0.0.0.0:* LISTEN 31859/redis-sentine tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 31846/redis-server tcp 0 0 192.168.81.210:6379 0.0.0.0:* LISTEN 31846/redis-server tcp 0 0 192.168.81.210:6380 0.0.0.0:* LISTEN 78126/redis-server tcp 0 0 192.168.81.210:6381 0.0.0.0:* LISTEN 78130/redis-server tcp 0 0 192.168.81.210:16380 0.0.0.0:* LISTEN 78126/redis-server tcp 0 0 192.168.81.210:16381 0.0.0.0:* LISTEN 78130/redis-server2.5.查看集群信息文件内容集群模式的redis除了原有的配置文件之外又增加了一个集群配置文件,当集群内节点信息发生变化时,如添加节点,节点下线,故障转移等,节点都会自动保存集群状态到配置文件,redis自动维护集群配置文件,不需要手动修改防止节点重启时产生错乱在集群启动后会生成一个数据文件,这个数据文件其实保存的就是集群的信息,在没有配置集群互相发现时,单个节点只保存自己的集群信息,文件中有节点id信息,每个节点的id都是唯一的当配置了互相发现了配置文件中就会增加所有节点的信息[root@redis-1 ~]# cat /data/redis_cluster/redis_6380/data/node_6380.conf b7748aedb5e51921db67c54e0c6263ed28043948 :0 myself,master - 0 0 0 connected vars currentEpoch 0 lastVoteEpoch 0 [root@redis-1 ~]# cat /data/redis_cluster/redis_6381/data/node_6381.conf 1ec79d498ecf9f272373740e402398e4c69cacb2 :0 myself,master - 0 0 0 connected vars currentEpoch 0 lastVoteEpoch 0 也可以登录redis进行查看[root@redis-1 ~]# for i in {1..3} do for j in {0..1} do echo "192.168.81.2${i}0---638${j}" redis-cli -h 192.168.81.2${i}0 -p 638${j} cluster nodes done done 192.168.81.210---6380 b7748aedb5e51921db67c54e0c6263ed28043948 :6380 myself,master - 0 0 0 connected 192.168.81.210---6381 1ec79d498ecf9f272373740e402398e4c69cacb2 :6381 myself,master - 0 0 0 connected 192.168.81.220---6380 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 :6380 myself,master - 0 0 0 connected 192.168.81.220---6381 bedd9482b08a06b0678fba01bb1c24165e56636c :6381 myself,master - 0 0 0 connected 192.168.81.230---6380 759ad5659d449dc97066480e1b7efbc10b34461d :6380 myself,master - 0 0 0 connected 192.168.81.230---6381 a2c95db5d6f9f288e6768c8d00e90fb7631f3021 :6381 myself,master - 0 0 0 connected3.配置cluster集群互相发现3.1.互相发现概念cluster集群互相发现只需要在一个节点上配置,所有节点都会接收到配置信息并自动加入到配置文件中例如在redis-1的6380节点上增加了本机的6381端口和redis-2的6380端口,这时在redis-2上查看6380的配置里面就能看到6380节点和redis-1的6380以及6381节点信息,这时redis-3的两个节点还有本机的6381则还是一条,因为他们没有加入在哪个节点添加的发现另一个节点的信息,那么当前这个节点就已经加入到了集群中其实只要在集群的任意一个节点配置,集群的所有节点都会自动添加配置下面演示一个在reids-1上添加几个节点,在redis-2上看是否自动配置1.在redis-1的6380节点上增加本机的6381和redis-2的6380端口 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> CLUSTER MEET 192.168.81.210 6381 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.220 6380 OK 2.查看redis-2的6380集群配置文件 [root@redis-2 ~]# cat /data/redis_cluster/redis_6380/data/node_6380.conf 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 master - 0 1612169525469 1 connected b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612169525369 0 connected 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 myself,master - 0 0 2 connected vars currentEpoch 2 lastVoteEpoch 0 很明显的看出已经将redis-1的6380和6381以及redis-2本机的6380端口都加到了集群配置文件中 3.查看redis-2的6381节点集群配置文件 [root@redis-2 ~]# cat /data/redis_cluster/redis_6381/data/node_6381.conf bedd9482b08a06b0678fba01bb1c24165e56636c :0 myself,master - 0 0 0 connected vars currentEpoch 0 lastVoteEpoch 03.2.将集群的所有节点进行互相发现在集群的任意一个节点配置就可以1.配置互相发现 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> CLUSTER MEET 192.168.81.210 6381 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.220 6380 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.220 6381 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.230 6380 OK 192.168.81.210:6380> CLUSTER MEET 192.168.81.230 6381 OK 2.查看配置文件是否增加,所有节点的配置文件都会生成 [root@redis-1 ~]# cat /data/redis_cluster/redis_6381/data/node_6381.conf 759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612169812886 4 connected 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 myself,master - 0 0 1 connected 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612169814797 2 connected bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 master - 0 1612169815806 0 connected a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612169815708 5 connected b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612169816814 3 connected vars currentEpoch 5 lastVoteEpoch 0 4.cluster集群分配操作4.1.redis cluster通讯流程集群内消息传递是同步的在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障灯状态信息,redis集群采用gossip协议,gossip协议工作原理就是节点彼此不断交换信息,一段时间后所有的节点偶会指定集群完整信息,这种方式类似于流言传播,因此只需要在一台节点配置集群信息所有节点都能收到信息通信过程: 1.集群中的每一个节点都会单独开辟一个tcp通道用于节点之间彼此通信,通信端口在基础端口上增加10000 2.每个节点在固定周期内通过特定规则选择结构节点发送ping消息 3.接收到ping消息的节点用pong作为消息响应,集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点的信息,也可能知道部分节点信息,只要这些节点彼此可以正常通信,最终他们就会达成一致的状态,当节点出现故障,新节点加入,主从角色变化等,彼此之间不断发生ping/pong消息,最终达成同步的模板通讯消息类型:gossip,信息交换,常见的消息分为ping、pong、meet、fail通讯示意图没有分配槽位时集群的状态,所有节点执行cluster info,cluster_state都是fail,fail状态表示集群不可用,没有分配槽位,cluster_slots都会显示04.2.手动配置集群槽位每个cluster集群都有16384个槽位,我们有三台机器,想要手动分配平均就需要使用16384除3redis-1 0-5461redis-2 5642-10922redis-3 10923-16383分配槽位语法格式(交互式):CLUSTER ADDSLOTS 0 5461分配槽位语法:redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0…5461}删除槽位分配语法格式: redis-cli -h 192.168.81.210 -p 6380 cluster delslots {5463…10921}1.配置手动分配槽位 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0..5461} OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster addslots {5462..10922} OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380 cluster addslots {10923..16383} OK 2.查看集群状态,到目前为止集群已经是可用的了 [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:5 cluster_my_epoch:2 cluster_stats_messages_sent:170143 cluster_stats_messages_received:170142 3.查看nodes文件内容 [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster nodes a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612251539412 5 connected bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 master - 0 1612251538402 0 connected 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 myself,master - 0 0 2 connected 5462-10922 b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612251540418 3 connected 0-5461 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 master - 0 1612251537394 1 connected 759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612251536386 4 connected 10923-163834.3.创建key验证集群是否可用不是所有的key都能插入,有的key插入的时候就提示说你应该去192.168.81.230上插入,这时手动到对应的主机上执行就可以插入,这是由于cluster集群槽位都是分布在不同节点的,每次新建一个key,都会通过hash算法均匀的在不同节点去创建不同节点创建的key只由自己节点可以看到自己创建的数据[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> set k1 v1 (error) MOVED 12706 192.168.81.230:6380 192.168.81.210:6380> set k2 v2 OK 192.168.81.210:6380> set k3 v3 OK 192.168.81.210:6380> set k4 v4 (error) MOVED 8455 192.168.81.220:6380 192.168.81.210:6380> set k5 v5 (error) MOVED 12582 192.168.81.230:6380 192.168.81.210:6380> set k6 v6 OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380 192.168.81.230:6380> set k1 v1 OK 192.168.81.230:6380> set k5 v5 OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 192.168.81.220:6380> set k4 v4 OK 4.4.ASK路由解决key创建提示去别的主机创建可以通过ASK路由解决创建key时提示去别的主机进行创建ASK路由创建key时,如果可以在本机直接创建就会执行创建key的命令,如果不能再本机执行,他会根据提示的主机去对应主机上创建keyASK路径的特性:每次通过hash在指定主机上创建了key后就会停留在这个主机上只需要执行redis-cli时加上-c参数即可[root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6380 192.168.81.210:6380> set k8 v8 -> Redirected to slot [8331] located at 192.168.81.220:6380 OK 192.168.81.220:6380> set k9 v9 -> Redirected to slot [12458] located at 192.168.81.230:6380 OK 192.168.81.230:6380> set k10 v10 OK 192.168.81.230:6380> set k11 v11 OK 192.168.81.230:6380> set k12 v12 -> Redirected to slot [2863] located at 192.168.81.210:6380 OK 192.168.81.210:6380> set k13 v13 -> Redirected to slot [6926] located at 192.168.81.220:6380 OK 192.168.81.220:6380> set k14 v14 -> Redirected to slot [11241] located at 192.168.81.230:6380 OK 很清楚的展示了在哪台主机上创建4.5.验证hash分配是否均已cluster架构是分布式的,创建的key会通过hash将数据均已的分布在每台主机的槽位上1.插入一千条数据,查看三个节点是否分配均已 插入的时候使用-c,自动在某个节点上插入数据 [root@redis-1 ~]# for i in {1..1000} do redis-cli -c -h 192.168.81.210 -p 6380 set key_${i} value_${i} done 2.查看每个节点的数据量,可以看到非常均匀,误差只有一点点 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> DBSIZE (integer) 339 [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 192.168.81.220:6380> DBSIZE (integer) 339 [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380 192.168.81.230:6380> DBSIZE (integer) 336 192.168.81.230:6380> exit 5.配置cluster集群三主三从高可用实现步骤: 1.使用cluster replicate将主机的6381redis节点交叉成为别的主机6380节点的从库 2.查看集群状态即可5.1.三主三从架构图三主三从是redis cluster最常用的架构,每个从节点复制的都不是本机主库的数据,而是其他节点主库的数据,这样即使某一台主机坏掉了,从节点备份还是在其他机器上,这样就做到了高可用,三主三从架构允许最多坏一台主机三主三从我们采用交叉复制架构类型,这样可以做到最多坏一台主机集群还是正常可以用的,如果每台主机的6381节点都是6380节点的备份,那么这台机器坏了,集群就不可用了,因此想要做到高可用,就采用交叉复制交叉复制的架构,当主节点挂掉了,主节点备份的从节点就会自动成为主节点,当主节点上线后每个节点的6380端口都是主库,6381端口都是从库从节点对应的主节点关系: redis-1的6381从节点对应的主节点是redis-2的6380主节点 redis-2的6381从节点对应的主节点是redis-3的6380主节点 redis-3的6381从节点对应的主节点是redis-1的6380主节点5.2.将每一个节点都配置rdb持久化在所有节点端口的配置文件中加上rdb持久化配置即可vim /data/redis_cluster/redis_6380/conf/redis_6380.conf bind 192.168.81.210 port 6380 daemonize yes logfile /data/redis_cluster/redis_6380/logs/redis_6380.log pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log dbfilename "redis_6380.rdb" dir /data/redis_cluster/redis_6380/data cluster-enabled yes cluster-config-file node_6380.conf cluster-node-timeout 15000 #持久化配置 save 60 10000 save 300 10 save 900 1 重启redis redis-cli -h 192.168.81.210 -p 6380 shutdown redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf5.3.配置三主三从配置三主三从规范操作步骤1.将集群信息粘到txt中,只保留下6380端口信息2.配置命令在txt中准备好在复制到命令行主节点我们已经有了,目前6个节点全是主节点,我们需要把所有主机的6381的主节点配置成从节点从节点对应的主节点关系: redis-1的6381从节点对应的主节点是redis-2的6380主节点 redis-2的6381从节点对应的主节点是redis-3的6380主节点 redis-3的6381从节点对应的主节点是redis-1的6380主节点CLUSTER REPLICATE 是配置当前节点成为某个主节点的从节点,replicate命令其实就相当于执行了slaveof,同步了某一个主库,并且在日志中查看到的就是主从同步的过程1.配置从节点连接主节点,交叉式复制 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 CLUSTER REPLICATE 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6381 CLUSTER REPLICATE 759ad5659d449dc97066480e1b7efbc10b34461d OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 CLUSTER REPLICATE b7748aedb5e51921db67c54e0c6263ed28043948 OK 2.查看集群节点信息,发现已经是三主三从了 [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 cluster nodes a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 myself,slave b7748aedb5e51921db67c54e0c6263ed28043948 0 0 5 connected bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612323918342 4 connected b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612323919350 3 connected 0-5461 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 1612323917331 2 connected 759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612323916826 4 connected 10923-16383 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612323920357 2 connected 5462-10922 配置完主从,可以看到集群中已经有slave节点了,并且也是交叉复制的打开主库的日志可以看到哪个从库同步了主库的日志,打开从库的日志可以看到同步了哪个主库的日志5.3.模拟故障转移三主三从架构允许最多坏一台主机,模拟将redis-1机器的主库6380挂掉,查看集群间的故障迁移思路: 1.将redis-1的6380主库关掉,查看集群状态信息是否将slave自动切换为master 2.当master上线后会变成一个节点的从库 3.将master通过cluster failover重新成为主库5.1.模拟坏掉redis-1的主库并验证就能是否可用1.挂掉redis-1的主库 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 shutdown 2.查看日志 先是由于主库挂了状态变成fail,当从库变成主库后,状态再次变为ok [root@redis-1 ~]# tail -f /data/redis_cluster/redis_6381/logs/redis_6381.log 124058:S 03 Feb 13:16:00.233 # Cluster state changed: fail 124058:S 03 Feb 13:17:01.857 # Cluster state changed: ok 3.查看集群信息 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes 4.查看集群状态 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:7 cluster_my_epoch:2 cluster_stats_messages_sent:18202 cluster_stats_messages_received:17036 5.验证集群是否可用 [root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6381 set k1111 v1111 OK当主库挂掉后,查看集群信息时会看到提示主库已经是fail状态,此时可用看到192.168.81.230机器的6381端口成为了master,192.168.81.230的6381端口是redis-1的从库,从库变为主库后,集群状态再次变为ok5.3.2.redis-1节点的主库恢复目前的架构图当主库重新加入集群后,架构图就变成了如下样子,主库的6380就成为了192.168.81.230的从库,而192.168.81.230的从库变成了192.168.81.210的主库1.启动redis-1的6380主库 [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf 2.查看集群信息 [root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6380 cluster nodes 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 1612330250901 2 connected b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 myself,slave a2c95db5d6f9f288e6768c8d00e90fb7631f3021 0 0 3 connected 759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612330255958 4 connected 10923-16383 bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612330252920 4 connected a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612330254941 7 connected 0-5461 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612330256960 2 connected 5462-10922 5.3.3.将恢的主库重新变为主库目前主库已经重新上线了,且现在是192.168.81.230的从库,而原来192.168.81.230的从库变成了现在192.168.81.210的主库,我们需要把关系切换回来,不能让一台机器上同时存在两台主库,每次故障处理后一定要把架构修改会原来的样子从库切换成主库也特别简单,只需要执行一个cluster falover即可变为主库cluster falover确实也类似于关系互换,简单理解就是原来的从变成了主,现在的主变成了从,这样一来就可以把故障恢复的主机重新变为主库cluster falover原理:falover原理也就是先执行了slave no one,然后在对应的由主库变为从库的机器上执行了slave of1.将故障上线的主库重新成为主库 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 192.168.81.210:6380> CLUSTER FAILOVER OK 2.查看集群信息,192.168.81.210的发现6380重新成为了master,192.168.81.230的从库变成了slave [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes 759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612331847795 12 connected 10923-16383 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612331849307 11 connected 5462-10922 b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612331848299 10 connected 0-5461 bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612331850317 12 connected a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 slave b7748aedb5e51921db67c54e0c6263ed28043948 0 1612331851324 10 connected 1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 myself,slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 0 8 connected查看集群信息,192.168.81.210的发现6380重新成为了master,192.168.81.230的从库变成了slave到此cluster集群故障转移成功,集群状态一切正常[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:16 cluster_my_epoch:16 cluster_stats_messages_sent:18614 cluster_stats_messages_received:34976.redis cluster需要注意的几点生产环境数据量可能非常大,当主库故障重新上线时,执行CLUSTER FAILOVER会很慢,因为这个就相当于是主从复制切换了,从库(刚上线的原来主库)关闭主从复制,主库(主库坏掉前的从库)同步从库(刚上线的原来主库)数据,然后从库(刚上线的原来主库)重新变为主库,这个时间一定要等,切记,千万不要因为慢在主库上(主库坏掉前的从库)同步手动进行了CLUSTER REPLICATE,这样确实会非常快的将主库(主库坏掉前的从库)重新变为从库,但也意味着这个节点数据全部丢失,因为clusert replicate相当于slaveof,slaveof会把自己的库清掉,这时候从库(刚上线的原来主库)在执行这CLUSTER FAILOVER同步着主库(主库坏掉前的从库)的数据,主库那边执行了replicate去同步从库(刚上线的原来主库),从而导致从库(刚上线的原来主库)还没有同步完主库(主库坏掉前的从库的数据),主库(主库坏掉前的从库)数据就丢失,整个集群还是可以用的,只是这个主库节点和从节点数据全部丢失,其他两个主库从库还能使用。切记,当从库执行CLUSTER FAILOVER变为主库时,一定不要在主库上执行CLUSTER REPLICATE变为从库,虽然CLUSTER REPLICATE变为从库很快,但是会清空自己的数据去同步主库,这时主库还没有数据,因此就会导致数据全部丢失CLUSTER FAILOVER:首先执行slave on one变为一个单独的节点,然后在要变成从库的节点上执行slaveof,只要从库执行完slave of,执行CLUSTER FAILOVER的节点就变成了主库CLUSTER REPLICATE:只是执行了slaveof使自身成为从节点当redis cluster主从正在同步时,不要执行cluster replicate,当主从复制完在执行,如何看主从是否复制完就要看节点的rdb文件是否是.tmp结尾的,如果是tmp结尾就说明他们正在同步数据,此时不要对集群做切换操作小总结: 1.3.0版本以后推出集群功能 2.cluster集群有16384个槽位,误差在2%之间 3.槽位与序号顺序无关,重点是槽的数量 4.通过发现集群,与集群之间实现消息传递 5.配置文件无需手动修改,都是自动生成的 6.分配操作,必须将所有的槽位分配完毕 7.理清复制关系,画图,按照图形执行复制命令 8.当集群状态为ok时,集群才可以正常使用 9.反复测试,批量插入key,验证分配是否均匀 10.测试高可用,关闭任意主节点,集群是否自动转移 11.当主节点修复后,执行主从关系切换 12.做实验尽量贴合生成环境,尽量使用和生成环境一样数量的数据 13.评估和记录同步数据、故障转移完成的时间 14.向领导汇报时要有图、文档、实验环境,随时都可以演示当应用需要连接redis cluster集群时要将所有节点都写在配置文件中
1.修改jar为war包形式<project ······> <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> //指定为war包 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> ······2.去除Spring Boot内置Tomcat将以下代码从pom.xml中删除 <!-- tomcat 依赖包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> 3.增加Tomcat启动插件 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <includeSystemScope>true</includeSystemScope> <fork>true</fork> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> 4.使用maven编译程序[root@192 TmallDemo-master]# mvn clean install -Dmaven.test.skip=true [root@192 TmallDemo-master]# ll target/ 总用量 447084 drwxr-xr-x. 6 root root 135 10月 17 22:10 classes drwxr-xr-x. 3 root root 25 10月 17 22:10 generated-sources drwxr-xr-x. 2 root root 28 10月 17 22:10 maven-archiver drwxr-xr-x. 3 root root 35 10月 17 22:10 maven-status drwxr-xr-x. 5 root root 80 10月 17 22:10 TmallDemo-0.0.1-SNAPSHOT -rw-r--r--. 1 root root 232534650 10月 17 22:11 TmallDemo-0.0.1-SNAPSHOT.war
Redis哨兵集群主库故障数据恢复当主库修复后重新上线首先通过哨兵知道谁是当前的主库,然后就会去找主库同步数据,并且会自动修改配置文件,当数据同步后,想恢复的主库重新成为主库则需要把主库的权重调高,然后重新选举,这时原来的主库就能成为新的主库,调整完再将主库的权重值调成默认的实现思路: 1.将故障的主库重新恢复 2.查看当前的主从状态,验证由于主库宕机,与从库产生的数据是否同步 3.调整权重值 4.重新选举,使原来的主库变成新的主库 5.恢复的主库重新成为新的主库后,要把调整的权重值全部变成默认值主库可以重新加入哨兵集群的前提:剩余的两个节点必须有一个是master,且这两个节点配置文件已经指定了新的master地址1.恢复损坏的主库1.恢复主库 [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf [root@redis-1 ~]# [root@redis-1 ~]# redis-sentinel /data/redis_cluster/redis_26379/conf/redis_26379.conf 2.查看其他两个节点的日志输出,任意一个节点都会输出,表示redis-1已经加入集群了 tail -f /data/redis_cluster/redis_26379/logs/redis_26379.log 78223:X 30 Jan 12:05:09.073 # -sdown sentinel ac621a57296db0cead07751a4f0a19c570daa7f9 192.168.81.210 26379 @ mymaster 192.168.81.220 6379,2.查看恢复的主库redis-1配置文件[root@redis-1 ~]# cat /data/redis_cluster/redis_26379/conf/redis_26379.conf bind 192.168.81.210 port 26379 daemonize yes logfile "/data/redis_cluster/redis_26379/logs/redis_26379.log" dir "/data/redis_cluster/redis_26379/data" sentinel myid ac621a57296db0cead07751a4f0a19c570daa7f9 sentinel monitor mymaster 192.168.81.220 6379 2可以看到已经自动修改为当前库的地址3.查看恢复的主库redis-1的主从关系1.已经同步了当前主库redis-2 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> CONFIG GET slaveof 1) "slaveof" 2) "192.168.81.220 6379" 2.已经可以看到主库宕机阶段,从库变为主库产生的最新数据 127.0.0.1:6379> get gzzy_test "guzhangzhuanyi"4.配置恢复的主库的权重值,使其重新选举为主库哨兵的选举首先是 1.查看谁的权重优先级比较高的当选为主库 2.权重优先级一致,就比较id,id大的当选1.查看其他两个节点的权重值 [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6379 config get slave-priority 1) "slave-priority" 2) "100" [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6379 config get slave-priority 1) "slave-priority" 2) "100" 2.将其他两个节点的权重值改为0 [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6379 config set slave-priority 0 OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6379 config set slave-priority 0 OK 3.设置恢复的主库的权限优先级高于其他两个节点 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6379 config set slave-priority 150 OK [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6379 config get slave-priority 1) "slave-priority" 2) "150" 4.重新选举 [root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 26379 sentinel failover mymaster 5.查看其他节点sentinel输出的日志 [root@redis-3 ~]# tail -f /data/redis_cluster/redis_26379/logs/redis_26379.log 78223:X 30 Jan 12:32:27.591 * +convert-to-slave slave 192.168.81.220:6379 192.168.81.220 6379 @ mymaster 192.168.81.210 6379 根据日志的输出,可以明显的看出调整了redis-1的权重优先级为150,比其他两个节点的高,因此redis-1就变成了主库查看节点的主从复制关系主库没有同步的库,其他两个节点都同步redis-1的主库[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6379 config get slaveof 1) "slaveof" 2) "" [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6379 config get slaveof 1) "slaveof" 2) "192.168.81.210 6379" [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6379 config get slaveof 1) "slaveof" 2) "192.168.81.210 6379" 5.将权重值调整为默认值将权重值调整为默认值,方便下次选举时作为判断条件[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6379 config set slave-priority 100 OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6379 config set slave-priority 100 OK [root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6379 config set slave-priority 100 OK
1.redis哨兵模式原理redis主从复制的不足: 当主库宕机后,slave无法自己变成主库,进行数据的写入,每次都需要人为配置将从库变为主库才能进行数据写入,当主库修复后还需要人为配置导入从库主机在配置主从复制redis哨兵模式的优势: redis哨兵建立在主从之上,有一个监控功能,监控主库是否异常,当主库异常之后会自动将某一个slave变为主库,省掉了人为配置redis哨兵模式原理: 哨兵模式建立在主从复制基础之上,会在每一个redis节点上打开一个sentinel监控,每个sentinel进程都有自己的端口号和IP,所有sentinel共享集群信息,集群中所有的sentinel都是可以通信的,当主库宕机后,主库上的sentinel就会向集群中的其他节点的sentinel发送信息说主库宕机了,需要在从库上选举master,这时每个节点上的sentinel会比较自己redis配置的ID号,比如slave1的ID号大,slave1就会选举为master作为主库,当故障的主库重新加入集群后,主库上的sentinel会向其他节点的sentinel询问谁是主库,这时slave1上的sentinel就会告诉主库上的sentinel说slave1是主库,重新加入集群的主库就会找slave1同步数据,如果重新加入的主库想再次成为主库,只需要执行提权命令就可以重新成为主库。主从复制的时候程序配置redis地址的时候都是写死主库的地址,每次主库宕机都需要手动修改应用有了哨兵模式后,在程序代码中配置不是redis地址,而是配置的所有哨兵的地址,形成一个地址池,即使集群中一个哨兵坏掉了,还有其他两个哨兵,每次需要找redis写入数据时,程序首先会找哨兵进程,哨兵之间信息共享,会立马告诉程序谁是主库,这时程序拿到哨兵告诉它的redis主库地址,就会去找主库存数据,因此即使主库坏了,也不需要修改程序代码哨兵的配置文件在启动哨兵服务后,尽量不要去修改,因为哨兵会自动增加配置哨兵集群个数建议是奇数,比如3/5/7配置了哨兵后,当主库挂掉,哨兵选举了新库,会自动把配置文件修改为最新主库的地址哨兵的选举规则: 首选判断slave-priority权重优先级,谁的高谁当选为master主库,如果都一致,那么久比较各个节点的id,谁的大谁当选哨兵模式架构和主从复制架构对比2.搭建redis哨兵集群2.1.环境准备配置哨兵集群步骤: 1.在所有节点搭建redis 2.配置主从复制,一主两从 3.在所有节点配置sentinel,启动sentinel后,配置文件会自动增加2.2.在所有机器上部署redis192.168.81.210配置1.创建redis部署路径 [root@redis-1 ~]# mkdir -p /data/redis_cluster/redis_6379/{conf,pid,logs,data} 2.下载redis [root@redis-1 ~]# mkdir /data/soft [root@redis-1 ~]# cd /data/soft [root@redis-1 /data/soft]# wget https://repo.huaweicloud.com/redis/redis-3.2.9.tar.gz 3.便于安装redis [root@redis-1 /data/soft]# tar xf redis-3.2.9.tar.gz -C /data/redis_cluster/ [root@redis-1 /data/soft]# cd /data/redis_cluster/ [root@redis-1 /data/redis_cluster]# ln -s redis-3.2.9/ redis [root@redis-1 /data/redis_cluster]# cd redis/src [root@redis-1 /data/redis_cluster/redis]# make && make install 4.准备配置文件 [root@redis-1 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf daemonize yes bind 192.168.81.210 127.0.0.1 port 6379 pidfile /data/redis_cluster/redis_6379/pid/redis_6379.pid logfile /data/redis_cluster/redis_6379/logs/redis_6379.log databases 16 dbfilename redis_6379.rdb dir /data/redis_cluster/redis_6379/data/ save 900 1 save 300 100 save 60 10000 5.启动redis [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 192.168.81.220配置由于redis-1已经部署好了一套redis,我们可以直接复制过来使用1.使用rsync将redis-1的redis目录拷贝过来你 [root@redis-1 ~]# rsync -avz /data root@192.168.81.220:/ 2.查看拷贝过来的目录文件 [root@redis-2 ~]# ls /data/redis_cluster/ redis redis-3.2.9 redis_6379 [root@redis-2 ~]# ls /data/redis_cluster/redis_6379/ conf data logs pid 3.编译安装redis,使系统能使用redis命令 直接执行make install即可,因为编译步骤在redis-1已经做了 [root@redis-2 ~]# cd /data/redis_cluster/redis-3.2.9/ [root@redis-2 /data/redis_cluster/redis-3.2.9]# make install 4.修改redis配置文件 [root@redis-2 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf bind 192.168.81.220 127.0.0.1 5.启动redis [root@redis-2 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 192.168.81.230配置由于redis-1已经部署好了一套redis,我们可以直接复制过来使用1.使用rsync将redis-1的redis目录拷贝过来你 [root@redis-1 ~]# rsync -avz /data root@192.168.81.230:/ 2.查看拷贝过来的目录文件 [root@redis-3 ~]# ls /data/redis_cluster/ redis redis-3.2.9 redis_6379 [root@redis-3 ~]# ls /data/redis_cluster/redis_6379/ conf data logs pid 3.编译安装redis,使系统能使用redis命令 直接执行make install即可,因为编译步骤在redis-1已经做了 [root@redis-3 ~]# cd /data/redis_cluster/redis-3.2.9/ [root@redis-3 /data/redis_cluster/redis-3.2.9]# make install 4.修改redis配置文件 [root@redis-3 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf bind 192.168.81.230 127.0.0.1 5.启动redis [root@redis-3 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf2.3.三台redis部署完成[root@redis-1 ~]# ps aux | grep redis root 21860 0.1 0.5 139020 9740 ? Ssl 09:36 0:16 redis-server 192.168.81.210:6379 root 25296 0.0 0.0 112724 984 pts/0 S+ 13:15 0:00 grep --color=auto redis [root@redis-1 ~]# ssh 192.168.81.220 "ps aux | grep redis" root 47658 0.1 0.5 141068 10780 ? Ssl 1月28 1:24 redis-server 192.168.81.220:6379 root 63254 0.0 0.0 113176 1588 ? Ss 13:15 0:00 bash -c ps aux | grep redis root 63271 0.0 0.0 112724 968 ? S 13:15 0:00 grep redis [root@redis-1 ~]# ssh 192.168.81.230 "ps aux | grep redis" root 56584 0.1 0.7 136972 7548 ? Ssl 13:13 0:00 redis-server 192.168.81.230:6379 root 56644 0.0 0.1 113176 1588 ? Ss 13:15 0:00 bash -c ps aux | grep redis root 56661 0.0 0.0 112724 968 ? S 13:15 0:00 grep redis 2.4.配置redis主从要在两台slave上同步主库配置1.配置主从复制 [root@redis-2 ~]# redis-cli 127.0.0.1:6379> SLAVEOF 192.168.81.210 6379 OK [root@redis-3 ~]# redis-cli 127.0.0.1:6379> SLAVEOF 192.168.81.220 6379 OK 2.主库新建一个key 127.0.0.1:6379> set name jiangxl OK 3.从库查看是否复制 [root@redis-2 ~]# redis-cli 127.0.0.1:6379> get name "jiangxl" [root@redis-3 ~]# redis-cli 127.0.0.1:6379> get name "jiangxl" 2.5.部署哨兵进程sentinel配置文件解释sentinel monitor mymaster 192.168.81.210 6379 2 //设置主节点信息,mymaster是主节点别名,就是随便起一个名字,然后填写主节点的ip地址,2表示当主节点挂掉后,有2个sentinel同意后才会选举新的master,一组哨兵集群,要把名称都写成一样的 sentinel down-after-milliseconds mymaster 3000 //主库宕机多少秒,从库在进行切换,因为有时因为网络波动,如果只要主库一宕机就切换主从,那么redis可能一直处于正在切换状态 sentinel parallel-syncs mymaster 1 //允许几个节点同时向主库同步数据 sentinel failover-timeout mymaster 18000 //故障转移超时时间,当从库同步主库的rdb文件,多长时间没有同步完就认为超时三台redis服务器都要按如下配置,已经将配置文件中的bind写成了系统变量,在配合cat写入到文件,因此直接执行如下命令即可1.创建哨兵服务配置路径 mkdir -p /data/redis_cluster/redis_26379/{conf,data,pid,logs} 2.写入哨兵配置文件 cat > /data/redis_cluster/redis_26379/conf/redis_26379.conf <<EOF bind $(ifconfig | awk 'NR==2{print $2}') port 26379 daemonize yes logfile /data/redis_cluster/redis_26379/logs/redis_26379.log dir /data/redis_cluster/redis_26379/data sentinel monitor mymaster 192.168.81.210 6379 2 sentinel down-after-milliseconds mymaster 3000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 18000 EOF 配置完记得查看下配置文件bind一列是否是各自主机的ip地址2.6.启动哨兵观察配置文件的变化三台机器都这么操作启动哨兵redis-sentinel /data/redis_cluster/redis_26379/conf/redis_26379.conf观察哨兵启动前后配置文件的变化启动前启动后每台哨兵主机都自动增加了一个myid的配置,这个就是当主库挂掉后,哨兵选举的依据,判断谁的myid大谁就当选为主库每台哨兵主机还自动增加了sentinel known-sentinel这个配置,这个配置每个哨兵会记录集群中其他节点的id号,这样就能够实现信息共享,即使应用在询问哨兵进程谁是主库,这时由于每个哨兵进程都有其他节点的信息,因此就能里面告诉应用谁是主库2.7.模拟主库故障验证应用是否可用配置完哨兵后,每个节点上都有集群的信息共享,当主库挂掉后,哨兵进程确认主库下线了,哨兵根据各自的id大小选举新的主库,接替主库的工作,保证应用程序不受影响,当主库修复好后,在通过提权的方式先同步目前主库的数据,在让自身成为主库1.关闭主库的redis服务,reids正常关闭,sentinel直接kill [root@redis-1 ~]# redis-cli shutdown [root@redis-1 ~]# pkill redis 4.查看配置文件看看谁的myid大 redis-2的myid比较大 [root@redis-1 ~]# grep 'known-sentinel' /data/redis_cluster/redis_26379/conf/redis_26379.conf sentinel known-sentinel mymaster 192.168.81.220 26379 df44bb3e9fdf8c635628b1ae724b2db7d3ef144c sentinel known-sentinel mymaster 192.168.81.230 26379 de282d14bb0a79df90603eb92243cd1f362dd46d 2.测试redis-2是否可用写入数据 可以写入数据,redis-2被选为主库 [root@redis-1 ~]# redis-cli -h 192.168.81.220 set gzzy_test guzhangzhuanyi OK [root@redis-1 ~]# redis-cli -h 192.168.81.220 config get slaveof 1) "slaveof" 2) "" 4.测试redis-3是否可用写入数据 写入数据失败,并且同步的是redis-2的数据,因此redis-2为主库 [root@redis-1 ~]# redis-cli -h 192.168.81.230 set kkkk111 vvv (error) READONLY You can't write against a read only slave. [root@redis-1 ~]# redis-cli -h 192.168.81.230 config get slaveof 1) "slaveof" 2) "192.168.81.220 6379" 主库挂掉后,其他两个节点选举出master后,配置文件也会填写为新master的地址2.8.主库挂掉其他节点配置文件的变化
0. 前言所有应用程序都需要处理输入和输出,文件是用于获取输入和保存输出的常用载体,文件可以是文本文档、图片、程序等等,我们就通过 10 道 Python 编程题来掌握解决常见文件处理问题的方法吧!1. 第 1 题:文件路径名的处理知识点描述:使用路径名来获取文件名,目录名,绝对路径。问题描述:有一文件路径如下:“/home/brainiac/Documents/csdn/hello_world.py”,请从以下选项中选出可以获取文件名 “hello_world.py” 的选项:A.import os path = '/home/brainiac/Documents/csdn/hello_world.py' file_name = os.path.dirname(path) print(file_name) 1234B.import os path = '/home/brainiac/Documents/csdn/hello_world.py' file_name = os.path.abspath(path) print(file_name) 1234C.import os path = '/home/brainiac/Documents/csdn/hello_world.py' file_name = os.path.basename(path) print(file_name) 1234D.import os path = '/home/brainiac/Documents/csdn/hello_world.py' file_name = os.path.splitext(path)[-1] print(file_name) 1234正确答案: C2. 第 2 题:检测文件是否存在知识点描述:检测指定文件或目录是否存在。问题描述:请从以下选项中选出可以检测 “/etc/passwd” 文件是否存在的选项:A.import os exist = os.path.exists('etc/passwd') print(exist) 123B.import os exist = os.path.isdir('etc/passwd') print(exist) 123C.import os exist = os.path.isdir('/etc/passwd') print(exist) 123D.import os exist = os.path.isfile('/etc/passwd') print(exist) 123正确答案: D3. 第 3 题:获取指定文件夹下的文件列表知识点描述:获取文件系统中指定目录下的所有文件列表。问题描述:获取 “/etc” 目录中所有 python 文件(以 “.py” 作为文件后缀)列表,请从以下选项中选出你认为正确的选项A.import ospath = "/usr/lib/python3/dist-packages"names = [name for name in os.listdir(path)]print(names)1234B.import ospath = "/usr/lib/python3/dist-packages"names = [name for name in os.listdir(path) if name.endswith('.py')]priC.import ospath = "/usr/lib/python3/dist-packages"names = [name for name in os.listdir(path) if os.path.isfile(name) anD.import ospath = "/usr/lib/python3/dist-packages"names = [name for name in os.listdir(path) if name.endswith('*.py')]pri正确答案: B4. 第 4 题:文本文件的读写知识点描述:读写使用不同编码方式的文本文件。问题描述:假设存在一文件 “text_1.txt”,如何向其中再添加两行新数据,请从以下选项中选出你认为正确的选项:A.new_line_1 = "New line 1"new_line_2 = "New line 2"with open('text_1.txt', 'rt') as f: f.write(new_line_1+'\n')B.new_line_1 = "New line 1"new_line_2 = "New line 2"with open('text_1.txt', 'at') as f: f.write(new_line_1) f.wriC.new_line_1 = "New line 1"new_line_2 = "New line 2"with open('text_1.txt', 'wt') as f: f.write(new_line_1+'\n') f.wD.new_line_1 = "New line 1"new_line_2 = "New line 2"with open('text_1.txt', 'at') as f: f.write(new_line_1+'\n')正确答案: D5. 第 5 题:将打印输出到文件中知识点描述:将 print() 函数的输出重定向到指定日志文件中。问题描述:将当前时间写入日志文件 “log.txt” 中,并记录函数执行结果,请从以下选项中选出你认为正确的答案:A.from datetime import datetimedef hello_world(num): return "Hello world {}!".format(num)for i in range(10): withB.from datetime import datetimedef hello_world(num): return "Hello world {}!".format(num)for i in range(10): withC.from datetime import datetimedef hello_world(num): return "Hello world {}!".format(num)for i in range(10): with opD.from datetime import datetimedef hello_world(num): return "Hello world {}!".format(num)for i in range(10): with正确答案: A6. 第 6 题:二进制文件的读写知识点描述:读写二进制文件,如图片、声音文件等。问题描述:已知存在二进制文件 “test.bin”,如何正确向此文件追加写入文本数据,请从以下选项中选出你认为正确的答案:A.with open('test.bin', 'at') as f: text = 'Hello World!\n' f.write(text)123B.with open('test.bin', 'wb') as f: text = 'Hello World!\n' f.write(text.encode('utf-8'))123C.with open('test.bin', 'ab') as f: text = 'Hello World!\n' f.write(text.encode('utf-8'))123D.with open('test.bin', 'ab') as f: text = 'Hello World!\n' f.write(text)123正确答案: C7. 第 7 题:压缩文件的读写知识点描述:读写 gzip 或 bz2 格式的压缩文件。问题描述:请从以下选项中选择能够将文本文件 “text.txt” 内容写入压缩文件 “compress.gz” 的程序,且要求压缩程度最佳:A.import gziptext = 'text.txt'with gzip.open('compress.gz', 'wt', compresslevel = 9) as f: f.write(text)1234B.import gziptext = 'text.txt'with gzip.open('compress.gz', 'wt', compresslevel = 0) as f: f.write(text)1234C.import gziptext = 'text.txt'with open(text, 'rt') as file: read_text = file.read() with gzip.open('compress.gz', 'D.import gziptext = 'text.txt'with open(text, 'rt') as file: read_text = file.read() with gzip.open('compress.gz',正确答案:C8. 第 8 题:以固定数据块大小读取文件知识点描述:以固定长度数据块长度迭代读取文件,而非逐行读取。问题描述:存在一文件 “test.bin”,编写程序每次读取数据块大小为 16B,直到文件末尾:A.from functools import partialRECORD_SIZE = 16with open('test.bin', 'rt') as f: records = iter(partial(f.read, RECORB.from functools import partialRECORD_SIZE = 16with open('test.bin', 'rb') as f: records = iter(partial(f.read, RECORC.from functools import partialRECORD_SIZE = 16 * 8with open('test.bin', 'rt') as f: records = iter(partial(f.read, RECORD_SIZE), b'') for r in records: print(r)123456D.from functools import partialRECORD_SIZE = 16with open('test.bin', 'rt') as f: records = iter(partial(f.read, RECO正确答案:B9. 第 9 题:增加或改变已打开文件的编码方式知识点描述:在不关闭已打开文件前提下改变文件的编码方式。问题描述:如何为一个以二进制模式打开的文件添加 “utf-8” 编码方式,请从以下选项中选出你认为正确的答案:A.import urllib.requestimport iowith urllib.request.urlopen('https://blog.csdn.net/LOVEmy134611') as u: f = io.TextIOB.import urllib.requestimport iowith urllib.request.urlopen('https://blog.csdn.net/LOVEmy134611') as u: f = io.TextIOWrC.import urllib.requestimport iowith urllib.request.urlopen('https://blog.csdn.net/LOVEmy134611') as u: f = io.TextIOWD.import urllib.requestimport iowith urllib.request.urlopen('https://blog.csdn.net/LOVEmy134611') as u: f = io.TextIOW正确答案:A10. 第 10 题:临时文件与文件夹的创建知识点描述:在程序执行时创建临时文件或目录,并在使用后自动销毁。问题描述:创建一个命名临时文件,向文件中写入 “Hello Python!” 后打印文件名,请从以下选项中选出你认为正确的答案:A.from tempfile import NamedTemporaryFilewith NamedTemporaryFile('text.txt', 'wt') as f: f.write('Hello Python!\n')B.from tempfile import TemporaryFilewith TemporaryFile('text.txt', 'wt') as f: f.write('Hello Python!\n') print(f.nC.from tempfile import NamedTemporaryFilewith NamedTemporaryFile('wt') as f: f.write('Hello Python!\n') print(f.nD.from tempfile import TemporaryFilewith TemporaryFile('wt') as f: f.write('Hello Python!\n') print(f.name)1234正确答案:C试题代码地址https://codechina.csdn.net/LOVEmy134611/python_problem
Redis主从复制集群及数据异常丢失恢复思路1.redis主从复制原理1.从库向主库发送同步请求2.主库接收从库发送的同步请求3.主库开始使用bgsave生成rdb文件4.主库rdb文件生成后保存到磁盘,让将rdb文件发送给从库5.从库接收主库发送的rdb文件,将rdb文件载入内存从库在同步主库的时候,会把从库上的所有数据全部清空,因此在做redis主从的时候尽量选择没有任何数据的redis架构图环境准备2.部署两台redis2.1.192.168.81.210配置1.创建redis部署路径 [root@redis-1 ~]# mkdir -p /data/redis_cluster/redis_6379/{conf,pid,logs,data} [root@redis-1 ~]# tree /data/redis_cluster/ /data/redis_cluster/ └── redis_6379 ├── conf ├── logs ├── pid └── data 2.下载redis [root@redis-1 ~]# mkdir /data/soft [root@redis-1 ~]# cd /data/soft [root@redis-1 /data/soft]# wget https://repo.huaweicloud.com/redis/redis-3.2.9.tar.gz 3.编译安装redis [root@redis-1 /data/soft]# tar xf redis-3.2.9.tar.gz -C /data/redis_cluster/ [root@redis-1 /data/soft]# cd /data/redis_cluster/ [root@redis-1 /data/redis_cluster]# ln -s redis-3.2.9/ redis [root@redis-1 /data/redis_cluster]# cd redis/src [root@redis-1 /data/redis_cluster/redis]# make && make install 4.准备配置文件 [root@redis-1 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf daemonize yes bind 192.168.81.210 127.0.0.1 port 6379 pidfile /data/redis_cluster/redis_6379/pid/redis_6379.pid logfile /data/redis_cluster/redis_6379/logs/redis_6379.log databases 16 dbfilename redis_6379.rdb dir /data/redis_cluster/redis_6379/data/ save 900 1 save 300 100 save 60 10000 appendonly yes appendfilename "appendonly.aof" appendfsync always appendfsync everysec appendfsync no no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes 5.启动redis [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 2.2.192.168.81.220配置由于redis-1已经部署好了一套redis,我们可以直接复制过来使用1.使用rsync将redis-1的redis目录拷贝过来你 [root@redis-1 ~]# rsync -avz /data root@192.168.81.220:/ 2.查看拷贝过来的目录文件 [root@redis-2 ~]# ls /data/redis_cluster/ redis redis-3.2.9 redis_6379 [root@redis-2 ~]# ls /data/redis_cluster/redis_6379/ conf data logs pid 3.编译安装redis,使系统能使用redis命令 直接执行make install即可,因为编译步骤在redis-1已经做了 [root@redis-2 ~]# cd /data/redis_cluster/redis-3.2.9/ [root@redis-2 /data/redis_cluster/redis-3.2.9]# make install 4.修改redis配置文件 [root@redis-2 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf bind 192.168.81.220 127.0.0.1 5.启动redis [root@redis-2 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 3.redis主从复制配置3.1.在主库批量创建key[root@redis-1 ~]# for i in {0..2000}; do redis-cli set k_${i} v_${i}; echo "k_${i} is ok"; done 127.0.0.1:6379> DBSIZE (integer) 20013.2.配置从库连接主库两种配置方式实现Redis主从复制:配置文件实现命令行执行命令实现3.2.1.在配置文件中设置1.修改配置文件 [root@redis-2 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf slaveof 192.168.81.210 6379 #指定主库的ip和端口 2.重启redis [root@redis-2 ~]# redis-cli shutdown [root@redis-2 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf3.2.2.在命令行热更新配置[root@redis-2 ~]# redis-cli 127.0.0.1:6379> SLAVEOF 192.168.81.210 6379 OK3.3.查看从库是否同步主库数据1.在从库上执行keys查看数据是否相同 [root@redis-2 ~]# redis-cli 127.0.0.1:6379> keys * 2.在主库上新建一个key,查看从库是否存在 主: 127.0.0.1:6379> set name jiangxl OK 从: 127.0.0.1:6379> get name "jiangxl" 3.在主库删除k_114,查看从库是否也删除 主: 127.0.0.1:6379> del k_114 (integer) 1 从: 127.0.0.1:6379> get k_114 (nil) 3.4.在查看日志中主从同步的原理主库从库有记录复制的详细日志4.redis主从复制危险操作4.1.使用热更新配置误操作redis主从复制如果使用热更新配置,有时候会因为选错主机把从库误认为主库,结果在主库上执行了slaveof,这样就会导致主库上的数据被清空,因为从库上是没有数据的从库在同步主库的时候会把原本自己的数据全部清空误操作过程从库数据为0 127.0.0.1:6379> DBSIZE (integer) 0 主库数据为2001 127.0.0.1:6379> DBSIZE (integer) 2001 在主库上操作同步本该从库的数据 127.0.0.1:6379> SLAVEOF 192.168.81.220 6379 OK 再次查看数据,数据已经清空 127.0.0.1:6379> DBSIZE (integer) 0 4.2.避免热更新配置误操作1.不使用热更新,直接在配置文件里配置主从2.在执行slaveof的时候先执行bgsave,把数据手动备份一下,然后在数据目录,将rdb文件复制成另一个文件,做备份,这样即使出现问题也能即使恢复bgsave之后不用重启,直接备份rdb文件即可1.手动持久化 127.0.0.1:6379> BGSAVE Background saving started 2.备份rdb文件 [root@redis-1 ~]# cd /data/redis_cluster/redis_6379/ [root@redis-1 /data/redis_cluster/redis_6379]# cd data/ [root@redis-1 /data/redis_cluster/redis_6379/data]# cp redis_6379.rdb redis_6379.rdb.bak 3.再次同步错误的主库,造成数据丢失 127.0.0.1:6379> SLAVEOF 192.168.81.220 6379 OK 127.0.0.1:6379> keys * (empty list or set) 4.还原备份的rdb文件,先停掉redis,在还原 [root@redis-1 ~]# redis-cli shutdown [root@redis-1 /data/redis_cluster/redis_6379/data]# cp redis_6379.rdb.bak redis_6379.rdb 5.查看还原后的数据 [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 127.0.0.1:6379> DBSIZE (integer) 2001 5.模拟redis主从复制错误数据恢复模拟redis主从同步误操作数据恢复大致思路: 1.清空两台redis的数据 2.在主库上创建一些数据,然后使用bgsave命令,将数据保存到磁盘,再将磁盘的rdb文件备份 3.再将从库的数据同步过来,模拟主库数据丢失 4.从rdb备份文件还原数据库这个实验的主要的目的是操作redis备份还原5.1.清空数据两台redis都需要操作先关闭再删除数据再启动[root@redis-1 ~]# redis-cli shutdown [root@redis-1 ~]# rm -rf /data/redis_cluster/redis_6379/data/* [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf [root@redis-1 ~]# redis-cli 127.0.0.1:6379> keys * (empty list or set)5.2.在主库批量创建数据并备份1.批量创建数据 [root@redis-1 ~]# for i in {0..2000}; do redis-cli set k_${i} v_${i}; echo "k_${i} is ok"; done 127.0.0.1:6379> DBSIZE (integer) 2001 2.将近数据写入到 127.0.0.1:6379> BGSAVE Background saving started 3.备份rdb文件 [root@redis-1 /data/redis_cluster/redis_6379/data]# cp redis_6379.rdb redis_6379.rdb.bak [root@redis-1 /data/redis_cluster/redis_6379/data]# ll 总用量 56 -rw-r--r--. 1 root root 27877 1月 28 21:00 redis_6379.rdb -rw-r--r--. 1 root root 27877 1月 28 21:01 redis_6379.rdb.bak5.3.同步从库的数据造成数据丢失这时从库的数据应该是空的[root@redis-2 ~]# redis-cli 127.0.0.1:6379> keys * (empty list or set)主库同步从库的数据,同步完主库数据丢失,这样就模拟了主库数据丢失的情况127.0.0.1:6379> SLAVEOF 192.168.81.220 6379 OK 127.0.0.1:6379> keys * (empty list or set)5.4.恢复主库的数据先关掉redis,还原,最后在开启redis1.关掉redis [root@redis-1 ~]# redis-cli shutdown 2.还原rdb备份文件 [root@redis-1 /data/redis_cluster/redis_6379/data]# cp redis_6379.rdb.bak redis_6379.rdb cp:是否覆盖"redis_6379.rdb"? y 3.启动redis [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 4.查看数据是否还原 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> keys *6.模拟线上环境主库宕机故障恢复思路: 1.首先保证主从同步已经配置完成,主库从库都有数据 2.关闭redis主库,模拟redis主库宕机 3.查看redis从库是否还存在数据,是否可读可写(不能写,只能读) 4.关闭从库的slaveof,停止主从同步,将应用连接redis的地址改成从库,保证业务不断 5.修复主库,主库上线后,与从库建立主从复制关系,原来的从库(redis-2)就变成了主库,现在的主库变成了从库(redis-1)这时 关掉应用程序,停止数据写入 6.然后将现在主库(redis-2)的数据同步到现在的从库(redis-1) 7.关闭现在从库(redis-1)的slaveof,停止主从复制,然后将现在主库(redis-2)配置salveof,同步原来的主库(redis-1) 8.数据同步完,原来的主库从库就恢复完毕了简单明了的一句话:主库因为某种原因宕机无法提供服务了,直接将从库切换成主库提供服务,然后后原来的主库恢复后同步当前主库的数据,然后停掉所有线上运行的程序,将现在的主库去同步恢复后的主库,重新生成主从关系。6.1.配置主从模拟线上环境配置主从前先保证主库上面有数据1.登陆主库redis-1查看是否有数据 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> DBSIZE (integer) 2001 2.登陆从库redis-2查看是否有数据 [root@redis-2 ~]# redis-cli 127.0.0.1:6379> keys * (empty list or set) 3.从库没有数据的情况下在从库上配置主从,同步主库的数据 127.0.0.1:6379> SLAVEOF 192.168.81.210 6379 OK 数据已经同步 127.0.0.1:6379> DBSIZE (integer) 20016.2.模拟主库宕机验证从库是否可读写1.直接关掉主库,造成宕机 [root@redis-1 ~]# redis-cli shutdown 2.查看从库是否可读写 只能读,不能写 [root@redis-2 ~]# redis-cli get k_1 "v_1" [root@redis-2 ~]# redis-cli set k999 k_1 (error) READONLY You can't write against a read only slave. 主库一宕机,从库就会一直输出日志提示连接不上主库6.3.关闭从库的主从复制保证业务的不间断现在主库是不可用的,从库也只能读不能写,但是数据只有这么一份了,我们只能关闭从库上的主从复制,让从库变成主库,再配置业务的redis地址,首先要保证业务的不中断1.关闭从库redis-2的主从同步配置,使其成为主库 [root@redis-2 ~]# redis-cli slaveof no one OK 2.将应用的redis地址修改为从库,只要从库关掉了主从配置,他自己就是一个可读可写的库了,库里有故障前的所有数据,可以先保证业务的不间断6.4.修复故障的主库同步原来从库的数据修复完主库,已经是有数据的了,为什么还要同步从库的数据呢,因为在主库挂掉的那一瞬间,从库去掉了主从配置,自己已经成了主库,并且也提供了一段时间的数据写入,这时从库的数据时最完整的同步现在主库(原来的从库)的数据时,先要将应用关掉,不要在往里写数据了在主库(原来的从库上)写入几个新的数据,模拟产生的新数据[root@redis-2 ~]# redis-cli 127.0.0.1:6379> set zuixinshujv vvvvv OK 在重新上线的主库上配置主从同步,使自己变成从库,同步主库的(原来的从库)数据同步之后,现在从库(重新修复的主库已经有最新数据了)同步之前先将应用停掉,不要再往redis中写数据 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> SLAVEOF 192.168.81.220 6379 OK 127.0.0.1:6379> get zuixinshujv "vvvvv" 6.5.从库重新上线为主库这里的从库重新上线指的就是原来故障的主库,现在已经同步到最新数据了,因此要上线成为主库,之前选他作为主库就是因为他的性能比从库各方面都要高,避免将来因为性能再次发生故障,因此要切换1.关闭从库(原来的主库)的主从配置 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> SLAVEOF no one OK 2.在主库(原来的从库)配置主从复制 [root@redis-2 ~]# redis-cli 127.0.0.1:6379> SLAVEOF 192.168.81.210 6379 OK6.6.将应用的redis地址再次修改为主库的地址目前主库已经恢复了,并且主从之前重新建立了主从同步关系,现在就可以把应用的redis地址修改为主库,启动应用就可以了
JAVA程序对应不同的部署环境针对配置文件如何管理可以通过以下四种方式来管理不同环境使用不同的配置文件kubernetes configmap资源可以根据线上、预发布、测试环境编写不同的configmap资源,然后将其挂载到对应的deployment资源上docker 容器启动脚本entrypoint.sh根据环境的不同在entrypoint.sh声明环境变量,运行特定的配置文件java启动命令控制java程序可以同时存在多个程序配置文件,可以在配置文件中声明各自的变量,然后使用java --spring.profiles.active=xxx xxx.jar的方式来指定不同环境的配置文件使用开源的统一配置中心程序,比如市面上主流的Apollo以及Disconf,这两款程序都有自己的图形化管理系统,配置可视化
tomcat升级版本为8.5.68后.启动报错: java.lang.IllegalArgumentException: AJP连接器配置secretRequired=“true” 属性secret确实为空1.tomcat启动报错内容如下。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.4.0.RELEASE) 2021-09-29 15:22:58 [localhost-startStop-1] INFO org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor -No TaskScheduler/ScheduledExecutorService bean found for scheduled processing 29-Sep-2021 15:22:58.514 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR web应用程序存档文件[/data/tomcat/xbtp/webapps/ROOT.war]的部署已在[49,933]ms内完成 29-Sep-2021 15:22:58.522 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-9280"] 29-Sep-2021 15:22:58.542 严重 [main] org.apache.catalina.core.StandardService.startInternal Failed to start connector [Connector[AJP/1.3-9209]] org.apache.catalina.LifecycleException: 协议处理器启动失败 at org.apache.catalina.connector.Connector.startInternal(Connector.java:1102) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:444) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:770) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.startup.Catalina.start(Catalina.java:688) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476) Caused by: java.lang.IllegalArgumentException: AJP连接器配置secretRequired="true",但是属性secret确实空或者空字符串,这样的组合是无效的。 at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:274) at org.apache.catalina.connector.Connector.startInternal(Connector.java:1099) ... 12 more 2.解决方法1. 在tomcat的配置文件,server.xml中找到这一行 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> 2. 添加: secretRequired="" ,即可 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" secretRequired=""/>
Redis key的生命周期故障案例1.设置key的生命周期查看key生命周期语法格式:ttl key设置key的生命周期:expire key 时间,单位为秒key的生命周期常用于优惠券这种活动,仅限于一天内使用,超过一天后优惠券自动消失当key处于生命周期进行时的时候,如果再创建一模一样的key,会覆盖处于生命周期的key,这时,这个key的生命周期将会变成永不过期redis key的生命周期到期后会自动把key删除ttl命令查出来的key生命周期,如果返回值为-1则表示永不过期,返回值为-2则表示键过期,不存在1.查看k2的生命周期 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> ttl k2 (integer) -1 2.设置k2的声明周期为100秒 127.0.0.1:6379> EXPIRE k2 100 (integer) 1 3.观察k2的声明周期值 127.0.0.1:6379> ttl k2 (integer) 86 127.0.0.1:6379> ttl k2 (integer) 85 127.0.0.1:6379> ttl k2 (integer) 84 127.0.0.1:6379> ttl k2 (integer) 83 127.0.0.1:6379> ttl k2 (integer) 82 127.0.0.1:6379> ttl k2 (integer) 72 127.0.0.1:6379> ttl k2 (integer) 71 127.0.0.1:6379> ttl k2 (integer) 66 127.0.0.1:6379> ttl k2 (integer) -22.key生命周期故障案例描述:双十一优惠,某电商平台的开发人员操作了创建了一个已经存在生命周期为一天的优惠券key,这时就会把正在进行生命周期消耗的key直接覆盖,从而成为默认的永不过期,当生命周期时长一过,发现优惠券还能使用,造成的损失不计其数,这就是由于新的key把就 的key覆盖了,生命周期也随着变成了永不过期,只要key的生命周期为不过期,那么这个key就不会删除只有key生命周期到期了,key删除了,第二天优惠券就会变成无法使用模拟破坏key的生命周期1.创建优惠券key 127.0.0.1:6379> ttl k2 (integer) -2 2.查看key的生命周期 127.0.0.1:6379> ttl youhuiquan (integer) -1 #永不过期,默认创建的key是永不过期 3.设置key的生命周期为150s 127.0.0.1:6379> EXPIRE youhuiquan 150 (integer) 1 4.观察生命周期的缩减 正在一点点缩减 127.0.0.1:6379> ttl youhuiquan (integer) 148 127.0.0.1:6379> ttl youhuiquan (integer) 147 127.0.0.1:6379> ttl youhuiquan (integer) 147 127.0.0.1:6379> ttl youhuiquan (integer) 144 127.0.0.1:6379> ttl youhuiquan (integer) 140 5.这时开发人员突然创建了一模一样的key,导致了存在生命周期的key被覆盖,从而变成了永不过期的key 127.0.0.1:6379> set youhuiquan 100 OK 127.0.0.1:6379> ttl youhuiquan (integer) -1 避免key生命周期故障的方法1.跟开发人员提前明确哪些key存在生命周期,将key的生命周期进行监控,通过zabbix的自定义监控项,监控redis-cli ttl key输出的结果,只要是包含-1就告警,这个key已经是永不过期2.规范操作,避免背锅3.将key的生命周期设置为永不过期persist命令可以将一个快要过期的key设置为永不过期语法格式:persist key1.设置k3位100秒生命周期 127.0.0.1:6379> EXPIRE k3 100 (integer) 1 2.查看k3的生命周期缩减 127.0.0.1:6379> ttl k3 (integer) 96 127.0.0.1:6379> ttl k3 (integer) 91 127.0.0.1:6379> ttl k3 (integer) 82 127.0.0.1:6379> ttl k3 (integer) 77 4.设置k3永不过期 127.0.0.1:6379> PERSIST k3 (integer) 1 5.查看k3的生命周期 127.0.0.1:6379> ttl k3 (integer) -1
redis字符串操作1.redis字符串类型string 字符串类型,常用于普通文本list 列表类型,常用于一个仓库,取走一个数据就删除hash 哈希类型,常用于将mysql数据导入redisset 集合类型,用于不同集合进行比对2.redis常用指令keys * //列出所有key,生产环境不要使用,很有可能一使用keys就会把服务器内存占满,从而导致redis挂机,因为生产环境有长千上万个keytype key //查看key是什么类型del key //删除一个keyflushdb //清除缓存3.redis字符串类型操作3.1.字符串类型常用指令3.2.创建一个key并查看语法:set key名 value值既可以在交互式创建也可以在命令行创建1.在交互式创建一个key [root@redis-1 ~]# redis-cli 127.0.0.1:6379> set k1 v1 OK 2.在命令行创建一个key [root@redis-1 ~]# redis-cli set k2 v2 OK 3.在交互式查看key内容 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> get k1 "v1" 4.在命令行查看key内容 [root@redis-1 ~]# redis-cli get k2 "v2"3.3.从文件中读取value并创建keyredis支持value的内容为中文,准备一个中文的文件,创建key的时候读取文件的值中文的文件存储到redis之后是,只是显示是乱码,实际上还是中文,可以导出到文件查看中文,也可以加–raw解决乱码显示问题1.准备一个中文的文件 [root@redis-1 ~]# cat > test.txt <<EOF > 当你能念书时,你念书就是;当你能做事时,你做事就是;当你能恋爱时,你再去恋爱;当你能结婚时,你再去结婚。环境不许可时,强求不来;时机来临时,放弃不得。这便是一个人应有的生活哲学了。 > EOF 2.创建一个key从文件中读取value [root@redis-1 ~]# redis-cli set test `cat test.txt` OK 3.查看key的内容,会发现是乱码 [root@redis-1 ~]# redis-cli get test "\xe5\xbd\x93\xe4\xbd\xa0\xe8\x83\xbd\xe5\xbf\xb5\xe4\xb9\xa6\xe6\x97\xb6\xef\xbc\x8c\xe4\xbd\xa0\xe5\xbf\xb5\xe4\xb9\xa6\xe5\xb0\xb1\xe6\x98\xaf\xef\xbc\x9b\xe5\xbd\x93\xe4\xbd\xa0\xe8\x83\xbd\xe5\x81\x9a\xe4\xba\x8b\xe6\x97\xb6\xef\xbc\x8c\xe4\xbd\xa0\xe5\x81\x9a\xe4\xba\x8b\xe5\xb0\xb1\xe6\x98\xaf\xef\xbc\x9b\xe5\xbd\x93\xe4\xbd\xa0\xe8\x83\xbd\xe6\x81\x8b\xe7\x88\xb1\xe6\x97\xb6\xef\xbc\x8c\xe4\xbd\xa0\xe5\x86\x8d\xe5\x8e\xbb\xe6\x81\x8b\xe7\x88\xb1\xef\xbc\x9b\xe5\xbd\x93\xe4\xbd\xa0\xe8\x83\xbd\xe7\xbb\x93\xe5\xa9\x9a\xe6\x97\xb6\xef\xbc\x8c\xe4\xbd\xa0\xe5\x86\x8d\xe5\x8e\xbb\xe7\xbb\x93\xe5\xa9\x9a\xe3\x80\x82\xe7\x8e\xaf\xe5\xa2\x83\xe4\xb8\x8d\xe8\xae\xb8\xe5\x8f\xaf\xe6\x97\xb6\xef\xbc\x8c\xe5\xbc\xba\xe6\xb1\x82\xe4\xb8\x8d\xe6\x9d\xa5\xef\xbc\x9b\xe6\x97\xb6\xe6\x9c\xba\xe6\x9d\xa5\xe4\xb8\xb4\xe6\x97\xb6\xef\xbc\x8c\xe6\x94\xbe\xe5\xbc\x83\xe4\xb8\x8d\xe5\xbe\x97\xe3\x80\x82\xe8\xbf\x99\xe4\xbe\xbf\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe4\xba\xba\xe5\xba\x94\xe6\x9c\x89\xe7\x9a\x84\xe7\x94\x9f\xe6\xb4\xbb\xe5\x93\xb2\xe5\xad\xa6\xe4\xba\x86\xe3\x80\x82" 4.将key导出到文件时会发现是中文输出 [root@redis-1 ~]# cat test2.txt 当你能念书时,你念书就是;当你能做事时,你做事就是;当你能恋爱时,你再去恋爱;当你能结婚时,你再去结婚。环境不许可时,强求不来;时机来临时,放弃不得。这便是一个人应有的生活哲学了。 5.解决redis显示中文乱码 [root@redis-1 ~]# redis-cli --raw get test 当你能念书时,你念书就是;当你能做事时,你做事就是;当你能恋爱时,你再去恋爱;当你能结婚时,你再去结婚。环境不许可时,强求不来;时机来临时,放弃不得。这便是一个人应有的生活哲学了。3.4.对整数的value增值redis支持对一些整数的value的值增加和减少,前提是value值必须为整数整数增值使使用INCR命令,INCR每次加1,INCRBY可以根据自己的需求进行增加1.创建一个整数的key,将100增加到103 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> set num1 100 OK 127.0.0.1:6379> INCR num1 (integer) 101 127.0.0.1:6379> INCR num1 (integer) 102 127.0.0.1:6379> INCR num1 (integer) 103 127.0.0.1:6379> get num1 "103" 2.使用INCRBY自定义增加值,将103加到113 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> get num1 "103 127.0.0.1:6379> INCRBY num1 10 (integer) 113 127.0.0.1:6379> get num1 "113" 3.5.对整数的Value进行减值DECR每次减1,DECRER可以自定义每次减的值1.使用DECR每次减1 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> get num1 "113" 127.0.0.1:6379> DECR num1 (integer) 112 127.0.0.1:6379> DECR num1 (integer) 111 2.使用DECR每次减10 [root@redis-1 ~]# redis-cli 127.0.0.1:6379> get num1 "111" 127.0.0.1:6379> DECRBY num1 11 (integer) 100 127.0.0.1:6379> get num1 "100"3.6.查看key类型127.0.0.1:6379> type k1 //类型为字符串 string 127.0.0.1:6379> type num1 //即使值为整数也属于string,因为是由set创建的key string 命令行查看 [root@redis-1 ~]# redis-cli type k1 string 3.7.使用mset创建多个key语法格式:mset key1 value2 key2 value2127.0.0.1:6379> MSET k3 v3 k4 v4 k5 v5 k6 v6 OK 127.0.0.1:6379> keys * 1) "test" 2) "k2" 3) "k4" 4) "num1" 5) "k1" 6) "num" 7) "k5" 8) "k3" 9) "k6" 在命令行创建 [root@redis-1 ~]# redis-cli MSET k3 v3 k4 v4 k5 v5 k6 v6 OK 3.8.使用mget查看多个key的值语法格式:mget key1 key2 key3127.0.0.1:6379> MGET k1 k2 k3 k4 k5 k6 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "v5" 6) "v6" 在命令行查看 [root@redis-1 ~]# redis-cli MGET k1 k2 k3 k4 k5 k6 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "v5" 6) "v6"3.9.查看一个key是否存在语法格式 exists key返回结果为1表示存在,返回结果为0表示不存在[root@redis-1 ~]# redis-cli 127.0.0.1:6379> EXISTS k10 (integer) 0 127.0.0.1:6379> EXISTS k6 (integer) 1 命令行创建 [root@redis-1 ~]# redis-cli exists k6 (integer) 1 3.10.删除一个key语法格式:del key返回结果为1表示删除成功,返回结果为0表示不存在[root@redis-1 ~]# redis-cli 127.0.0.1:6379> del k6 (integer) 1 127.0.0.1:6379> del k6 (integer) 0 命令行 [root@redis-1 ~]# redis-cli del k6 (integer) 0
redis基本概念及部署redis1.redis介绍rediis是一种基于键值对的NoSQL数据库,与很多键值对数据库不同,redis中的值可以有string、hash、list、set、zset、geo等多种数据结构和算法组成。redis会将所有的数据都放在内存中,因此redis的读写性能非常快,redis还可以将内存中的数据利用快照和日志的形式保存在硬盘上,redis还提供了键过期,发布订阅,事务,流水线等附加功能2.redis的特点速度快redis所有的数据都存放在内存中redis使用c语言实现redis使用单线程架构基于键值对的数据结构服务器所谓键值对就是key/value5种数据结构:字符串、哈希、列表、集合、有序结合丰富的功能提供了键过期功能,可以实现缓存提供了发布订阅功能,可以实现消息系统提供了pipeline功能,客户端可以将一批命令一次性传给redis,减少了网络开销稳定简单源码很少,3.0版本以后,只有5万行代码使用单线程模型,使得redis服务端处理模型变得简单不依赖操作系统中的类库客户端支持的语言多java、php、python、c、c++、nodejs持久化RDB和AOF集群主从复制哨兵模式集群3.redis应用场景缓存(键过期时间)缓存可以通过键过期时间进行设置缓存session会话每个网站都有登陆过期时间,例如24小时不登录就会退出缓存用户信息,找不到数据再去mysql查,查到之后再次写到redis排行榜(列表和有序集合)可以通过redis列表和有序集合做出排行榜功能热度排名排行榜发布时间排行榜计数器应用帖子浏览数视频播放次数商品浏览数社交网络踩/赞、粉丝、共同好友、喜好、推送、打标签消息队列系统可以作为一个仓库使用,当数据全部取走,仓库删除可以配合elk实现日系收集4.redis的部署、配置、启动、关闭4.1.部署redis1.创建redis部署路径 [root@redis-1 ~]# mkdir -p /data/redis_cluster/redis_6379/{conf,pid,logs,data} [root@redis-1 ~]# tree /data/redis_cluster/ /data/redis_cluster/ └── redis_6379 ├── conf ├── logs ├── pid └── data 2.下载redis [root@redis-1 ~]# mkdir /data/soft [root@redis-1 ~]# cd /data/soft [root@redis-1 /data/soft]# wget https://repo.huaweicloud.com/redis/redis-3.2.9.tar.gz 3.便于安装redis [root@redis-1 /data/soft]# tar xf redis-3.2.9.tar.gz -C /data/redis_cluster/ [root@redis-1 /data/soft]# cd /data/redis_cluster/ [root@redis-1 /data/redis_cluster]# ln -s redis-3.2.9/ redis [root@redis-1 /data/redis_cluster]# cd redis/src [root@redis-1 /data/redis_cluster/redis]# make && make install 4.2.redis可执行文件make install完redis的可执行命令都存放在了/usr/local/bin下[root@redis-1 /data/redis_cluster/redis]# ll /usr/local/bin/redis-*-rwxr-xr-x. 1 root root 2433000 1月 27 13:32 /usr/local/bin/redis-benchmark-rwxr-xr-x. 1 root root 25128 1月 27 13:32 /usr/local/bin/redis-check-aof-rwxr-xr-x. 1 root root 5181912 1月 27 13:32 /usr/local/bin/redis-check-rdb-rwxr-xr-x. 1 root root 2585960 1月 27 13:32 /usr/local/bin/redis-clilrwxrwxrwx. 1 root root 12 1月 27 13:32 /usr/local/bin/redis-sentinel -> redis-server-rwxr-xr-x. 1 root root 5181912 1月 27 13:32 /usr/local/bin/redis-server4.3.使用redis官方脚本生成redis配置文件[root@redis-1 ~]# cd /data/redis_cluster/redis/utils/ [root@redis-1 /data/redis_cluster/redis/utils]# sh install_server.sh Welcome to the redis service installer This script will help you easily set up a running redis server Please select the redis port for this instance: [6379] Selecting default: 6379 Please select the redis config file name [/etc/redis/6379.conf] Selected default - /etc/redis/6379.conf Please select the redis log file name [/var/log/redis_6379.log] Selected default - /var/log/redis_6379.log Please select the data directory for this instance [/var/lib/redis/6379] Selected default - /var/lib/redis/6379 Please select the redis executable path [/usr/local/bin/redis-server] Selected config: Port : 6379 Config file : /etc/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /var/lib/redis/6379 Executable : /usr/local/bin/redis-server Cli Executable : /usr/local/bin/redis-cli Is this ok? Then press ENTER to go on or Ctrl-C to abort. Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service... Successfully added to chkconfig! Successfully added to runlevels 345! Starting Redis server... 执行完在/etc/redis/目录下面即可看到配置文件 [root@redis-1 /data/redis_cluster/redis/utils]# ls /etc/redis/ 6379.conf4.4.配置redis并启动一般编译安装完之后,redis目录就没什么用了,在生产环境中,都是新建一个redis目录,里面存放配置文件,直接启动就行,因为一台机器上会部署很多个redis1.配置redis [root@redis-1 ~]# vim /data/redis_cluster/redis_6379/conf/redis_6379.conf #以守护进程模式启动 daemonize yes #绑定主机地址 bind 192.168.81.210 127.0.0.1 #监听端 port 6379 #pid和log文件所在路径 pidfile /data/redis_cluster/redis_6379/pid/redis_6379.pid logfile /data/redis_cluster/redis_6379/logs/redis_6379.log #设置数据库的数量,默认为0 databases 16 #指定本地持久化文件的文件名,默认dump.rdb dbfilename redis_6379.rdb #本地数据库的目录,持久化文件路径 dir /data/redis_cluster/redis_6379/data 2.启动redis [root@redis-1 ~]# redis-server /data/redis_cluster/redis_6379/conf/redis_6379.conf 3.查看进程和端口号 [root@redis-1 ~]# ps aux | grep redis root 16597 0.1 0.4 136972 7528 ? Ssl 13:57 0:00 /usr/local/bin/redis-server 127.0.0.1:6379 [root@redis-1 ~]# netstat -lnpt | grep redis tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 16597/redis-server 4.5.redis关闭方式不管是关系型数据库还是缓存数据库,都不能直接kill,会导致数据文件丢失关闭redis的方式需要在redis-cli交互模式输入shutdown即可关闭或者使用redis-cli shutdown[root@redis-1 ~]# redis-cli 127.0.0.1:6379> SHUTDOWN not connected> exit [root@redis-1 ~]# ps aux | grep redis 第二种关闭redis的方法 [root@redis-1 ~]# redis-cli shutdown
使用蓝鲸自愈平台完成java项目程序的自愈机制1.蓝鲸自愈平台官方文档故障自愈是行业领先的"故障自动化处理"解决方案,提升企业的服务可用性和降低故障处理的人力投入,实现故障自愈从"人工处理"到"无人值守"的变革!自愈平台可以根据连接配置好的监控平台,当收到我们指定要自愈的监控告警时,首先筛选出告警信息的ip地址,再匹配该服务器所在的集群节点,确认服务器信息,然后将服务器地址传到对应的作业平台的某个作业里,通过作业的具体恢复脚本,实现项目的故障资源机制。实现步骤:首先配置一个告警源准备故障资源的作业平台脚本然后配置一个自愈套餐,调用作业平台最后接入自愈2.配置告警源在菜单 [接入自愈] -> [管理告警源] 中,点击 启用 Zabbix。跳转到接入流程页面登陆zabbix服务器操作以下步骤cd /usr/lib/zabbix/alertscripts wget 'http://${PaaS_Host}/o/bk_fta_solutions/0/alarm_source/scripts/zabbix_fta_alarm.py?fta_application_id=66fdfe50-3075-49bf-8101-d97386030c9b&fta_application_secret=EfgBbXD25N6870j9nkgf3ns8eOEsH2Sk' -O /usr/lib/zabbix/alertscripts/zabbix_fta_alarm.py --no-check-certificate chmod +x zabbix_fta_alarm.py ./zabbix_fta_alarm.py --init http://${Zabbix_Host}/api_jsonrpc.php Admin zabbix该脚本会创建一个名为FTA_Event_Handler的 报警媒介,名为 FTA_Act 的 Action,名为 FTA_Mgr 的用户。3.新建一个作业平台点击作业执行—>新建作业—>填写作业名称—>填写脚本内容脚本内容如下#!/bin/bash anynowtime="date +'%Y-%m-%d %H:%M:%S'" NOW="echo [\`$anynowtime\`][PID:$$]" ##### 可在脚本开始运行时调用,打印当时的时间戳及PID。 function job_start { echo "`eval $NOW` job_start" } ##### 可在脚本执行成功的逻辑分支处调用,打印当时的时间戳及PID。 function job_success { MSG="$*" echo "`eval $NOW` job_success:[$MSG]" exit 0 } ##### 可在脚本执行失败的逻辑分支处调用,打印当时的时间戳及PID。 function job_fail { MSG="$*" echo "`eval $NOW` job_fail:[$MSG]" exit 1 } job_start ###### 可在此处开始编写您的脚本逻辑代码 ###### 作业平台中执行脚本成功和失败的标准只取决于脚本最后一条执行语句的返回值 ###### 如果返回值为0,则认为此脚本执行成功,如果非0,则认为脚本执行失败 #输出告警信息 echo "告警信息:`echo $1`" echo $1 #输出自愈机器IP ip=`ifconfig |grep 192.168 | awk '{print $2}' |awk -F ':' '{print $2}'` echo "自愈机器IP: ${ip}" #指定tomcat所在路径 tomcat_path=/data/tomcat #剩余内存容量 free_memory=`free -g | grep Mem | awk '{print $4}'` echo "服务器剩余内存:${free_memory} GB" #要自愈的tomcat名称 tomcat_name=`echo $1 | awk '{print $1}'` #输出当前tomcat服务所使用的端口号 port=`grep 'Connector port=' ${tomcat_path}/${tomcat_name}/conf/server.xml | grep 'protocol="HTTP/1.1"' | egrep -o "[0-9]{4,5}"` echo "服务端口:${port}" #自愈项目 if [[ "$ip" == "192.168.5.91" ]] || [[ "$ip" == "192.168.5.92" ]];then echo "开始重启${tomcat_name}" #ps aux | grep ${tomcat_name} | grep -v grep | awk '{print \$2}' | xargs kill -9 ${tomcat_path}/${tomcat_name}/bin/startup.sh sleep 10s fi #检查项目是否启动成功 for i in {1..20} do sleep 3s echo "第$i次尝试" ava=`curl curl -s http://${ip}:${port}/test_ping` if [[ "$ava" = "true" ]];then echo "${tomcat_name}自愈成功" break fi if [ $i -ge 20 ];then echo "项目自愈不成功!!!" exit 1 fi done 4.新建一个自愈套餐按下图填写5.接入自愈
elasticsearch分片lock锁无法分配报错内容如下所示出现这个问题的原因是原有分片未正常关闭或者清理,所以当分片要重新分配回出问题节点时就会没办法获取分片锁,这不会导致数据丢失,只需要重新出发一下分配分片的操作即可failed to obtain in-memory shard lockcurl -XPOST "http://192.168.10.10:9200/_cluster/reroute?retry_failed" 或者 curl -XPOST "http://192.168.10.10:9200/_cluster/reroute?retry_failed=true"
1.快照存储库备份es索引es的索引库也是需要备份的,我们可以通过kibana上的快照存储库,给索引每天创建快照,定时备份注意:使用nfs作为索引备份存储路径时,一定要为存储路径的属组和属主全部改成elasticsearch,否则会报没权限但是修改属主属组有个问题,有的es集群的elasticsearch用户的uid和其他的会不同,这时就导致在nfs上改了属主属组但是在某个es节点不识别这个uid,这也会导致没权限,最好的解决办法就是在es安装的时候首先创建elasticsearch用户并且制定uid号,这样就能保证有权限使用nfs存储了针对es索引的备份,可以创建一个快照,快照就相当于一个备份,这个快照里面包含了所有的索引,可以借助kibana上的快照存储库,定时的进行索引备份es索引备份恢复大致思路:首先针对要备份的索引创建一个快照01,然后在往索引里面添加一些数据,再创建一个快照02,然后还原01查看效果,在还原02查看效果kibana快照存储备份的好处就是:备份全部索引,每次备份占用的资源特别小,且备份时间在几秒左右环境准备2.部署nfs存储并在es节点进行挂载2.1.部署nfs存储[root@kibana ~]# yum -y install nfs-utils [root@kibana ~]# vim /etc/exports /data/es_backup 192.168.16.0/24(rw,sync,no_root_squash) [root@kibana ~]# systemctl restart nfs [root@kibana ~]# mkdir /data/es_backup [root@kibana ~/soft]# showmount -e Export list for kibana: /data/es_backup 192.168.16.0/242.2.配置es集群各节点增加nfs存储配置所有节点都配置1.挂载nfs [root@elasticsearch ~]# mkdir /data/es_backup [root@elasticsearch ~]# mount 192.168.16.105:/data/es_backup/ /data/es_backup 2.配置es指定存储路径 [root@elasticsearch ~]# vim /etc/elasticsearch/elasticsearch.yml path.repo: /data/es_backup [root@elasticsearch ~]# systemctl restart elasticsearch 3.授权,在nfs上操作 [root@kibana ~]# chmod 777 /data/es_backup/ [root@kibana ~]# chown -R elasticsearch.elasticsearch /data/es_backup/ 如果nfs没有elasticsearch用户需要创建出来,并且uid和gid号要和es每个集群都保持一致3.在kibana界面创建快照存储库3.1.点击Managerment—快照存储库—注册存储库3.2.填写存储库名称,存储库类型选择共享文件系统名称:es索引备份存储类型选择共享文件系统3.3.填写存储库信息位置(共享存储路径):/data/es_backup块大小:100mb,根据实际来填写3.4.点击注册之后点击验证存储库点击验证存储库3.5.验证存储库成功点击右侧的验证存储库,状态是已连接表示存储库可以正常使用了,如果状态是未连接很有可能是nfs存储权限的问题4.es索引库备份4.1.创建linuxbook索引库并插入数据创建一个linuxbook索引库,用于还原前后的效果对比[root@elaticsearch ~]# curl -XPOST '127.0.0.1:9200/linuxbook/book?pretty' -H 'Content-Type: application/json' -d '{ "id": 1, "book_name": "nginx", "book_jg": "35¥", "book_ys": "206", "book_group": "web" }'插入5条数据数据,包含创建索引时的一条[root@elasticsearch ~]# curl -XPOST '127.0.0.1:9200/linuxbook/book?pretty' -H 'Content-Type: application/json' -d '{ "id": 2, "book_name": "ansible", "book_jg": "20¥", "book_ys": "300", "book_group": "zdh" }' [root@elasticsearch ~]# curl -XPOST '127.0.0.1:9200/linuxbook/book?pretty' -H 'Content-Type: application/json' -d '{ "id": 3, "book_name": "shell", "book_jg": "20¥", "book_ys": "3110", "book_group": "shell" }' [root@elasticsearch ~]# curl -XPOST '127.0.0.1:9200/linuxbook/book?pretty' -H 'Content-Type: application/json' -d '{ "id": 4, "book_name": "tomcat", "book_jg": "20¥", "book_ys": "1024", "book_group": "web" }' [root@elasticsearch ~]# curl -XPOST '127.0.0.1:9200/linuxbook/book?pretty' -H 'Content-Type: application/json' -d '{ "id": 5, "book_name": "python", "book_jg": "20¥", "book_ys": "11024", "book_group": "python" }'4.2.在es上查看新建索引的数据linuxbook索引已经创建,数据插入成功4.3.创建一个快照01一个快照里面包含所有的索引数据,可以每天定时制作一个快照,这就是es的备份方式创建快照的命令只能在kibana上执行,在交互式使用curl命令,会报错,因为我们的存储库是中文的PUT /_snapshot/es索引备份/es-backup-1-2021.1.26?wait_for_completion=true 解释: PUT 提交方式 /_snapshot 快照目录 es索引备份 存储库 es-backup-1-2021.1.26 快照名称 wait_for_completion 参数指定是在初始化快照(默认)后立即返回请求还是等待快照完成 整体来说就是在es索引备份存储库中创建一个es-backup-2021.1.26快照信息 curl命令 curl -XPUT '127.0.0.1:9200/_snapshot/es索引备份/es-backup-1-2021.1.26?wait_for_completion=true'创建完快照点击Managerment—快照存储库—快照 就可以看到我们创建的快照信息了4.4.查看快照信息GET /_snapshot/es索引备份/es-backup-1-2021.1.26可以看到有6个分片,那是因为有6个索引,一个索引一个分片点击快照名也可以看快照的详细信息服务器上生成的快照文件5.在linuxbook索引中增加数据5.1.在索引库中增加数据在kibana上增加就可以了POST /linuxbook/book?pretty { "id": 6, "book_name": "linux", "book_jg": "50¥", "book_ys": "389", "book_group": "system" } POST /linuxbook/book?pretty { "id": 7, "book_name": "windows", "book_jg": "50¥", "book_ys": "789", "book_group": "system" } POST /linuxbook/book?pretty { "id": 8, "book_name": "jenkins", "book_jg": "70¥", "book_ys": "287", "book_group": "jenkins" } POST /linuxbook/book?pretty { "id": 9, "book_name": "elk", "book_jg": "99¥", "book_ys": "10000", "book_group": "elk" } POST /linuxbook/book?pretty { "id": 10, "book_name": "k8s", "book_jg": "100¥", "book_ys": "10000", "book_group": "k8s" } POST /linuxbook/book?pretty { "id": 11, "book_name": "prometheus", "book_jg": "100¥", "book_ys": "10000", "book_group": "prometheus" }查看es上是否新增了数据5.2.再创建一个快照02这个快照里面包含了刚刚插入的6条数据PUT /_snapshot/es索引备份/es-backup-2-2021.1.26?wait_for_completion=true6.将索引还原出第一个快照的状态es索引的还原可以选择不覆盖现有的索引,可以相当于将原来的索引复制一份出来6.1.还原es-backup-1-2021.1.26快照中的linuxbook索引es-backup-1-2021.1.26这个快照中的linuxbook索引只有5条数据,我们还原一下,查看是否正确找到要还原的快照,点击类似于下载的按钮,可以看到提示的是还原勾选取消所有索引,包括系统所有的按钮,如果这个勾选了,那么该快照中的所有索引都会被还原只选择我们要还原的linuxbook索引,选择后下面会提示将还原1个索引勾选重命名索引,将还原的索引库还原到es时改个名字,避免数据覆盖将linuxbook索引重命名为linuxbook_huanyuan_20200126继续点击下一步摘要信息确认无误后点击还原快照还原结束后会在还原状态那边看到是否成功6.2.查看es上是否有还原的索引库已经有我们还原的linuxbook索引并且也已经重命名了6.3.查看数据是否是快照01时的5条数据数据没问题,还原成功7.还原第二个快照第二个快照还原方式和第一个快照还原一模一样,只需要修改一下还原的索引名即可还原成功在es上查看数据,数据11条,完整无误8.定时创建索引快照形成es索引库备份8.1.通过shell脚本实现1.编写脚本[root@elasticsearch /data/es_backup]# vim es_index_bak.sh #!/bin/bashday=`date +%Y.%m.%d` curl -XPUT "http://192.168.75.21:9200/_snapshot/es索引备份/es-index-backup-${day}" 2.赋权 [root@elasticsearch /data/es_backup]# chmod a+x es_index_bak.sh 3.制作定时任务,每天的零点30分进行备份 [root@elasticsearch /data/es_backup]# crontab -e 30 0 * * * /data/es_backup/es_index_bak.sh8.2.通过快照存储库策略实现8.2.1.创建策略点击Managerment—快照存储库—策略—创建策略填写策略信息名称:es索引每日备份快照名称:<es-backup-{now/d}> 官网配置:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/date-math-index-names.html存储库选择es索引备份,频率选择day,时间选择03:30这样生成的下一次快照时间就是每天上午的11:30进行备份,设置11:30主要为了测试,一般还是要在凌晨进行备份,具体为什么选择03:30对应11:30,差了8个小时,这里也不是很清楚,估计是时区的问题,我是上午10点24创建的,时间写03:30就对应了下午的11:30,可以来回调整,直到根据自己的合理匹配了就可以快照设置保持默认即可设置快照的保留天数,这里保留30天信息复查没问题后点击创建策略8.2.2.查看策略信息只要下次快照的时间是我们理想中的即可快照策略也可以立即运行、编辑、删除8.3.查看快照是否定时创建备份已经自动创建还原linuxbook索引,验证备份是否可用查看es索引数据
1.kibana汉化前可以看到全是英文,有时候根本不知道什么意思2.汉化kibana2.1.下载汉化包[root@elasticsearch ~]# wget https://mirrors.yangxingzhen.com/kibana/Kibana_Hanization.tar.gz2.2.开始汉化yum安装的kibana目录为:/usr/shar/kibana1.备份程序 [root@elasticsearch ~/Kibana_Hanization/old]# cp -r /usr/share/kibana/ /tmp 2.开始汉化 [root@elasticsearch ~]# cd Kibana_Hanization/old [root@elasticsearch ~/Kibana_Hanization/old]# python main.py /usr/share/kibana2.3.重启kibana[root@elasticsearch ~/Kibana_Hanization/old]# systemctl restart kibana3.汉化以后的样子虽然还是有很多英文,不过已经够用了
ELK终极架构ELK终极架构ELK终极架构1.ELK终极架构图2.部署终极ELK架构2.2.部署两台redis2.3.配置nginx四层负载均衡2.4.配置keepalived高可用2.5.挂掉redis01查看是否会切换到redis02实现高可用2.6.配置filebeat将日志存储到高可用的redis集群2.7.产生日志并查看redis上是否产生的key2.8.配置logstash连接redis高可用集群2.9.启动logstash并查看es上是否产生索引库3.在kibana上关联es索引并查看日志信息3.1.关联es索引库3.2.查看收集来的日志数据1.ELK终极架构图最接近终极的架构图就是我们从redis中读取收集来的日志最后由logstash存储到es库,但是这个架构有个缺陷假如redis挂掉,我们就无法收集日志了redis单点问题,我们可以通过集群的方式来实现,但是redis的三种集群模式,除了主从复制,其他两个集群,filebeat均不支持将数据写入集群,但是主从复制又有弊端,假如主节点挂掉,还需要通过命令的方式把从节点改为可读可写filebeat支持kafka集群的写入,但是kafka不太熟悉,我们还是用redis来实现我们可以配置两个单独的redis,在通过nginx四层负载均衡+keepalvide做成高可用集群,当其中一个redis坏掉了,另一个redis接替其工作,当redis01处于工作模式时,就把redis02作为备份模式,这样redis02上面就没有数据的产生,从而可以保证数据的一致性,不会导致重复ELK终极架构图2.部署终极ELK架构2.2.部署两台redis192.168.81.210配置1.安装redis(epel源中有redis的rpm包) [root@elasticsearch ~]# yum -y install redis 2.启动redis [root@elasticsearch ~]# systemctl start redis [root@elasticsearch ~]# systemctl enable redis 3.查看端口号 [root@elasticsearch ~]# netstat -lnpt | grep redis tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 94345/redis-server 4.登陆redis [root@elasticsearch ~]# redis-cli 127.0.0.1:6379> 5.配置redis允许任何主机访问 [root@elasticsearch ~]# vim /etc/redis.conf bind 0.0.0.0 [root@elasticsearch ~]# systemctl restart redis 6.创建一个key方便识别(最终测试的时候看) [root@elasticsearch ~]# redis-cli 127.0.0.1:6379> set redis01 192.168.81.210 OK 192.168.81.220配置1.安装redis(epel源中有redis的rpm包) [root@node-2 ~]# yum -y install redis 2.启动redis [root@node-2 ~]# systemctl start redis [root@node-2 ~]# systemctl enable redis 3.查看端口号 [root@node-2 ~]# netstat -lnpt | grep redis tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 94345/redis-server 4.登陆redis [root@node-2 ~]# redis-cli 127.0.0.1:6379> 5.配置redis允许任何主机访问 [root@node-2 ~]# vim /etc/redis.conf bind 0.0.0.0 [root@node-2 ~]# systemctl restart redis 6.创建一个key方便识别(最终测试的时候看) [root@node-2 ~]# redis-cli 127.0.0.1:6379> set redis02 192.168.81.220 OK2.3.配置nginx四层负载均衡192.168.81.210配置[root@elasticsearch ~]# vim /etc/nginx/nginx.conf stream { upstream redis { server 192.168.81.210:6379 max_fails=2 fail_timeout=10s; server 192.168.81.220:6379 max_fails=2 fail_timeout=10s backup; } server { listen 6378; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass redis; } } [root@elasticsearch ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@elasticsearch ~]# systemctl restart nginx192.168.81.220配置[root@node-2 ~]# vim /etc/nginx/nginx.conf stream { upstream redis { server 192.168.81.210:6379 max_fails=2 fail_timeout=10s; server 192.168.81.220:6379 max_fails=2 fail_timeout=10s backup; } server { listen 6378; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass redis; } } [root@elasticsearch ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@node-2 ~]# systemctl restart nginx测试nginx负载是否可用使用两个负载均衡任意一个ip都可以负载到redis01,因为redis02是备份状态,一般高可用集群都是两套负载均衡集群连接到keepalived[root@elasticsearch ~]# redis-cli -h 192.168.81.210 -p 6378 192.168.81.210:6378> keys * 1) "redis01 [root@elasticsearch ~]# redis-cli -h 192.168.81.220 -p 6378 192.168.81.220:6378> keys * 1) "redis01"2.4.配置keepalived高可用192.168.81.210配置[root@elasticsearch ~]# vim /etc/keepalived/keepalived.conf global_defs { router_id lb01 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 50 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.81.211 } } [root@elasticsearch ~]# systemctl restart keepalived [root@elasticsearch ~]# systemctl enable keepalived192.168.81.220配置[root@node-2 ~]# vim /etc/keepalived/keepalived.conf global_defs { router_id lb02 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 50 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.81.211 } } [root@node-2 ~]# systemctl restart keepalived [root@node-2 ~]# systemctl enable keepalived测试keepalived1.漂移IP已经在主节点 [root@elasticsearch ~]# ip a |grep virbr0 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 2.使用虚拟IP登陆redis [root@elasticsearch ~]# redis-cli -h 192.168.81.211 -p 6378 192.168.81.211:6378> keys * 1) "redis01 3.关闭主节点,查看ip是否会漂移 [root@elasticsearch ~]# systemctl stop keepalived 在backup节点查看,漂移成功 [root@node-2 ~]# ip a | grep vir 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 2.5.挂掉redis01查看是否会切换到redis02实现高可用[root@elasticsearch ~]# redis-cli -h 192.168.81.211 -p 6378 192.168.81.211:6378> keys *1) "redis01"192.168.81.211:6378> keys *1) "redis01"192.168.81.211:6378> keys *1) "redis01"192.168.81.211:6378> 192.168.81.211:6378> 192.168.81.211:6378> 192.168.81.211:6378> keys *1) "filebeat"2) "redis02"192.168.81.211:6378>完美的实现了高可用,可以看到redis01挂掉后redis02里面进行了工作2.6.配置filebeat将日志存储到高可用的redis集群只需要修改传输给redis的地址为漂移ip地址即可[root@nginx ~]# vim /etc/filebeat/filebeat.yml output.redis: hosts: ["192.168.81.211:6379"] key: "nginx-all-key" db: 0 timeout: 5 [root@nginx ~]# systemctl restart filebeat 2.7.产生日志并查看redis上是否产生的key1.产生日志 ab -c 100 -n 1000 http://www.jiangxl.com/ ab -c 100 -n 1000 http://bbs.jiangxl.com/ ab -c 100 -n 1000 http://blog.jiangxl.com/ 2.查看redis上是否产生了key 192.168.81.211:6378> keys * 1) "nginx-all-key" #已经产生了key 2) "redis01"2.8.配置logstash连接redis高可用集群[root@elasticsearch ~]# vim /etc/logstash/conf.d/redis.conf input { redis { host => "192.168.81.210" port => "6379" db => "0" key => "nginx-all-key" data_type => "list" } }只需要改redis地址这一行即可2.9.启动logstash并查看es上是否产生索引库[root@elasticsearch ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf logstash输出es上已经有数据索引产生了3.在kibana上关联es索引并查看日志信息3.1.关联es索引库nginx-www-access索引nginx-bbs-access索引nginx-blog-access索引3.2.查看收集来的日志数据nginx-www-access索引nginx-bbs-access索引nginx-blog-access索引
1.优化配置思路之前的logstash读取redis收集来的日志数据配置需要很多步骤,每次新加一个日志都特别繁琐没有优化前新增一个日志收集的配置步骤:1.配置filebeat收集什么日志,增加标签 2.配置filebeat将日志存储到哪里 3.配置logstash从哪里读取数据 4.配置logstash将数据存放在哪里可以思考一下,logstash其实从哪里读取数据都是一样的,关键在于存储到哪里,如果我们在filebeat配置的时候就把所有的日志都存储到redis的某一个key中,并将所有的日志都打上tag标签,logstash在收集的时候,只读取这一个key的数据,最后按照tag标签去分类存储,这样一来就减少了2步配置优化后增加一个日志配置步骤: 1.在filebeat中配置收集什么日志 2.在logstash中配置tag存放在哪个es索引库2.优化filebeat配置每个日志都打上不同的tag标签,所有的日志都存储到nginx-all-key[root@nginx /etc/filebeat]# vim filebeat.yml #定义收集什么日志 filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/www_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["nginx-www"] - type: log enabled: true paths: - /var/log/nginx/bbs_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["nginx-bbs"] #定义redis集群地址以及定义索引名 output.redis: hosts: ["192.168.81.220:6379"] key: "nginx-all-key" db: 0 timeout: 5 setup.template.name: "nginx" setup.template.pattern: "nginx-*" setup.template.enabled: false setup.template.overwrite: true 3.优化logstash配置只留一个key,从这个key中获取数据后在根据标签的不同,分别创建不同的索引库# input { redis { host => "192.168.81.220" port => "6379" db => "0" key => "nginx-all-key" data_type => "list" } } output { if "nginx-www" in [tags] { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-www-access-%{+yyyy.MM.dd}" } } if "nginx-bbs" in [tags] { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-bbs-access-%{+yyyy.MM.dd}" } } } 4.新收集一个blog日志4.1.配置filebeat指定blog日志路径只需要指定路径即可,不需要其他配置[root@nginx ~]# vim /etc/filebeat/filebeat.yml - type: log enabled: true paths: - /var/log/nginx/blog_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["nginx-blog"] [root@nginx ~]# systemctl restart filebeat4.2.配置logstash自定义索引库只需要增加创建什么索引库即可[root@elasticsearch ~]# vim /etc/logstash/conf.d/redis.conf if "nginx-blog" in [tags] { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-blog-access-%{+yyyy.MM.dd}" } } 4.3.启动logstash[root@elasticsearch ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf4.4.产生日志并查看redis key1.产生日志 ab -c 100 -n 1000 http://bbs.jiangxl.com/ ab -c 100 -n 1000 http://www.jiangxl.com/ ab -c 100 -n 1000 http://blog.jiangxl.com/ 2.查看redis上的key [root@node-2 ~]# redis-cli --raw 127.0.0.1:6379> KEYS * filebeat nginx-all-key 127.0.0.1:6379> LLEN nginx-all-key 3000 nginx-all-key中一共有3000条数据,正好就是我们用ab产生的3000个访问4.5.查看es索引库是否生成三个日志的索引库全部生成了
logstash读取redis缓存日志1.logstash从redis读取收集日志原理常规的日志收集方式都是由filebeat收集完直接输出给es集群,如果当后端应用访问量大,产生的日志也特别巨大,这时再由filebeat收集日志直接传输给es,会给es带来特别大的压力,如果es这时挂掉,filebeat依然在收集日志,这时filebeat找不到es集群,则会把收集来的日志丢弃针对日志量大的问题可以在es集群前面增加redis和logstash,filebeat收集完日志交给redis,由logstash从redis中读取收集来的日志数据传输给es集群,最终在kibana上进行展示logstash只需要部署一台即可,只是用于将redis收集来的日志传输给es集群由于redis属于缓存数据库,当logstash把数据从redis上取完后,会自动把key删掉logstash并不是读完redis中所有的数据后直接传输给es,而是读完一条redis的数据后,就往es上存储一条,这样就不会减轻es集群的压力环境准备2.配置filebeat收集日志存储到redis2.1.部署redis1.安装redis(epel源中有redis的rpm包) [root@node-2 ~]# yum -y install redis 2.启动redis [root@node-2 ~]# systemctl start redis [root@node-2 ~]# systemctl enable redis 3.查看端口号 [root@node-2 ~]# netstat -lnpt | grep redis tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 94345/redis-server 4.登陆redis [root@node-2 ~]# redis-cli 127.0.0.1:6379> 5.配置redis允许任何主机访问 [root@node-2 /etc/filebeat]# vim /etc/redis.conf bind 0.0.0.0 [root@node-2 /etc/filebeat]# systemctl restart redis2.2.redis基本操作1.设置一个key 127.0.0.1:6379>set key OK 2.查看一个key 127.0.0.1:6379> keys * 1) "key" 3.查看key类型 127.0.0.1:6379> type test none 4.查看数据 127.0.0.1:6379> LRANGE test 0 -1 (empty list or set)2.3.配置filebeat将收集的日志存储到redisinputs还是一致的,只是outpot换成了redis配置语法:output.redis:hosts: [“192.168.81.220:6379”] #redis地址key: “nginx-www” #存储的库名db: 0timeout: 5收集前要确保nginx应用的日志输出为json格式,在使用ab命令生成日志1.配置filebeat [root@nginx ~]# !vim /etc/filebeat/filebeat.yml #定义收集什么日志 filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/www_access.log json.keys_under_root: true json.overwrite_keys: true #定义modules模块路径 filebeat.config.modules: path: ${path.config}/modules.d/*.yml reload.enabled: false #指定kibana地址 setup.kibana: host: "192.168.81.210:5601" #定义redis集群地址以及定义索引名 output.redis: hosts: ["192.168.81.220:6379"] #redis地址 key: "nginx-www" #存储的库名 db: 0 timeout: 5 setup.template.name: "nginx" setup.template.pattern: "nginx-*" setup.template.enabled: false setup.template.overwrite: true 2.重启filebeat [root@nginx ~]# systemctl restart filebeat2.4.查看redis是否创建了nginx-www由于我们nginx的日志是中文的,因此在使用redis-cli时要增加raw参数,否则看到的都是乱码[root@node-2 ~]# redis-cli --raw 127.0.0.1:6379> KEYS * 1) "key" 2) "nginx-www" 127.0.0.1:6379> TYPE nginx-www list 127.0.0.1:6379> LRANGE nginx-www 0 -1已经有nginx-www key了,并且数据也都是刚刚filebeat传输过来的nginx 日志解析正常3.配置logstash读取redis日志并存储到es集群3.1.安装logstash1.下载logstash https://repo.huaweicloud.com/logstash/6.6.0/logstash-6.6.0.rpm 2.安装logstash [root@elasticsearch ~/soft]# rpm -ivh logstash-6.6.0.rpm 警告:logstash-6.6.0.rpm: 头V4 RSA/SHA512 Signature, 密钥 ID d88e42b4: NOKEY 准备中... ################################# [100%] 正在升级/安装... 1:logstash-1:6.6.0-1 ################################# [100%] Using provided startup.options file: /etc/logstash/startup.options OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N Successfully created system startup script for Logstash 3.2.配置logstash读取redis缓存的日志配置文件含义input { //从哪里读取数据redis { //数据源是从redis读取host => “192.168.81.220” //redis地址port => “6379” //redis端口db => “0”key => “nginx-www” //从哪个key读取数据data_type => “list” //key的类型}}output { //存储到哪stdout{}elasticsearch { //存储到eshosts => “http://192.168.81.210:9200” //es地址manage_template => falseindex => “nginx-www-access-%{+yyyy.MM.dd}” //索引名}1.配置logstash [root@elasticsearch ~]# vim /etc/logstash/conf.d/redis.conf input { redis { host => "192.168.81.220" port => "6379" db => "0" key => "nginx-www" data_type => "list" } } output { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-www-access-%{+yyyy.MM.dd}" } } 2.启动logstash [root@elasticsearch ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf 启动成功会输出很多读取来的日志内容,最好用nohup来启动,启动过程特别耗时间nohup /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf &每次收集过来的日志都会输出在大屏上个,用了nohup后会输出到nohup.out文件,还是比较方便的3.3.查看es索引库数据收集过来23条3.4.kibana关联es索引库并查看收集的日志3.4.1.关联es索引库3.4.2.查看收集来的日志数据点击Discovery—选择索引字段也都是可以过滤匹配的4.filebeat收集多个日志存储到redis并自定义key4之前都是一台机器上的所有日志都存储到redis的一个key中,显然有点不合理,因此需要针对每一个收集的日志文件让其存储到不同的key中。配置和存储到es集群差不多,不同日志存储到redis不同key,其实思路和存储到es是一样的,做一个tag标签,当tag值为xxx就创建xxx的key keys: - key: "www" //当tags为www就创建www的key when.contains: tags: "www" - key: "bbs" when.contains: tags: "bbs"4.1.配置filebeat收集日志并自定义redis key[root@nginx ~]# vim /etc/filebeat/filebeat.yml #定义收集什么日志 filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/www_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["nginx-www"] - type: log enabled: true paths: - /var/log/nginx/bbs_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["nginx-bbs"] #定义modules模块路径 filebeat.config.modules: path: ${path.config}/modules.d/*.yml reload.enabled: false #指定kibana地址 setup.kibana: host: "192.168.81.210:5601" #定义redis集群地址以及定义索引名 output.redis: hosts: ["192.168.81.220:6379"] #key: "nginx-www" keys: - key: "nginx-www" when.contains: tags: "nginx-www" - key: "nginx-bbs" when.contains: tags: "nginx-bbs" db: 0 timeout: 5 setup.template.name: "nginx" setup.template.pattern: "nginx-*" setup.template.enabled: false setup.template.overwrite: true [root@nginx ~]# systemctl restart filebeat4.2.产生日志并查看redis上的key1.产生日志 [root@elasticsearch ~]# ab -c 100 -n 2000 http://www.jiangxl.com/ [root@elasticsearch ~]# ab -c 100 -n 2000 http://bbs.jiangxl.com/ 2.查看redis上生成的key 127.0.0.1:6379> keys * 1) "nginx-bbs" 2) "filebeat" 3) "nginx-www" 127.0.0.1:6379> LLEN nginx-bbs #查key里面有多少条数据 2000 127.0.0.1:6379> LLEN nginx-www 2000 5.配置logstash自定义es索引5.1.配置logstash指定不同的索引存储库语法格式:if “nginx-www” in [tags] { //当标签为nginx-www时,就创建nginx-www-access索引库,如果要写多组自定义索引就填写几个if即可stdout{}elasticsearch {undefinedhosts => “http://192.168.81.210:9200”manage_template => falseindex => “nginx-www-access-%{+yyyy.MM.dd}”}} input { redis { host => "192.168.81.220" port => "6379" db => "0" key => "nginx-www" data_type => "list" } redis { host => "192.168.81.220" port => "6379" db => "0" key => "nginx-bbs" data_type => "list" } } output { if "nginx-www" in [tags] { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-www-access-%{+yyyy.MM.dd}" } } if "nginx-bbs" in [tags] { stdout{} elasticsearch { hosts => "http://192.168.81.210:9200" manage_template => false index => "nginx-bbs-access-%{+yyyy.MM.dd}" } } } 5.2.重载logstash并查看收集输出[root@elasticsearch ~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf logstash并不是全部收集完在传输给es集群,而是收集过来一条就传输给es一条,这样一样就减轻了es的压力5.3.观察redis key变化127.0.0.1:6379> LLEN nginx-www 0 127.0.0.1:6379> LLEN nginx-bbs 05.4.查看es上的是否创建索引5.5.在kibana上关联es索引nginx-www-access索引nginx-bbs-access索引5.5.查看日志数据nginx-www-access索引nginx-bbs-access索引6.故障排查6.1.logstash启动不成功启动提示如下,一直不动OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N[root@elasticsearch ~]# vim /etc/logstash/jvm.options -Xms256m -Xmx256m -XX:-AssumeMP 配置完重启即可
centos7双网卡绑定bond1.bond简介生产环境必须提供 7×24 小时的网络传输服务。借助于网卡绑定技术,不仅 可以提高网络传输速度,更重要的是,还可以确保在其中一块网卡出现故障时,依然可以正 常提供网络服务。假设我们对两块网卡实施了绑定技术,这样在正常工作中它们会共同传输 数据,使得网络传输的速度变得更快;而且即使有一块网卡突然出现了故障,另外一块网卡 便会立即自动顶替上去,保证数据传输不会中断。Linux 内核网卡绑定驱动模式:mode0(平衡负载模式):平时两块网卡均工作,且自动备援,但需要在与服务器本地 网卡相连的交换机设备上进行端口聚合来支持绑定技术。mode1(自动备援模式):平时只有一块网卡工作,在它故障后自动替换为另外的网卡。mode6(平衡负载模式):平时两块网卡均工作,且自动备援,无须交换机设备提供辅 助支持。2.配置bond以双网卡为例2.1.配置两块网卡配置信息[root@k8s-master ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE=Ethernet BOOTPROTO=none ONBOOT=yes DEVICE=ens33 MASTER=bond0 SLAVE=yes [root@k8s-master ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens37 TYPE=Ethernet BOOTPROTO=none ONBOOT=yes DEVICE=ens37 MASTER=bond0 SLAVE=yes 2.2.配置bond网卡信息[root@k8s-master ~]# vim /etc/sysconfig/network-scripts/ifcfg-bond0 TYPE=Ethernet BOOTPROTO=none ONBOOT=yes DEVICE=bond0 IPADDR=192.168.81.210 NETMASK=255.255.255.0 GATEWAY=192.168.81.2 DNS=114.114.114.1142.3.配置内核网卡驱动模式[root@k8s-master ~]# vim /etc/modprobe.d/bond.conf alias bond0 bonding options bonding mode=6 miimon=2002.4.重启网卡[root@k8s-master ~]# systemctl restart network2.5.查看bond是否生效[root@k8s-master ~]# ifconfig bond0: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500 inet 192.168.81.210 netmask 255.255.255.0 broadcast 192.168.81.255 inet6 fe80::20c:29ff:fed5:a566 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:d5:a5:66 txqueuelen 1000 (Ethernet) RX packets 811 bytes 65115 (63.5 KiB) RX errors 0 dropped 187 overruns 0 frame 0 TX packets 1574 bytes 118007 (115.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST> mtu 1500 ether 00:0c:29:d5:a5:66 txqueuelen 1000 (Ethernet) RX packets 1851 bytes 209289 (204.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1857 bytes 234505 (229.0 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens37: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST> mtu 1500 ether 00:0c:29:d5:a5:70 txqueuelen 1000 (Ethernet) RX packets 457 bytes 39789 (38.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 753 bytes 52110 (50.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 3.自动化配置bond脚本使用方式:sh boun.sh 网卡模式 IP地址[root@elk-1 ~/soft]# cat bound.sh #!/bin/bash #设置多网卡bond,实现网卡的高可用,提升网卡带宽 #此脚本需要传入两个参数 $1为bond模式 $2为boundIP地址 if [ $# = 2 ] ; then #判断传入的参数是否为2个 #定义主机上网卡的名称变量 NAME1=eno1 NAME2=eno2 #定义要写入网卡配置文件的网络参数 IPADDR=$2 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 DNS=114.114.114.114 else echo "脚本使用错误!!!! 格式为:$PWD/$0 [ 0-6 ] ipaddr 例如: $PWD/$0 网卡模式 192.168.1.100" exit 1; fi #生成bond配置文件 echo "alias bond0 bonding options bonding mode=$1 miimon=200 " > /etc/modprobe.d/bonding.conf #判断第一个网卡是否存在,如果存在就生成第一个网卡的配置文件 if [ ! -z $NAME1 ] ;then echo "DEVICE=$NAME1 BOOTPROTO=none MASTER=bond0 SLAVE=yes" > /etc/sysconfig/network-scripts/ifcfg-$NAME1 fi #判断第二个网卡是否存在,如果存在就生成第二个网卡的配置文件 if [ ! -z $NAME2 ] ;then echo "DEVICE=$NAME2 BOOTPROTO=none MASTER=bond0 SLAVE=yes" > /etc/sysconfig/network-scripts/ifcfg-$NAME2 fi #生成bond配置文件 echo "DEVICE=bond0 BOOTPROTO=none ONBOOT=yes IPADDR=$IPADDR NETMASK=$NETMASK GATEWAY=$GATEWAY DNS1=$DNS " >/etc/sysconfig/network-scripts/ifcfg-bond0 #重启网络服务 systemctl disable NetworkManager systemctl stop NetworkManager modprobe -r bonding modprobe bonding service network restart #打印网络信息 echo "IPADDR=$IPADDR NETMASK=$NETMASK GATEWAY=$GATEWAY DNS1=$DNS "
filebeat收集容器日志现在很多公司都是用docker容器来运行服务,一台机器上会有很多个docker,docker容器里面的日志也需要收集分析,filebeat也有docker容器的日志收集方案官方配置地址https://www.elastic.co/guide/en/beats/filebeat/6.6/filebeat-input-docker.html1.部署docker1.安装docker [root@docker ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo [root@docker ~]# sed -i 's#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#' /etc/yum.repos.d/docker-ce.repo [root@docker ~]# yum -y install docker-ce [root@docker ~]# tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://zggyaen3.mirror.aliyuncs.com"] } EOF { "registry-mirrors": ["https://zggyaen3.mirror.aliyuncs.com"] } 2.启动docker [root@docker ~]# systemctl start docker 3.运行一个nginx容器 [root@docker ~]# docker run -d -p 888:80 nginx 4.查看容器日志路径,这个日志就是容器里面程序的日志 [root@docker ~]# docker inspect compassionate_mayer | grep log "LogPath": "/var/lib/docker/containers/7b345b1107fdd302d6b476403bb61eaca19414d42a3c316283d3f490f7380dfb/7b345b1107fdd302d6b476403bb61eaca19414d42a3c316283d3f490f7380dfb-json.log", 2.配置filebeat收集单个docker容器日志2.1.配置filebeat1.配置filebeat [root@docker /etc/filebeat]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: docker containers.ids: - '7b345b1107fdd302d6b476403bb61eaca19414d42a3c316283d3f490f7380dfb' #填写容器的id output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: index: "docker-nginx-%{+yyyy.MM.dd}" setup.template.name: "docker" setup.template.pattern: "docker-*" setup.template.enabled: false setup.template.overwrite: true 2.重启filebeat [root@docker /etc/filebeat]# systemctl restart filebeat.service2.2.查看es是否产生了索引2.3.kibana关联es上的索引点击Managerment—创建索引2.4.查看收集来的日志点击Discovery—选择索引这次收集的docker容器日志不是那么细分的,虽然这个日志也是json格式,但是docker默认他们放在了一个value里格式化后的日志3.配置filebeat收集多个容器日志3.1.运行多个docker[root@docker ~]# docker run -d -p 999:80 nginx [root@docker ~]# docker run -d -p 888:80 nginx3.2.配置filebeat[root@docker ~]# grep -Ev '#|^$' /etc/filebeat/filebeat.yml filebeat.inputs: - type: docker containers: path: "/var/lib/docker/containers" #docker容器日志的路径 ids: - "*" #如果只想收集一个容器的日志,就写一个容器的id号,如果想收集所有容器的日志则写* output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: index: "docker-nginx-%{+yyyy.MM.dd}" setup.template.name: "docker" setup.template.pattern: "docker-*" setup.template.enabled: false setup.template.overwrite: true3.3.产生日志ab -c 100 -n 5672 http://www.jiangxl.com:999/ ab -c 100 -n 1000 http://www.jiangxl.com:888/ 3.4.查看es索引是否增加数据已经增加3.5.kibana关联es索引3.6.查看收集来的日志是不是多个容器的已经是不同容器的日志了
1.elasticsearch集群介绍elasticsearch可以横向扩展至数百(甚至数千)的服务器节点,同时可以处理PB级别数据elasticsearch天生就是分布式的,并且在设计时屏蔽了分布式的复杂性elasticsearch经肯屏蔽了风不是系统的复杂性elasticsearch集群的特点:分配文档到不同的容器或分配中,文档可以存储一个或多个节点按集群节点来负载均衡这些分配,从而对索引和搜索过程进行负载均衡复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失将集群中任意节点的请求路由到存有相关数据的节点集群扩容时无缝整合性节点,重新分配分片以便于从群节点中恢复一个运行中的elasticsearch实例被称为一个节点,而集群是由一个或多个拥有相同cluster.name配置的节点组成,他们共同承担数据和负载的压力当有节点加入集群或者从集群中移除节点时,集群将会重新平均分布所有的数据当一个节点被选举称为主节点时,它将负责管理集群范围内所有的变更,例如增加、删除索引或者增加、删除节点等,而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个节点的情况下,即使流量增加它也不会成为瓶颈,任何节点都可以成为主节点,我们的实例集群只有一个节点,所以同时也成为了主节点,也就是谁先部署完并启动了第一个节点,谁就是master作为用户,我们可以将请求发送到集群中的任何节点,包括主节点,每个节点的数据都是一样的,每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点,无论我们将请求发送到那个节点,它都能负责从各个包含我们所需文档节点进行收集,并将数据结果返回给客户端文档doc就是索引中的一条数据es集群搭建完后将不在往elasticsearch.log中写日志,而是在集群名.log中写日志2.elasticsearch集群部署2.1.192.168.81.210主节点配置集群配置文件含义cluster.name: es-application #集群名称,要求唯一node.name: node-1 #节点名称path.data: /data/elasticsearch #数据存储路径path.logs: /var/log/elasticsearch #日志路径network.host: 192.168.81.210,127.0.0.1 #对外暴露的地址http.port: 9200 #端口号discovery.zen.ping.unicast.hosts: [“192.168.81.210”, “192.168.81.220”] #主节点要配置上集群各节点ip地址,从节点配置的时候只写上主节点的ip和自己节点的ip即可discovery.zen.minimum_master_nodes: 1 #允许master的数量http.cors.enabled: truehttp.cors.allow-origin: “*”2.1.1.安装elasticsearch所有节点都要安装1.准备Java环境 yum -y install java java -version 2.下载elasticsearch rpm包 mkdir soft cd soft wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.0.rpm 3.安装elasticsearch yum -y localinstall elasticsearch-6.6.0.rpm 4.启动elasticsearch systemctl daemon-reload systemctl start elasticsearch systemctl enable elasticsearch 2.1.2.配置node-1主节点1.修改主配置文件 [root@elasticsearch ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: es-application node.name: node-1 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.210,127.0.0.1 http.port: 9200 discovery.zen.ping.unicast.hosts: ["192.168.81.210", "192.168.81.220"] discovery.zen.minimum_master_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" 2.重启 [root@elaticsearch ~]# systemctl restart elasticsearch2.1.3.访问node-1节点访问:http://192.168.81.210:92002.2.192.168.81.220从节点配置2.2.1.安装elasticsearch1.准备Java环境 [root@node-2 ~]# yum -y install java [root@node-2 ~]# java -version openjdk version "1.8.0_262" OpenJDK Runtime Environment (build 1.8.0_262-b10) OpenJDK 64-Bit Server VM (build 25.262-b10, mixed mode) 2.下载elasticsearch rpm包 [root@node-2 ~]# mkdir soft [root@node-2 ~]# cd soft [root@node-2 soft]# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.0.rpm [root@elasticsearch soft]# ll -h -rw-r--r--. 1 root root 109M 11月 15 08:58 elasticsearch-6.6.0.rpm 3.安装elasticsearch [root@node-2 soft]# yum -y localinstall elasticsearch-6.6.0.rpm 4.启动elasticsearch [root@node-2 soft]# systemctl daemon-reload [root@node-2 soft]# systemctl start elasticsearch [root@node-2 soft]# systemctl enable elasticsearch2.2.2.配置node-2节点1.修改配置文件 [root@node-2 ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: es-application node.name: node-2 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.220,127.0.0.1 http.port: 9200 discovery.zen.ping.unicast.hosts: ["192.168.81.210", "192.168.81.220"] discovery.zen.minimum_master_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" 2.重启 [root@node-2 ~]# systemctl restart elasticsearch2.2.3.访问node-2节点访问:http://192.168.81.220:92002.3.查看集群状态在es-head插件中连接任意es节点都能看到数据则表示集群搭建成功集群状态为绿色的要求:最少一个集群节点,且主分片和副本分片都正常,没有数据丢失星号表示主节点、圆圈表示副本节点索引分片全绿表示数据无丢失3.elasticsearch集群状态码集群状态最低要求:至少一个副本五个分片副本的数量是可以控制的,每次创建索引的时候可以指定拥有几个副本分片,如果超出了当前节点数,则会变灰3.1.green状态要想达到green状态需要满足的条件:所有索引数据都存在,副本满足条件、所有的数据都完整一条数据会分布在所有分片中,假如一个数据本来应该是五个分片,但是只在其中三个分片中有数据,则表示数据不完整,集群状态就达不到green状态由于是是刚搭建好的集群,之前单台节点的时候也做过索引,因此主分片都会在一个节点上,后面创建的所有将会分布在所有节点上,提供冗余,当系统负载小的时候在一定时间内,它也会重新分片3.2.yellow状态yellow的状态:所有索引数据完整,但是副本不满足条件,yellow状态常常是刚刚搭建起一个elasticsearch节点,这时没有副本分片,因此会处于yellow状态我们可以停掉一个node节点查看 效果停止任意一个node节点的命令systemctl stop elasticsearch3.3.red状态red状态:数据不完整,有点所以数据丢失elasticsearch中会有多个索引,其中一个索引数据有丢失不会影响整个集群其他索引的使用,只是单单某一个有问题,这时集群的状态也会显示为red状态red状态示意图,其中一个副本的数据有问题3.4.索引分片处于黄色状态处于黄色状态表示正在同步数据,当数据同步完会变成绿色刚起来的node节点它是没有数据的,因此需要从主节点进行同步数据,新增一个node节点都会从主节点去同步数据,最后同步完就变成了绿色4.elasticsearch集群操作集群的任意操作命令都可以在任意node节点去执行,因为数据都是同步的curl命令中的GET一般都是获取某些信息,PUT是提交某些信息在elasticsearch交互模式中只能使用GET、DELETE、HEAD、PUT集群操作指令帮助文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-node-info.html4.1.查看集群状态[root@elasticsearch ~]# curl -XGET 'http://localhost:9200/_cluster/health?pretty' { "cluster_name" : "es-application", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 10, "active_shards" : 20, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 } 4.2.查看集群所有信息输出的信息超级多,包含了集群的节点信息、索引信息[root@elasticsearch ~]# curl -XGET 'http://localhost:9200/_cluster/stats?human&pretty' { "_nodes" : { "total" : 2, #node节点的数量 "successful" : 2, #成功的几个 "failed" : 0 #失败的几个 }, "cluster_name" : "es-application", "cluster_uuid" : "z4wKY7WiQaa6ZkcmW8lTtA", "timestamp" : 1609636910311, "status" : "green", #集群的状态码 "indices" : { "count" : 2, "shards" : { "total" : 20, "primaries" : 10, "replication" : 1.0, "index" : { "shards" : { "min" : 10, "max" : 10, "avg" : 10.0 }, "primaries" : { "min" : 5, "max" : 5, "avg" : 5.0 }, "replication" : { "min" : 1.0, "max" : 1.0, "avg" : 1.0 } } }, "docs" : { "count" : 8, #所有索引的文档总数 "deleted" : 0 }, "store" : { "size" : "89.9kb", #所有索引总大小 "size_in_bytes" : 92094 }, "fielddata" : { "memory_size" : "1.3kb", "memory_size_in_bytes" : 1396, "evictions" : 0 }, "query_cache" : { "memory_size" : "0b", "memory_size_in_bytes" : 0, "total_count" : 0, "hit_count" : 0, "miss_count" : 0, "cache_size" : 0, "cache_count" : 0, "evictions" : 0 }, "completion" : { "size" : "0b", "size_in_bytes" : 0 }, "segments" : { "count" : 16, "memory" : "43.9kb", "memory_in_bytes" : 44992, "terms_memory" : "32.6kb", "terms_memory_in_bytes" : 33424, "stored_fields_memory" : "4.8kb", "stored_fields_memory_in_bytes" : 4992, "term_vectors_memory" : "0b", "term_vectors_memory_in_bytes" : 0, "norms_memory" : "4kb", "norms_memory_in_bytes" : 4096, "points_memory" : "32b", "points_memory_in_bytes" : 32, "doc_values_memory" : "2.3kb", "doc_values_memory_in_bytes" : 2448, "index_writer_memory" : "0b", "index_writer_memory_in_bytes" : 0, "version_map_memory" : "0b", "version_map_memory_in_bytes" : 0, "fixed_bit_set" : "0b", "fixed_bit_set_memory_in_bytes" : 0, "max_unsafe_auto_id_timestamp" : -1, "file_sizes" : { } } }, "nodes" : { "count" : { "total" : 2, "data" : 2, "coordinating_only" : 0, "master" : 2, "ingest" : 2 }, "versions" : [ "6.6.0" ], "os" : { "available_processors" : 2, "allocated_processors" : 2, "names" : [ { "name" : "Linux", "count" : 2 } ], "pretty_names" : [ { "pretty_name" : "CentOS Linux 7 (Core)", "count" : 2 } ], "mem" : { "total" : "3.5gb", "total_in_bytes" : 3815882752, "free" : "144.8mb", "free_in_bytes" : 151838720, "used" : "3.4gb", "used_in_bytes" : 3664044032, "free_percent" : 4, "used_percent" : 96 } }, "process" : { "cpu" : { "percent" : 0 }, "open_file_descriptors" : { "min" : 291, "max" : 301, "avg" : 296 } }, "jvm" : { "max_uptime" : "2.2h", "max_uptime_in_millis" : 7944670, "versions" : [ { "version" : "1.8.0_275", "vm_name" : "OpenJDK 64-Bit Server VM", "vm_version" : "25.275-b01", "vm_vendor" : "Red Hat, Inc.", "count" : 2 } ], "mem" : { "heap_used" : "307.9mb", "heap_used_in_bytes" : 322941368, "heap_max" : "1.4gb", "heap_max_in_bytes" : 1593180160 }, "threads" : 67 }, "fs" : { "total" : "93.9gb", "total_in_bytes" : 100865679360, "free" : "82.7gb", "free_in_bytes" : 88830054400, "available" : "82.7gb", "available_in_bytes" : 88830054400 }, "plugins" : [ ], "network_types" : { "transport_types" : { "security4" : 2 }, "http_types" : { "security4" : 2 } } } } 4.3.查看集群节点信息[root@elasticsearch ~]# curl -XGET 'http://localhost:9200/_cat/nodes?human&pretty' 192.168.81.210 21 96 0 0.00 0.01 0.05 mdi * node-1 192.168.81.220 15 96 0 0.00 0.01 0.05 mdi - node-2 第一列显示集群节点的ip 倒数第二列显示集群节点的类型,*表示主节点,-表示工作节点,主节点也属于工作节点,只是多了一个调度的作用4.4.查看集群jvm信息这个输出信息属实有点长会输出jvm的版本、内存设置的大小、调优参数[root@elasticsearch ~]# curl -XGET 'http://localhost:9200/_nodes/_all/info/jvm,process?human&pretty' 4.5.在集群中创建一个索引观察分片[root@elasticsearch ~]# curl -XPUT 'http://localhost:9200/index1?pretty' { "acknowledged" : true, "shards_acknowledged" : true, "index" : "index1" }创建完后打开head插件,可以看到:集群创建完之后再次创建的索引主分片和副本分片都会分散存放在不同的节点上,不再是主分片在一台机器,副本分片在一台机器4.6.在集群中创建索引指定分片数量[root@elasticsearch ~]# curl -XPUT 'http://localhost:9200/index2?pretty' -H 'Content-Type: application/json' -d ' { "settings": { "number_of_shards":3, #指定分片数量 "number_of_replicas": 1 #指定副本数量 } }' { "acknowledged" : true, "shards_acknowledged" : true, "index" : "index2" } 主要用到两个参数"number_of_shards"指定分片数量,"number_of_replicas"指定副本数量创建完成后可以在elasticsearch-head中明显看到刚刚创建的索引只有3个分片,1个副本4.7.修改索引的副本数[root@elasticsearch ~]# curl -XPUT 'http://localhost:9200/index2/_settings?pretty' -H 'Content-Type: application/json' -d ' { "settings" : { "number_of_replicas" : 2 } }' { "acknowledged" : true }调整为副本可以看到有一个副本变灰了,是由于我们没有那么多集群节点导致的,一个副本相当于一个机器,俩副本相当于3个节点,我们没有那么多节点因此就会变灰可以看到当有一个索引的副本数有问题时,集群的状态就会变黄,但是其他的索引不会影响使用5.增加一个elasticsearch节点解决副本数问题现在的环境5.1.增加一个节点5.1.1.安装elasticsearch1.准备Java环境 [root@node-3 ~]# yum -y install java java -version 2.下载elasticsearch rpm包 [root@node-3 ~]# mkdir soft [root@node-3 ~]# cd soft [root@node-3 ~]# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.0.rpm 3.安装elasticsearch [root@node-3 ~]# yum -y localinstall elasticsearch-6.6.0.rpm 4.启动elasticsearch [root@node-3 ~]# systemctl daemon-reload [root@node-3 ~]# systemctl start elasticsearch [root@node-3 ~]# systemctl enable elasticsearch5.1.2.修改主节点配置增加node-3节点主节点要在discovery.zen.ping.unicast.hosts配置node-3节点的ip地址,主节点在这个参数中填写集群中所有node节点的地址,而node节点只需要填写一个主节点ip和自身ip即可[root@elasticsearch ~]# vim /etc/elasticsearch/elasticsearch.yml discovery.zen.ping.unicast.hosts: ["192.168.81.210", "192.168.81.220","192.168.81.70"] 5.1.3.配置node-3节点的elasticsearch1.修改主配置文件 [root@node-3 ~]# vim /etc/elasticsearch/elasticsearch.yml cluster.name: es-application node.name: node-3 path.data: /data/elasticsearch path.logs: /var/log/elasticsearch bootstrap.memory_lock: true network.host: 192.168.81.70,127.0.0.1 http.port: 9200 discovery.zen.ping.unicast.hosts: ["192.168.81.210", "192.168.81.70"] discovery.zen.minimum_master_nodes: 1 http.cors.enabled: true http.cors.allow-origin: "*" 2.增加以下配置防止bootstrap报错 [root@node-3 ~]# mkdir /etc/systemd/system/elasticsearch.service.d [root@node-3 ~]# vim /etc/systemd/system/elasticsearch.service.d/override.conf [Service] LimitMEMLOCK=infinity 3.重启 [root@node-3 ~]# systemctl restart elasticsearch5.1.4.查看日志node加入集群后不再使用elasticsearch.log记录日志而是使用集群名.log进行记录日志node已经成功加入集群[root@node-3 ~]# tail -f /var/log/elasticsearch/es-application.log 5.2.head插件查看集群状态在插件中可以看到index2的索引已经达到我们再4.7中指定的副本数量,集群状态也变成了绿色,当副本数的数量是集群总数减去主节点的数量时,副本分片的分布就是特别整齐的,每个节点上都有分片,看起来不会空篮框中的索引因为只有一个副本分片,而node节点有3个,副本分片会随机分配在不同的node,因此会看起来比较空缺,默认创建的索引就是1个副本,5个分片副本也就是相当于备份,副本分片永远都是细框
npm安装依赖报错使用npm安装一个依赖包时报错,报错内容如下:[root@D20L42 qtone-resource-fe]# npm install -g cnpm --registry=https://registry.npm.taobao.org npm ERR! code ENOTFOUND npm ERR! errno ENOTFOUND npm ERR! network request to https://registry.npm.taobao.org/cnpm failed, reason: getaddrinfo ENOTFOUND registry.npm.taobao.org registry.npm.taobao.org:443 npm ERR! network This is a problem related to network connectivity. npm ERR! network In most cases you are behind a proxy or have bad network settings. npm ERR! network npm ERR! network If you are behind a proxy, please make sure that the npm ERR! network 'proxy' config is set properly. See: 'npm help config' npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2021-06-15T05_39_54_815Z-debug.log 解决方法:npm config get proxy npm config get https-proxy npm config set proxy null npm config set https-proxy null npm config set registry http://registry.cnpmjs.org/再次安装依赖就不会报错了npm install -g cnpm --registry=https://registry.npm.taobao.org
filebeat收集多个域名日志并创建不同索引1.为什么要针对不同的应用系统创建不同的索引公司生产环境中一台机器上一定会运行着多个域名的应用,web应用也是集群的方式,如果filebeat收集来的日志都是分散存储,且在es上建立的索引也都是分散的,这样不利于日志的聚合汇总,因此就需要把同一种应用的不同机器上的日志全部采集过来存储到一个索引库中,在kibana根据各种条件去匹配2.搭建web集群环境2.1.环境准备2.2.web集群部署所有节点都按如下配置1.安装nginx yum -y install nginx 2.配置站点配置文件 cat www.conf server{ server_name www.jiangxl.com; listen 80; location ~ / { root /web/www; index index.html; } } cat bbs.conf server{ server_name bbs.jiangxl.com; listen 80; location ~ / { root /web/bbs; index index.html; } } cat blog.conf server{ server_name blog.jiangxl.com; listen 80; location ~ / { root /web/blog; index index.html; } } 3.创建站点路径 mkdir /web/{www,bbs,blog} -p chown -R nginx.nginx /web/ echo "www index" > /web/www/index.html echo "bbs index" > /web/bbs/index.html echo "blog index" > /web/blog/index.html 4.重载nginx nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful systemctl reload nginx 5.访问站点 curl www.jiangxl.com bbs.jiangxl.com blog.jiangxl.com www index bbs index blog index 2.3.配置应用支持json格式的日志输出所有节点都这样配置cat www.conf server{ server_name www.jiangxl.com; listen 80; location ~ / { root /web/www; index index.html; } access_log /var/log/nginx/www_access.log main; } cat bbs.conf server{ server_name bbs.jiangxl.com; listen 80; location ~ / { root /web/bbs; index index.html; } access_log /var/log/nginx/bbs_access.log main; } cat blog.conf server{ server_name blog.jiangxl.com; listen 80; location ~ / { root /web/blog; index index.html; } access_log /var/log/nginx/blog_access.log main; } 3.配置filebeat实现不同日志对应不同索引3.1.实现思路**日志索引思路:**如何才能让filebeat根据不同的日志路径去创建不同的索引,其实我们可以想一下ls -l命令,使用ls -l命令才能得到文件的详细信息,但是使用ll也可以得到,这是为什么呢?是由于ll仅仅只是一个别名,我们也可以当成一个标记,ll对应的就是ls -l命令那么日志也一样的,我们可以把www_access.log当成是一个标记,当标记内容为www_access.log时,我们就把他的日志存储在www_access_xxx的索引库中具体配置:如果一个主机上有多个不同应用的日志需要采集,我们可以定义多个type类型,最后根据定义的标记在indices中进行匹配**日志聚合思路:**我们也可以将所有机器的tomcat、nginx日志进行聚合收集,不需要根据应用去区分,而是把所有的tomcat日志收集在一起,这样便于开发人员去查询日志,查哪台主机的就在kibana上进行过滤就行了如下图所示,tomcat就是聚合收集,查哪台机器的日志就添加一个筛选写上主机名就可以了filebeat标记匹配语法:filebeat.inputs: - type: log //一个日志一个type enabled: true //是否写在es中 paths: //日志路径 - /var/log/nginx/www_access.log json.keys_under_root: true //开启json格式解析 json.overwrite_keys: true tags: ["www"] //标记内容,在[]里填写即可 output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: //索引匹配 - index: "nginx-www-access-%{+yyyy.MM.dd}" //索引库名称 when.contains: //匹配什么标记 tags: "www" //匹配标记为www的日志3.2.配置filebeat不同日志使用不同索引库nginx集群内的所有filebeat都需要如下配置vim复制小技巧:复制2-8行的内容,粘贴到第9行的操作命令:在vim命令模式输入:2,8t9,2,8表示2-8t行复制,9表示粘贴在第九行1.配置filebeat vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/www_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["www"] - type: log enabled: true paths: - /var/log/nginx/bbs_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["bbs"] - type: log enabled: true paths: - /var/log/nginx/blog_access.log json.keys_under_root: true json.overwrite_keys: true tags: ["blog"] output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: - index: "nginx-www-access-%{+yyyy.MM.dd}" when.contains: tags: "www" - index: "nginx-bbs-access-%{+yyyy.MM.dd}" when.contains: tags: "bbs" - index: "nginx-blog-access-%{+yyyy.MM.dd}" when.contains: tags: "blog" setup.template.name: "nginx" setup.template.pattern: "nginx-*" setup.template.enabled: false setup.template.overwrite: true 2.重启filebeat systemctl restart filebeat3.3.在es上查看创建的索引库由于nginx集群相同的应用是要写在同一个索引库中的,因此我们要观察每加一个集群产生的数据变化刚配置完nginx01时的样子www:12条 blog:11条 bbs:12条增加nginx02后的样子访问nginx02上的应用六七次后,数据明显发生了变化www:19条 blog:18条 bbs:19条可以具体看索引中的数据,看看是不是对应的日志,完全正确3.4.在kibana上关联es索引库3.4.1.创建www索引库点击Managerment----索引模式—创建索引字段选择@timestamp3.4.2.创建bbs索引库操作与www的一致3.4.3.创建blog索引库操作与www的一致3.4.4.所有应用索引库都一一对应上了4.在kibana统计日志分析4.1.统计nginx01主机www应用200状态码数量筛选添加:beat.name(主机名)is(是) nginx01(主机名) 状态码(访问状态码) is(是) 200(状态码为200)4.2.统计所有节点访问状态码为200的日志只需要添加一个筛选器即可筛选添加:状态码(访问状态码) is(是) 200(状态码为200)日志也起到了聚合的作用,所有节点都可以统计
filebeat自定义索引名称环境准备1.配置filebeat使用自定义的索引名称我们配置192.168.81.220的filebeat使用自定义的索引名称1.1.配置nginx开启json格式的日志[root@node-2 ~]# vim /etc/nginx/nginx.conf http { log_format main '{"客户端内网地址":"$remote_addr",' '"时间":"$time_iso8601",' '"URL":"$request",' '"状态码":$status,' '"传输流量":$body_bytes_sent,' '"跳转来源":"$http_referer",' '"浏览器":"$http_user_agent",' '"客户端外网地址":"$http_x_forwarded_for",' '"请求响应时间":$request_time,' '"后端地址":"$upstream_addr"}'; } [root@node-2 ~]# systemctl reload nginx1.2.配置filebeat使用自定义的索引名自定义索引名主要修改output的配置,自定义索引名,必须新设置一个模板,否则会报错配置解释:output.elasticsearch:hosts: [“192.168.81.210:9200”]index: “nginx-jiangxl-access-%{+yyyy.MM}” //自定义索引名,这里配置的日期是按月进行创建索引了,也就是1个月创建一个索引,个人还是建议以天来创建索引,这样容易备份setup.template.name: “nginx” //设置一个新的模板,模板的名称setup.template.pattern: “nginx-*” //模板匹配那些索引,这里表示以nginx开头的所有的索引setup.template.enabled: false //关掉默认的模板配置setup.template.overwrite: true //开启新设置的模板1.修改配置 [root@node-2 ~]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log - /var/log/nginx/error.log json.keys_under_root: true json.overwrite_keys: true output.elasticsearch: hosts: ["192.168.81.210:9200"] index: "nginx-jiangxl-access-%{+yyyy.MM}" setup.template.name: "nginx" setup.template.pattern: "nginx-*" setup.template.enabled: false setup.template.overwrite: true 2.重启filebeat [root@node-2 ~]# systemctl restart filebeat 1.3.查看es是否增加了新的索引可以看到自定义的索引已经创建好了,但是由于我们启用了新的模板,则应用了es默认的配置,5个分片1个副本,旁边的索引使用的是默认的filebeat配置,3个分片1个副本1.4.在kibana上关联es索引点击Managerment—索引模式—创建索引索引名使用通配符的形式,这样以后索引的nginx-jiangxl开头的索引库收集来的日志可以聚合展示了,否则每个月甚至每天都需要创建索引可以看到在选择字段的时候也比原来的要少,因为是自定义的模板,因此字段只有我们定义的内容,默认的模板把所有支持的字段都会加上创建成功
filebeat将收集的日志存储在指定es索引库并在kibana上展示日志数据1.为什么要指定索引库名称由于一台机器上不止一个应用服务,比如web机器,上面一定会有tomcat、nginx、redis这种服务,如果我们不指定每个应用收集来的日志存放在es集群中的索引名的话,filebeat会将所有的日志存放在一个叫filebeat-xxx的索引库中,这样一来,我们想针对性的看某一个应用的日志将会非常困难因此就需要当filebeat收集完日志存放在es时,指定不同应用对应的不同索引名,这样就能实现tomcat在tomcat的索引库,nginx在nginx 的索引库,互不干扰2.配置文件详解filebeat.inputs: //收集什么日志 - type: log //采集类型,如果有多个应用系统则配置多个 enabled: true //是否启用,true为启用,false为不起用,启用后就会在es上创建索引库 paths: //日志所在路径 - /var/log/nginx/access.log - /var/log/nginx/error.log fields: //在es库里额外增加一个字段,也类似于标签 index: nginx //字段名:值 json.keys_under_root: true //解析json格式的日志 json.overwrite_keys: true output.elasticsearch: //日志存放在哪个es集群 hosts: ["192.168.81.210:9200"] //集群地址 indices: //索引信息 - index: "elk-nginx-%{+yyyy.MM.dd}" //索引名称 when.equals: //匹配哪个标签 fields: //配置标签类型为字段 index: "nginx" //配置指定的字段,当index字段的值为nginx则存储到elk-nginx索引中 3.filebeat配置多个应用日志收集并存放到不同的索引库3.1.修改配置文件[root@logsj ~]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log - /var/log/nginx/error.log fields: index: nginx json.keys_under_root: true json.overwrite_keys: true - type: log enabled: true paths: - /application/tomcat/logs/catalina.out fields: index: tomcat output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: - index: "elk-nginx-%{+yyyy.MM.dd}" when.equals: fields: index: "nginx" - index: "elk-tomcat-%{+yyyy.MM.dd}" when.equals: fields: index: "tomcat"3.2.重启filebeat[root@logsj ~]# systemctl restart filebeat3.3.查看es上创建的索引库已经有了tomcat索引和nginx索引,可以看到已经不是默认的3个索引了,因为我们也修改了默认的模板,只要自定义索引名,就默认启用了新的模板配置,就成了es默认的5个分片,1个副本4.在kibana上创建tomcat和nginx的索引库在kibana上创建的索引,其实就是调了es上的索引在这里填写了es索引库的名称后,会自动把匹配的索引库都列出来,所以就相当于调用了填写名称时要写通配符,比如elk-nginx-*,因为filebeat每天收集来的日志都是单独存放在不用的索引库中,比如第一天为elk-nginx-01,第二天就是elk-nginx-02,这样一来,如果写死索引名,则每天都需要新增索引库,非常麻烦,因此就填写通配符,这样就会把每天的日志都合并在一起,也可以做到不同日期进行对比查询4.1.创建elk-tomcat索引库点击Managerment—kibana一栏—索引模式名称那填写elk-tomcat-*字段选择@timestamp创建完成4.2.创建elk-nginx索引库名称那填写elk-nginx-*自动选择@timestamp4.3.创建完成5.在kibana上统计不同应用的日志5.1.统计tomcat日志点击Discovery—选择对应的tomcat索引需要统计什么就填写筛选器,如果搜索内容就在上面>_里搜5.2.统计nginx日志nginx开启了json格式的日志,因此统计的面更全
filebeat收集json格式的nginx日志1.为什么要收集json格式的日志类型由于nginx普通日志收集过来的日志内容都是存在一个字段中的值,我们想单独对日志中的某一项进行查询统计,比如我只想查看某个IP请求了我那些页面,一共访问了多少次,在普通的日志中是无法过滤的,不是很满意如下图,可以明显的看出,收集过来的日志信息都是在一块的,不能够根据某一项内容进行查询因此就需要让filebeat收集json格式日志内容,把日志内容分成不同的字段,也就是Key/value,这样我们就可以根据一个字段去统计这个字段的相关内容了我们期望日志收集过来是这个样子的$remote_addr:192.168.81.210 $remote_user:- [$time_local]:[15/Jan/2021:15:03:39 +0800] $request:GET /yem HTTP/1.1" $status:404 $body_bytes_sent:3650 $http_referer: - $http_user_agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" $http_x_forwarded_for:- 中文格式更是我们期望的客户端地址:192.168.81.210 访问时间:[15/Jan/2021:15:03:39 +0800] 请求的页面:GET /yem HTTP/1.1" 状态码:404 传输流量:3650 跳转来源: - 客户端程序:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" 客户端外网地址:- 请求响应时间:- 后端地址:-2.配置nginx支持json格式的日志输出1.修改主配置文件 [root@logsj ~]# vim /etc/nginx/nginx.conf http { log_format main '{"客户端内网地址":"$remote_addr",' '"时间":"$time_iso8601",' '"URL":"$request",' '"状态码":$status,' '"传输流量":$body_bytes_sent,' '"跳转来源":"$http_referer",' '"浏览器":"$http_user_agent",' '"客户端外网地址":"$http_x_forwarded_for",' '"请求响应时间":$request_time,' '"后端地址":"$upstream_addr"}'; } 2.重启 [root@logsj ~]# nginx -t [root@logsj ~]# systemctl reload nginx日志已经输出为json格式3.配置filebeat解析json格式的日志一定要改filebeat配置文件,使其支持json格式的日志解析,否则写入es索引库的时候还是一串字符串,无法识别每个字段的值1.1.在配置文件增加json格式解析配置 [root@logsj ~]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log - /var/log/nginx/error.log json.keys_under_root: true json.overwrite_keys: true output.elasticsearch: hosts: ["192.168.81.210:9200"] 2.重启filebeat [root@logsj ~]# systemctl restart filebeat.service 4.清空之前收集的旧格式数据一定要清空es之前收集的传统日志格式的数据,还要把nginx日志情况,如果有多台nginx服务器,则改完json格式的日志后,一定要把日志清空,否则将会在kibana中显示两种日志格式4.1.停掉filebeat停掉filebeat,不再收集日志[root@logsj ~]# systemctl stop filebeat.service4.2.删除es日志索引库kibana展示的数据都是从es库拿过来的,如果es库不删除重建的,也会是两种格式的数据4.3.删除kibana的日志索引库kibana上对应es的日志索引库也需要删除,否则新日志进来后,由于是json格式,很多字段会提示感叹号点击Managerment—索引模式—索引库—删除5.配置filebeat指定索引库名称filebeat每次自动创建的索引都是filebeat-xxx,对应我们生产环境来说不太友好,我们可以自定义索引名称1.修改配置文件 [root@logsj ~]# vim /etc/filebeat/filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log - /var/log/nginx/error.log fields: #类似于标签 index: nginx json.keys_under_root: true json.overwrite_keys: true output.elasticsearch: hosts: ["192.168.81.210:9200"] indices: #定义索引名 - index: "elk-nginx-%{+yyyy.MM.dd}" when.equals: #与那个标签关联 fields: index: "nginx" 2.重启 [root@logsj ~]# systemctl restart filebeat6.kibana创建日志索引库全部删除完成后就可以启动filebeat并在kibana上创建索引库,展示json格式的日志了刚才es上的索引库已经建立了,下面去kibana上建立同名的索引进行关联调用,也类似于软连接的效果点击Managerment—创建索引—索引名称使用通配符形式,与es上的索引进行关联填写索引名elk-nginx-*之后会列出es上elk-nginx开头的索引库并进行关联字段选择@timestamp创建完成查看json格式收集来的日志数据,已经将每一项内容变成了一个字段值便于查询7.使用kibana统计json格式的日志7.1.统计客户端地址为192.168.81.210访问了多少次页面7.1.1.找到客户端内网地址的字段点击添加找到下面的客户端内网地址的字段点击ADD即可添加7.1.2.添加一个筛选器筛选指定的客户端地址7.1.3.查看数据点击完保存后即可查询,右上角可以看到总数,中间可以看到具体的日志信息7.2.统计客户端地址为192.168.81.210访问/jiangxl页面多少次7.1.添加筛选条件1)客户端地址为192.168.81.210筛选的时候选择客户端内网地址字段,在写上匹配的值2)请求的页面为/jiangxl筛选URL字段值为/jiangxl HTTP/1.17.2.查看统计数据两个筛选器都勾选后即可字段筛选出统计数据,右上角为总数,中间为具体日志内容
1.elasticsearch备份工具介绍elasticsearch备份工具由elasticsearch-dump实现官网:https://github.com/elasticsearch-dump/elasticsearch-dump2.安装elasticsearch-dump1.下载elasticsearch-dump [root@elasticsearch ~/soft]# git clone https://github.com/taskrabbit/elasticsearch-dump 2.安装elasticsearch-dump [root@elasticsearch ~/soft]# mv elasticsearch-dump/ /data/ [root@elasticsearch ~/soft]# cd /data/elasticsearch-dump [root@elasticsearch /data/elasticsearch-dump]# npm install elasticdump -g 3.查看版本 [root@elasticsearch /data/elasticsearch-dump]# elasticdump --version 6.62.1 3.elasticsearch-dump备份实战3.1.使用elsearch-dump备份xinwen索引库到某个路径命令语法:elasticdump --input es地址/索引 --output 备份到某个路径[root@elasticsearch ~]# mkdir /data/es-backer [root@elasticsearch ~]# elasticdump --input http://192.168.81.210:9200/xinwen --output /data/es-backer/xinwen.json Thu, 14 Jan 2021 02:57:08 GMT | starting dump Thu, 14 Jan 2021 02:57:09 GMT | got 4 objects from source elasticsearch (offset: 0) Thu, 14 Jan 2021 02:57:09 GMT | sent 4 objects to destination file, wrote 4 Thu, 14 Jan 2021 02:57:09 GMT | got 0 objects from source elasticsearch (offset: 4) Thu, 14 Jan 2021 02:57:09 GMT | Total Writes: 4 Thu, 14 Jan 2021 02:57:09 GMT | dump complete 3.2.删除xinwen索引库在kibana中删除Delete xinwen 删除成功3.3.使用elasticsearch-dump还原xinwen索引库命令语法:elasticdump --input 备份文件路径 --output es地址/索引[root@elasticsearch ~]# elasticdump --input /data/es-backer/xinwen.json --output http://192.168.81.210:9200/xinwen Thu, 14 Jan 2021 03:04:45 GMT | starting dump Thu, 14 Jan 2021 03:04:45 GMT | got 4 objects from source file (offset: 0) Thu, 14 Jan 2021 03:04:50 GMT | sent 4 objects to destination elasticsearch, wrote 4 Thu, 14 Jan 2021 03:04:50 GMT | got 0 objects from source file (offset: 4) Thu, 14 Jan 2021 03:04:50 GMT | Total Writes: 4 Thu, 14 Jan 2021 03:04:50 GMT | dump complete还原xinwen索引库成功4…两个es之间进行数据迁移elasticdump --input 要迁移es1地址/索引 --output 迁移到es2地址/索引[root@elasticsearch ~]# elasticdump --input http://192.168.81.210:9200/xinwen --output http://192.168.81.220:9200/xinwen Thu, 14 Jan 2021 03:08:24 GMT | starting dump Thu, 14 Jan 2021 03:08:24 GMT | got 4 objects from source elasticsearch (offset: 0) Thu, 14 Jan 2021 03:08:32 GMT | sent 4 objects to destination elasticsearch, wrote 4 Thu, 14 Jan 2021 03:08:32 GMT | got 0 objects from source elasticsearch (offset: 4) Thu, 14 Jan 2021 03:08:32 GMT | Total Writes: 4 Thu, 14 Jan 2021 03:08:32 GMT | dump complete5.安装elasticsearch-dump报错问题排查报错内容如下[root@elasticsearch /data/elasticsearch-dump]# npm install elasticdump npm ERR! code ENOSELF npm ERR! Refusing to install package with name "elasticdump" under a package npm ERR! also called "elasticdump". Did you name your project the same npm ERR! as the dependency you're installing? npm ERR! npm ERR! For more information, see: npm ERR! <https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm> npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2021-01-13T06_36_56_956Z-debug.log 报错内容翻译如下 错误的ERR! 代码ENOSELF 错误的ERR! 拒绝在包下安装名为“webpack”的包 错误的ERR! 也被称为“webpack”。 你的项目名称是否相同? 错误的ERR! 作为您正在安装的依赖项? 错误的ERR! 错误的ERR! 有关更多信息,请参阅: 错误的ERR!<https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm> 错误的ERR! 可以在以下位置找到此运行的完整日志:错误解决根据翻译的内容提示说我们包安装名相同,elasticsearch-dump目录下有个package.json的文件,打开文件,将里面的name字段值换成和npm安装插件的名称不一致就行[root@elasticsearch /data/elasticsearch-dump]# vim package.json { "author": "Evan Tahler <evantahler@gmail.com>", "name": "elasticdump1", #随便改就行 ······ 再次致谢npm install [root@elasticsearch /data/elasticsearch-dump]# npm install elasticdump npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated s3signed@0.1.0: This module is no longer maintained. It is provided as is. npm notice created a lockfile as package-lock.json. You should commit this file. + elasticdump@6.62.1 added 114 packages from 201 contributors in 37.994s
2022年08月
2022年07月
2022年04月