MySQL选型以及使用mariadb踩过的几个坑

MySQL新版本选型

公司早期主要用mysql5.5这个版本,今年我们把数据库配置中心搭建起来,主要推的是mysql5.6这个版本,性能和功能上都有了一定的提升,mysql5.6也能支持gtid,但是无法在线在gtid模式与普通模式之间切换,同时5.6的同步性能还是无法让人满意,只能做到在多个db的情况启动并行复制,业务上很难有这样的保证,所以一旦写操作密集的业务,同步慢就会是个严重的问题;

所以,最近一直在考虑升级MySQL,升级MySQL首先面临的一个问题就是选一个合适的版本,首先我们考虑是的采用mysql5.7,5.7今年已经连续发了多个正式版本了,目前使用范围也比较广,可以考虑在正式环境使用了。于是我们进行了线上对比测试,发现mysql5.7与我们线上的mysql5.6版本的性能有较大的差距(也许还是有些参数没有调好的原因,5.7确实要复杂很多)。

与此同时,最近公司频繁出现一些日志性存储,大多数都是采用innodb引擎,容量非常浪费,另一方面由于我们公司的标准mysql服务器容量是1.3T左右,对于一些大容量需求的业务来说,容量上也存在瓶颈,如果要保留长时间的数据就难以满足需求了。所以借此机会我们打算把这块一起考虑进去,目前Percona和Mariadb都支持Tokudb,Mariadb 10.2还是10.3也准备支持Myrocks了。

于是决定对比试一下,选择了Percona 5.7.14、Mariadb 10.1.18与我们线上的MySQL 5.6进行了对比测试,经过压测。

首先是都使用Innodb引擎的情况:

Mariadb与MySQL5.6测试结果接近

Percona 5.7.14与官方MySQL5.7的性能结果差不多,比起MySQL5.6有一定的差距(去掉performance_schema好一点,但是也有差距)。

采用Tokudb引擎测试的结果与官方声称的有差距,使用snappy压缩的情况下,insert比innodb约慢1/4,update只有innodb的一半左右。Percona性能更差,就不考虑了。

最终选型Mariadb 10.1.18,并且在线上部署了一个业务,通过这个业务慢慢试用以后,逐步推广开来。

使用Mariadb踩到的一些坑

在使用Mariadb的过程中,碰到了不少问题,这里主要提一下我碰到的两个较大的问题,供大家参考:

1、同步性能问题:

我们上的这个业务高峰期达到了9000多写操作/秒,首先面临的第一个问题就是同步性能跟不上,slave同步线程数加到了16个线程,勉强能追上,但是一旦数据库从库停一会,就有可能面临永远最不上的可能。当快绝望的时候,看了一下mariadb的官方文章(https://mariadb.com/kb/en/mariadb/parallel-replication/),Mariadb的并行复制支持好几种模式,其中有in-order和out-of-order两种,不过我们这个业务支持in-order,所以没考虑out-of-order,在in-order模式下,又支持两种:Conservative 和 Optimistic,缺省情况下Conservative ,这种并行模式会严格保证事物的顺序性,估计和5.7的group commit原理差不多;而Optimistic模式下,复制的时候会尽量启动更多的会话,直到发现冲突时才会去处理冲突。果断试了一下Optimistic,非常强劲,最高同步速度达到了14000次/秒。

2、”内存泄露”

系统部署结构为:两个Mariadb做成主主复制,在前面部署了一个自己开发的分布式数据库,业务方连接到分布式数据库进程。系统上线了几天,发现主库会莫名其妙的挂掉,好在有分布式数据库,并且会自动切换,Mariadb主库挂了,会自动切到另外一个主库上,业务方没有感知。查看内核日志,发现是OOM了,内核把MySQL杀掉了。

于是开始了各种尝试,去掉Tokudb引擎配置,换Mariadb 10.1.19 ,都尝试过,最终都会发生主库挂掉的事情。一次偶然的机会,我把主库上的slave停掉了,发现主库的内存突然下降好多,并且内存不再增加了,但是一旦把主库上的slave启动就会发现,内存又逐渐身高。这种现象很像mysql线程内的内存分配机制造成的(基于mem_root的内存分配,线程停掉会全部释放),所以初步怀疑是这个原因造成的。发现作为双主中的另外一个Mariadb,就不会出现内存上涨的问题。

发现上面的现象以后,就开始代码上的调试,用gdb启动一个mariadb,另外一个用普通命令启动,这两个库做成双主:

第一种情况:测试作为从库的时候,接收到的binlog事件情况

在普通命令启动的mariadb上插入一行数据,gdb查看接收到的事件的顺序如下:

### i ) Gtid_log_event

### ii) Table_map_log_event

### iii) Write_rows_log_event

### iv) Xid_log_event

第二种情况:测试作为主库的时候,接收到的binlog事件

在gdb启动的mariadb上插入一行记录,然后gdb观察接收到的事件为:

### 1)Rotate_log_event

### 2)Gtid_list_log_event

### 3)Rotate_log_event

Rotate_log_event事件是虚拟出来的,用于让主库跟上从库的同步位置,这基本上是一个空事件,没有做任何处理,所以初步怀疑是在处理Gtid_list_log_event事件的时候,出现了问题。

反复查看Gtid_list_log_event::do_appy_event函数中的调用情况,发现确实有些方法会调用thd->alloc来分配内存,但是没有回收,所以造成内存不断的增大,我考虑了一下,因为是主库对于同步性能要求也不高,所以在Gtid_list_log_event::do_apply_event函数的最后加了一行代码:free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));  重新编译后,跑了一天,内存终于稳定了。

由于目前发现只有主库有该事件,主库同步处理性能要求不高,所以暂时先这样用着了。不知道mariadb官方版本什么时候会优化一下。

总体来看,Mariadb还是比较适合我们公司的,它有最新的功能、特性能够给我们提供很多解决方案。Tokudb可以解决日志型存储的问题;连接池可以解决大量连接情况下性能地下的问题;审计插件提供安全方面的审核;slave并发模式能够提供高性能的复制能力。除了这些常见功能以外,Mariadb还提供了Cassandra插件、图数据库插件等等,这些都给我们给业务的服务增加了想象力。

CentOS 7.x yum 方式安装 MariaDB(MySQL)

MariaDB 是 MySQL 的一个分支,采用 GPL 授权许可证,目前主要由开源社区在维护。MariaDB的目的是完全兼容MySQL,包括 API 和命令行,是之能轻松成为 MySQL 的替代品。

通过 yum 方式安装 MariaDB 非常简单,执行如下命令即可。

# yum install mariadb-server mariadb
# rpm -q mariadb mariadb-server
mariadb-5.5.56-2.el7.x86_64
mariadb-server-5.5.56-2.el7.x86_64

安装完成后,将 MariaDB 设置为开机启动,操作如下:

# systemctl enable mariadb

输出类似如下:

Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.

接着,启动 MariaDB,执行如下命令:

# systemctl start mariadb

最后,登录 MariaDB,执行如下命令:

# mysql -uroot -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or g.
Your MariaDB connection id is 2
Server version: 5.5.56-MariaDB MariaDB Server

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

MariaDB [(none)]>

从这里可以看到,在 MariaDB 中,默认的登录方式跟 MySQL 数据库一样,root 密码默认为空。
对 MariaDB 服务进行管理,可以通过 systemctl 命令实现。例如:

关闭 MariaDB 

# systemctl stop mariadb

重启 MariaDB 

# systemctl restart  mariadb

检查 MariaDB 服务运行状态

# systemctl status  mariadb

MariaDB 通过内置的安全脚本可实现对数据库的安全保护,执行“/usr/bin/mysql_secure_installation”命令,加固 MariaDB 数据库,操作过程如下:

# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):  // 这里输入目前 MariaDB 数据库的 root 密码,默认为空
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y      // 这里询问是否是之 root 密码,输入 y  给 root 用户设置一个新密码
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y  //这里询问是否删除 anonymous 用户,输入 "Y" 
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y   // 这里询问是否关闭 root 用户远程登录权限 输入 "Y"
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y  // 这里询问是否删除测试数据库及其权限 输入 "Y"
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y   // 这里询问是否重新载入授权表 输入 "Y"
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

至此,MariaDB 数据库安转完成了。

CentOS7 平滑升级 MariaDB 5.5 到 10.x 新版本实践

1. 前言

自从 CentOS 7 开始,自带的数据库就变成 MariaDB 了,yum 安装之后的默认版本是 5.5,但是这个数据版本已经比较老了,无论是安装全新的 Percona 还是升级 MariaDB 第一步始终是不要忘记备份。

2. 备份数据库

重要的事情说三遍,备份,备份,备份

# 备份数据库,如果升级顺利是不要实施备份还原的 
mysqldump -u root -p --all-databases > alldb.sql
# 如果想保留自己的 my.cof 配置,则备份一下这个文件 
cp /etc/my.cnf /etc/my.cnf.bak
# 停止数据库运行 
systemctl stop mariadb
# 卸载 MariaDB 老版本 
yum remove mariadb mariadb-server

3. 添加 MariaDB Yum 库

建议使用 MariaDB 官方推荐的 stable 稳定版,

https://downloads.mariadb.org/mariadb/
http://yum.mariadb.org/

# 添加 MariaDB 官方源 
vi /etc/yum.repos.d/MariaDB.repo

# MariaDB 10.3 CentOS repository list
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

# 清除 yum 缓存 
yum clean all 
yum makecache

4. 升级已有数据库

# 安装 MariaDB 新版本 
yum install mariadb mariadb-server

# 启动新版 MariaDB
systemctl start mariadb

# 升级已有数据库 
mysql_upgrade -uroot -p 

[root@sg-gop-10-71-12-89 tmp]# mysql_upgrade -uroot -p
Enter password:
Phase 1/7: Checking and upgrading mysql database
Processing databases
mysql
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.event                                        OK
mysql.func                                         OK
mysql.help_category                                OK
mysql.help_keyword                                 OK
mysql.help_relation                                OK
mysql.help_topic                                   OK
mysql.host                                         OK
mysql.ndb_binlog_index                             OK
mysql.plugin                                       OK
mysql.proc                                         OK
mysql.procs_priv                                   OK
mysql.proxies_priv                                 OK
mysql.servers                                      OK
mysql.tables_priv                                  OK
mysql.time_zone                                    OK
mysql.time_zone_leap_second                        OK
mysql.time_zone_name                               OK
mysql.time_zone_transition                         OK
mysql.time_zone_transition_type                    OK
mysql.user                                         OK
Upgrading from a version before MariaDB-10.1
Phase 2/7: Installing used storage engines
Checking for tables with unknown storage engine
Phase 3/7: Fixing views
Phase 4/7: Running 'mysql_fix_privilege_tables'
Phase 5/7: Fixing table and database names
Phase 6/7: Checking and upgrading tables
Processing databases
information_schema
performance_schema
zabbix
zabbix.acknowledges                                OK
zabbix.actions                                     OK
zabbix.alerts                                      OK
zabbix.application_discovery                       OK
zabbix.application_prototype                       OK
zabbix.application_template                        OK
zabbix.applications                                OK
zabbix.auditlog                                    OK
zabbix.auditlog_details                            OK
zabbix.autoreg_host                                OK
zabbix.conditions                                  OK
zabbix.config                                      OK
zabbix.corr_condition                              OK
zabbix.corr_condition_group                        OK
zabbix.corr_condition_tag                          OK
zabbix.corr_condition_tagpair                      OK
zabbix.corr_condition_tagvalue                     OK
zabbix.corr_operation                              OK
zabbix.correlation                                 OK
zabbix.dashboard                                   OK
zabbix.dashboard_user                              OK
zabbix.dashboard_usrgrp                            OK
zabbix.dbversion                                   OK
zabbix.dchecks                                     OK
zabbix.dhosts                                      OK
zabbix.drules                                      OK
zabbix.dservices                                   OK
zabbix.escalations                                 OK
zabbix.event_recovery                              OK
zabbix.event_suppress                              OK
zabbix.event_tag                                   OK
zabbix.events                                      OK
zabbix.expressions                                 OK
zabbix.functions                                   OK
zabbix.globalmacro                                 OK
zabbix.globalvars                                  OK
zabbix.graph_discovery                             OK
zabbix.graph_theme                                 OK
zabbix.graphs                                      OK
zabbix.graphs_items                                OK
zabbix.group_discovery                             OK
zabbix.group_prototype                             OK
zabbix.history                                     OK
zabbix.history_log                                 OK
zabbix.history_str                                 OK
zabbix.history_text                                OK
zabbix.history_uint                                OK
zabbix.host_discovery                              OK
zabbix.host_inventory                              OK
zabbix.hostmacro                                   OK
zabbix.hosts                                       OK
zabbix.hosts_groups                                OK
zabbix.hosts_templates                             OK
zabbix.housekeeper                                 OK
zabbix.hstgrp                                      OK
zabbix.httpstep                                    OK
zabbix.httpstep_field                              OK
zabbix.httpstepitem                                OK
zabbix.httptest                                    OK
zabbix.httptest_field                              OK
zabbix.httptestitem                                OK
zabbix.icon_map                                    OK
zabbix.icon_mapping                                OK
zabbix.ids                                         OK
zabbix.images                                      OK
zabbix.interface                                   OK
zabbix.interface_discovery                         OK
zabbix.item_application_prototype                  OK
zabbix.item_condition                              OK
zabbix.item_discovery                              OK
zabbix.item_preproc                                OK
zabbix.items                                       OK
zabbix.items_applications                          OK
zabbix.maintenance_tag                             OK
zabbix.maintenances                                OK
zabbix.maintenances_groups                         OK
zabbix.maintenances_hosts                          OK
zabbix.maintenances_windows                        OK
zabbix.mappings                                    OK
zabbix.media                                       OK
zabbix.media_type                                  OK
zabbix.opcommand                                   OK
zabbix.opcommand_grp                               OK
zabbix.opcommand_hst                               OK
zabbix.opconditions                                OK
zabbix.operations                                  OK
zabbix.opgroup                                     OK
zabbix.opinventory                                 OK
zabbix.opmessage                                   OK
zabbix.opmessage_grp                               OK
zabbix.opmessage_usr                               OK
zabbix.optemplate                                  OK
zabbix.problem                                     OK
zabbix.problem_tag                                 OK
zabbix.profiles                                    OK
zabbix.proxy_autoreg_host                          OK
zabbix.proxy_dhistory                              OK
zabbix.proxy_history                               OK
zabbix.regexps                                     OK
zabbix.rights                                      OK
zabbix.screen_user                                 OK
zabbix.screen_usrgrp                               OK
zabbix.screens                                     OK
zabbix.screens_items                               OK
zabbix.scripts                                     OK
zabbix.service_alarms                              OK
zabbix.services                                    OK
zabbix.services_links                              OK
zabbix.services_times                              OK
zabbix.sessions                                    OK
zabbix.slides                                      OK
zabbix.slideshow_user                              OK
zabbix.slideshow_usrgrp                            OK
zabbix.slideshows                                  OK
zabbix.sysmap_element_trigger                      OK
zabbix.sysmap_element_url                          OK
zabbix.sysmap_shape                                OK
zabbix.sysmap_url                                  OK
zabbix.sysmap_user                                 OK
zabbix.sysmap_usrgrp                               OK
zabbix.sysmaps                                     OK
zabbix.sysmaps_elements                            OK
zabbix.sysmaps_link_triggers                       OK
zabbix.sysmaps_links                               OK
zabbix.tag_filter                                  OK
zabbix.task                                        OK
zabbix.task_acknowledge                            OK
zabbix.task_check_now                              OK
zabbix.task_close_problem                          OK
zabbix.task_remote_command                         OK
zabbix.task_remote_command_result                  OK
zabbix.timeperiods                                 OK
zabbix.trends                                      OK
zabbix.trends_uint                                 OK
zabbix.trigger_depends                             OK
zabbix.trigger_discovery                           OK
zabbix.trigger_tag                                 OK
zabbix.triggers                                    OK
zabbix.users                                       OK
zabbix.users_groups                                OK
zabbix.usrgrp                                      OK
zabbix.valuemaps                                   OK
zabbix.widget                                      OK
zabbix.widget_field                                OK
Phase 7/7: Running 'FLUSH PRIVILEGES'
OK

# 配置服务自启动 
systemctl enable mariadb

# 登录数据库验证 
mysql -uroot -p

# 升级过程遇到错误记得先查看日志分析 

5. MariaDB 官方升级文档

Upgrading from MariaDB 5.5 to MariaDB 10.0

https://mariadb.com/kb/en/library/upgrading-from-mariadb-55-to-mariadb-100/

Linux Nginx LVS HAproxy 负载均衡功能对比

Nginx:

  1. 工作在网络7层,可以针对http应用做一些分流的策略,比如针对域名,目录结构
  2. Nginx对网络的依赖较小,理论上能ping通就能进行敷在功能
  3. Nginx安装配置比较简单,测试起来很方便
  4. 也可以承担较高的负载压力且稳定,Nginx是为了解决c10k问题而诞生的
  5. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测
  6. Nginx对请求的异步处理可以帮助节点服务器减轻负载压力
  7. Nginx仅能支持http、https和Email协议,这样就在适用范围较小
  8. 不支持Session的直接保持,但能通过ip_hash来解决,对Bigrequestheader的支持不是很好
  9. Nginx还能做Web服务器即Cache功能。

LVS:

  1. 抗负载能力强,性能高,能达到F5的60%,对内存和cpu资源消耗比较低
  2. 工作在网络4层,通过VRRP协议(仅做代理使用),具体的流量是由liunx内核来处理,因此没有流量的产生。
  3. 稳定,可靠性强,自身有完美的热备方案(Keepalived+LVS)
  4. 不支持正则处理,不能做动静分离
  5. 支持多种负载均衡算法:rr(轮询),wrr(带权轮询)、lc(最小连接)、wlc(带权最小连接)
  6. 配置相对复杂,对网络依赖比较大,稳定性很高。

LVS工作模式有4种:

  • nat地址转换
  • dr直接路由
  • tun隧道
  • full-nat

HAproxy:

  1. 支持两种代理模式:TCP(四层)和HTTP(七层),支持虚拟主机
  2. 能够补充Nginx的一些缺点比如Session的保持,Cookie引导等工作
  3. 支持url检测后端的服务器出问题的检测会有很好的帮助。
  4. 更多负载均衡策略比如:动态加权轮循,加权源地址哈希,加权URL哈希加权等参数哈希已经实现。
  5. 单纯从效率上来讲HAproxy更会比Nginx有更出色的负载均衡
  6. HAproxy可以对MYsql进行负载均衡,对后端的DB节点进行检测和负载均衡
  7. 支持负载均衡算法:轮循、带权轮循、源地址保持、请求URL、根据Cookie
  8. 不能做Web服务器即Cache。

三大主流软件负载均衡器适用的生产场景:

  1. 网站建设初期,可以选用Nginx、HAproxy作为反向代理负载均衡(流量不大时可以选择不用负载均衡)因为其配置简单,性能也能满足一般业务场景。如果考虑到负载均衡器是有单点失败问题,可以采用Nginx+Keepalived避免负载均衡器自身单点问题。
  2. 网站并发达到一定程度后,为了提高稳定性和转发效率,可以使用LVS,毕竟LVS比Nginx/HAproxy要更稳定,转发效率也高。

lvs工作模式和工作原理

一、lVS基本介绍

LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器。也是国人章文嵩博士发起的一个开源项目,现在LVS已经是Linux内核标准的一部分。利用LVS技术可以实现高性能,高可压缩的网络服务,例如www服务,FTP服务,MAIL服务等。

二、LVS的体系架构

使用LVS架设的服务器集群系统有三个部分组成:最前端的负载均衡层(Loader Balancer),中间的服务器群组层,用Server Array 表示,最底层的数据共享存储层,用Shared Storage表示。在用户看来所有的应用都是透明的,用户只是在使用一个虚拟服务器提供的高性能服务。

1、LVS的体系架构如图

未分类

2、LVS的各个层次的详细介绍

Load Balancer层:位于整个集群系统的最前端,有一台或者多台负载调度器(Director Server)组成,LVS模块就安装在Director Server 上,而Director 的主要作用类似于一个路由器,它含有完成LVS功能所设定的路由表,通过这些路由表把用户的请求分发给Server Array层的应用服务器上。同时,在Director Server上还要安装对Real Server服务的监控模块Ldirectord,此模块用于监测各个Real Server服务的健康状况。在Real Server不可用时把它从LVS路由表中剔除,恢复时加入。

Server Array层:由一组实际运行应用服务的机器组成,Real Server可以是WEB服务器、MAIL服务器、FTP服务器、DNS服务器、时评服务器中的一个或多个,每个Real Server之间通过高速的LAN或分布在各地的wan相连接。在实际的应用中,Director Server也可以同时兼任Real Server的角色。

Shared Storage层:是为所有Real Server提供共享存储空间和内容一致性的存储区域,在物理上,一般有磁盘阵列设备组成,为了提供内容的一致性,一般可以通过NFS网络文件系统共享数据,但是NFS在繁忙的业务系统中,性能并不是很好,此时可以采用集群文件系统。

从整个LVS结构可以看出,Director Server是整个LVS的核心,对于Real Server,可以是所有的系统平台,Linux、windows、Solaris、AIX、BSD系列都能很好的支持。

三、LVS集群

1、十种调度算法

(1)静态

  • rr 轮循调度 (Round-Robin Scheduling)

  • wrr 加权轮循调度 (Weighted Round-Robin Scheduling)

  • sh 源地址散列调度 (Source Hashing Scheduling)

  • dh 目的地址散列调度 (Destination Hashing Scheduling)

(2)动态

  • lc 最小连接调度 (Least-Connection Scheduling)

  • wlc 加权最小连接调度 (Weighted Least-Connection Scheduling)

  • sed 最短预期延时调度 (Shortest Expected Delay Scheduling)

  • nq 不排队调度 (Never Queue Scheduling)

  • lblc 基于局部性的最少连接调度 (Locality-Based Least Connections Scheduling)

  • lblcr 带复制的基于局部性的最少连接调度 (Locality-Based Least Connections with Replication Scheduling)

2、三种IP负载均衡技术

(1)IPVS/NAT

网络结构图:

未分类

负载均衡内核空间原理图

未分类

IPVS/NAT模式的基本原理

首先CIP发送请求package给VIP,VIP收到package后,会根据LVS设置的LB算法选择一个合适的RS?然后把package的目标IP修改为RIP,RIP收到这个package后判断目标ip为自己,就处理这个package,处理完后把这个包发送给LVS VIP,LVS 收到这个package 后把sorce ip改成VIP的IP,dst ip改成 CIP,然后发给CIP。其中的转换我们可以这样理解:所有发送到VIP的数据包全部转换为RIP的地址以及对应端口。IPVS/NAT模式优缺点

优点:

  • 容易配置,容易理解,容易管理的工作模式
  • 节省外网IP资源,LVS-NAT工作方式将系统架构封装在局域网中,只需要LVS有一个外网地址或外网地址映射就可实现访问
  • 系统架构相对封闭,内网环境下防火墙的设置要求不会太高,容易进行物理服务器的运维
  • LVS/NAT工作模式下的RS服务器可以是任何操作系统,只要支持TCP/IP协议即可

缺点:

  • LVS-NAT中,负载均衡调度器作为转发点,当RS服务器数量变多时,调度器将会负载,转发点也是瓶颈点

(2)IPVS/DR

网络结构图

未分类

IPVS/DR模式的基本原理

LVS节点接收到请求报文后,会改写报文的数据链路层格式。将VIP MAC写成RIP的Mac,但是网络层和传输层报文不会改写,然后重新回发给交换机。这里就涉及一个问题,现在RIP和 IP的对应关系的错误的,这个数据报文到了交换机后,由于这种错位的关系,是不能进行三层交换的,只能进行二层交换(一旦进行IP交换,数据报文的验证就会出错,被丢弃)。所以LVS-DR方式要求Real Server和LVS节点必须在同一个局域网内,或者这样说更确切:LVS节点需要找到一个二层链路,将改写了Mac地址的报文发送给Real Server,而不能进行三层交换的校验。

简单来说就是CIP发送一个PV请求给VIP,VIP收到这个请求后会跟LVS设置的LB算法选择一个LB比较合理的realserver,然后将此请求的package的MAC地址修改为realserver的MAC地址;VIP会把这个包广播到当前这个LAN里面,所以,要提前保证VIP和所有的realserver在同一个网段

IPVS/DR 模式的优缺点

优点

  • 解决了LVS-NAT工作模式中的转发瓶颈问题,能够支撑规模更大的负载均衡场
  • 比较耗费网外IP资源,机房的外网IP资源都是有限的,如果在正式生产环境中确实存在这个问题,可以采用LVS-NAT和LVS-DR混合使用的方式来缓解

缺点

  • 配置工作较LVS-NAT方式稍微麻烦一点,您至少需要了解LVS-DR模式的基本工作方式才能更好的指导自己进行LVS-DR模式的配置和运行过程中问题的解决
  • 由于LVS-DR模式的报文改写规则,导致LVS节点和Real Server节点必须在一个网段,因为二层交换是没法跨子网的。但是这个问题针对大多数系统架构方案来说,实际上并没有本质限制

(3)IPVS/TUN

首先这里需要理解以下关于IP隧道的概念

将一个完整的IP报文封装成另一个新的IP报文的数据部分,并通过路由器传送到指定的地点。在这个过程中路由器并不在意被封装的原始协议的内容。到达目的地点后,由目的地方依靠自己的计算能力和对IP隧道协议的支持,打开封装协议,取得原始协议。如图:

未分类

其实数据转发原理和DR是一样的,不过这个我个人认为主要是位于不同位置(不同机房);LB是通过隧道进行了信息传输,虽然增加了负载,可是因为地理位置不同的优势,还是可以参考的一种方案;

优点

  • 负载均衡器只负责将请求包分发给物理服务器,而物理服务器将应答包直接发给用户。所以,负载均衡器能处理很巨大的请求量,这种方式,一台负载均衡能为超过100台的物理服务器服务,负载均衡器不再是系统的瓶颈。使用VS-TUN方式,如果你的负载均衡器拥有100M的全双工网卡的话,就能使得整个Virtual Server能达到1G的吞吐量。

缺点

  • 这种方式需要所有的服务器支持”IP Tunneling”(IP Encapsulation)协议;

Linux LVM2 磁盘管理及 LUKS 加密

LVM 是 Logical Volume Manager (逻辑卷管理)的简写,它由 Heinz Mauelshagen 在 Linux 2.4 内核上实现。 LVM 将一个或多个硬盘的分区在逻辑上集合,相当于一个大硬盘 来使用,当硬盘的空间不够使用的时候,可以继续将其它的硬盘的分区加入其中,这样可 以实现磁盘空间的动态管理,相对于普通的磁盘分区有很大的灵活性。

1、LVM 磁盘管理

1.1 术语

  • 物理卷
    Physical Volume(PV), 即物理的磁盘分区

  • 卷组
    Volume Group(VG), LVM中的物理的磁盘分区,也就是PV,必须加入VG,可以将VG理解 为一个仓库或者是几个大的硬盘。

  • 逻辑卷
    Logical Volume(LV), 也就是从VG中划分的逻辑分区

1.2 磁盘管理

1.2.1 物理卷(PV)操作

创建PV:

pvcreate /dev/sda /dev/sdb1

查看PV:

pvscan

1.2.2 卷组(VG)操作

VG是由各个PV组成的,创建VG:

vgcreate VolGroup /dev/sda /dev/sdb1

VolGroup 是VG名,后面两个设备是加入到 VolGroup 卷组的设备。

查看VG:

vgdisplay

增加VG的设备成员:

vgextend VolGroup /dev/sda3

1.2.3 逻辑卷(LV)操作

LV是在VG上面划分出来的。创建LV:

lvcreate -n osd -L 200G VolGroup

或:

lvcreate -n test -l 50 vg0

从卷组 VolGroup 中创建逻辑卷 osd, 用 -L 指定大小为200G,或用 -l 指 定大小为50个PE(Physical Extents,默认是4MB)

查看LV:

lvdisplay

改变LV大小:

lvresize -L +200G /dev/VolGroup/osd

该命令把 osd 逻辑卷增大了200G,类似的,如果要减小大小200G,用 -200G 即 可。逻辑卷的是从卷组划分来的,其大小当然不能比所在卷组的空间大。

1.2.4 改变 Ext2/3/4 文件系统大小

resize2fs /dev/dnfs/osd

这样会改变 osd 逻辑卷上的Ext3文件系统的大小到 osd 逻辑卷的总大小, resize2fs 也可以指定大小,更多用法,请 man resize2fs. resize2fs 支 持在线改变Ext3文件系统大小,不需卸载即可调整大小。

1.2.5 删除操作

如果不想用逻辑卷管理器了,可以从LV,VG到PV逐层删除:

lvremove /dev/dnfs/osd

把 dnfs 转为休眠状态:

vgchange -an dnfs
lvremove dnfs
pvremove /dev/sda

1.2.6 缩小分区大小

第一步, 先卸载分区

第二步, 强制检查文件系统的正确性:

e2fsck -f /dev/VolGroup/osd

第三步, 缩小文件系统的大小:

resize2fs /dev/VolGroup/osd 1G

即缩小文件系统大小到 1G.

第四步, 缩小逻辑卷的大小:

lvresize -L 1G /dev/VolGroup/osd

即缩小逻辑卷大小到 1G, 这里使用了绝对容量单位.

2、LUKS 磁盘加密

2.1 概念

LUKS(Linux Unified Key Setup) 为 Linux 硬盘加密提供了一种标准,它不仅能通用于不 同的 Linux 发行版本,还支持多用户/口令。因为它的加密密钥独立于口令,所以如果口 令失密,我们可以迅速改变口令而无需重新加密真个硬盘。通过提供一个标准的磁盘上的 格式,它不仅方便之间分布的兼容性,而且还提供了多个用户密码的安全管理。必须首先 对加密的卷进行解密,才能挂载其中的文件系统。

工具: cryptsetup (默认已经安装)

常用参数: luksFormat, luksOpen, luksClose, luksAddKey

使用 cryptsetup 对分区进行了加密后,这个分区就不再允许直接挂载。 LUKS 也是一种 基于device mapper 机制的加密方案。如果要使用这个分区,必须对这个分区做一个映射 ,映射到 /dev/mapper 这个目录里去,我们只能挂载这个映射才能使用。然而做映射 的时候是需要输入解密密码的。

Crypsetup 工具加密的特点:

  • 加密后不能直接挂载
  • 加密后硬盘丢失也不用担心数据被盗
  • 加密后必须做映射才能挂载

步骤:

  1. 创建分区并加密分区
  2. 映射分区
  3. 格式化分区并挂载使用
  4. 关闭映射分区

2.2 基本操作

Centos 6.x 上默认的卷组名称是 VolGroup.

创建一个LV:

lvcreate -n jiami -L 1G VolGroup

对LV进行加密:

cryptsetup luksFormat /dev/mapper/VolGroup-jiami

格式化时需要输入密码, 这个密码输入之后是不可更改的.

格式化之后, 我们需要先打开它, 然后才可以执行相关的操作(比如格式化, 挂载):

cryptsetup luksOpen /dev/mapper/VolGroup-jiami jiami

jiami 是解锁之后映射的设备名称, 比如 /dev/mapper/jiami.

下面执行格式化:

mkfs.ext4 /dev/mapper/jiami

之后就可以像正常分区一样操作

2.3 自动挂载

第1步:创建随机密钥文件

sudo dd if=/dev/urandom of=/root/keyfile bs=1024 count=4

第2步:将密钥文件设为只读为root

sudo chmod 0400 /root/keyfile

第3步:将密钥文件添加到LUKS

sudo cryptsetup luksAddKey /dev/mapper/VolGroup-jiami /root/keyfile

第4步:创建一个映射器

sudo nano /etc/crypttab

并添加一个新的条目

jiami      /dev/mapper/VolGroup-jiami  /root/keyfile  luks

或者您可以使用设备的UUID。

步骤5:将设备安装在fstab中

sudo nano /etc/fstab

并添加一个新的条目

/dev/mapper/jiami  /media/jiami     ext4    defaults        0       2

0表示不自检; 1或2表示需要自检, 根分区设为1, 其他分区只能是2.

第6步:重新启动或重新安装

sudo mount -a

2.4 更改分区大小

2.4.1 调整LUKS加密LVM分区的大小

我最近不得不调整我们在安全的FTP服务器上使用的分区。幸运的是,我们在所有机器上使用LVM,因此这是一项简单的任务。我唯一担心的是它是一个LUKS加密分区,我担心由于加密算法和密钥根据新的大小而改变,我会丢失数据。在搜索之后,以下是我提出的调整LUKS分区大小而不丢失任何数据的步骤:

假设和开始信息:

  • 我们有一个名为encrypted的LUKS文件系统,它位于名为encrypted_LV的逻辑卷上
  • 该encypted_LV属于一个名为卷组root_VG
  • 我们将此文件系统安装在/ secret
  • 我们使用ext3作为底层文件系统
  • 我们希望通过从root_VG卷组添加20 Gig来扩展卷(它已作为可用空间提供)。

步骤1.卸载文件系统

umount /secret

步骤2.运行文件系统检查以清理inode表,然后再使用它

fsck.ext3 -C 0 -f /dev/mapper/encrypted

步骤3.关闭LUKS文件系统

cryptsetup luksClose encrypted

步骤4.像扩展任何其他LVM一样扩展逻辑卷(我们正在添加额外的20G空间)

lvextend -L +20G /dev/root_VG/encrypted_LV

步骤5.重新打开加密文件系统并调整其大小

cryptsetup luksOpen /dev/root_VG/encrypted_LV encrypted
cryptsetup --verbose resize myfs

步骤6.再次FSCK(为了测量好)然后调整底层文件系统的大小(本例中为ext3)

fsck.ext3 -f /dev/mapper/encrypted
resize2fs /dev/mapper/encrypted

步骤7.安装新大小的LUKS文件系统并确保一切正常

mount /dev/mapper/encrypted /secret

2.4.2在LVM上调整LUKS上的ext4大小

下一个比较棘手,因为LVM不会自动支持调整大小。

步骤1.调整逻辑卷的大小

lvextend -L +50G /dev/VG-0/LV-1

步骤2.打开LUKS卷

cryptsetup luksOpen /dev/VG-0/LV-1 crypt_LV-1

步骤3.调整内部文件系统的大小(扩展到适合空间)

e2fsck -f /dev/mapper/crypt_LV-1
resize2fs /dev/mapper/crypt_LV-1

(e2fsck是一个很好的做法,无论如何都是由resize2fs强制实施的。)

centos系统LVM逻辑卷如何使用调整

首先需要了解几个概念

  • PE (Physical Extend)  物理拓展
  • PV (Physical Volume)  物理卷
  • VG (Volume Group)  卷组
  • LV (Logical Volume)  逻辑卷

未分类

首先使用fdisk -l 查看硬盘状态,这次我们使用的是2块新硬盘sdb 和 sdc

未分类

接着使用fdisk /dev/sdb 对第一块硬盘进行分区

选择p显示分区状态,选择n进行分区,选择t进行标记 lvm的标记为8e,最后使用w保存分区信息。

未分类

接着就需要创建物理卷,也就是PV。

使用pvcreate /dev/sdb1 命令创建

使用pvs 命令查看 (pvdisplay查看详细)

未分类

可以看到系统中增加了sdb1的pv,大小为5G 未使用5G

接着创建卷组,也就是VG

使用vgcreate work /dev/sdb1 命令创建work卷组,同时将/dev/sdb1 加入进来。

使用vgs命令查看 (vgdisplay查看详细)

未分类

其中cl组是系统原有的,这次新的work组已经建立,大小5G,未使用5G

然后我们需要从VG上创建出逻辑卷,也就是LV

使用lvcreate -L 500M -n lv1 work 命令来从work卷组中分配500M大小,用于创建lv1的逻辑卷

用lvs可以查看

未分类

可以看到新的lv1逻辑卷已经建立。这个时候使用vgs查看会发现work组未使用空间只有4.5G了

随后我们需要在LV上建立文件系统,使用mkfs.ext4 /dev/work/lv1 命令创建ext4文件系统

未分类

最后就是需要挂载到相应的目录上了,使用mount /dev/work/lv1 /data 命令来挂载到/data目录

如果需要系统一启动就自动挂载,需要修改/etc/fstab 其中UUID可以使用blkid命令查询

未分类

未分类

第一步我们完成了,将一块新硬盘设置了LVM逻辑卷挂在到了一个目录(/data)下面。

未分类

那如果/data经过一段时间使用,剩余空间不足怎么办?这就需要我们来扩充lv1这个逻辑卷。

使用 lvextend -L +500M /dev/work/lv1 来增加500M空间,给逻辑卷增加空间不会影响文件系统,所以不需要卸载文件系统。

未分类

可以看到 /data目录已经进行了扩容,lv1逻辑卷扩容前后也发生了变化。需要记得使用resize2fs /dev/work/lv1 来同步文件系统

于是我们可以继续使用/data目录了,但当卷组不够用了怎么办?这就需要我们扩容了。

未分类

可以看到此时work卷组几乎没有未使用空间了,我们通过之前的方法把另外一块硬盘也创建PV 。过程就省略了,使用pvs查看新的sdc1分区已经创建了PV

未分类

使用vgextend work /dev/sdc1 命令将sdc1也加入到work卷组中来。使用vgs查看效果

未分类

发现work卷组变大了,有5G空间未使用,接着重复上述操作将它分配给lv1即可。

未分类

突然有一天,我们发现给/data(lv1)分配的空间用不掉,但其他地方缺少空间怎么办?

首先卸载目录/data

然后通过e2fsck -f /dev/mapper/work-lv1命令检测逻辑卷上的空余空间

未分类

使用resize2fs /dev/mapper/work-lv1 700M 将文件系统减少到700M

未分类

使用 lvreduce -L 700M /dev/work/lv1 使lv1卷缩小到700M

未分类

使用vgs发现work卷组未使用空间变大了。接着可以分给其他逻辑卷,这里就不再重复说明了。

至此,基础的LVM操作都涉及到了。但是使用虚拟机的时候,会发生另外一种情况,就是我们的sdb硬盘是可以修改变大的。这本身没有太大区别,当硬盘变大时,使用fdisk继续分区,然后依次创建pv、加入vg、分配给lv就可以了。

linux系统lvm中lv使用空间的调整

前言:最近部署一个项目,甲方使用虚拟化平台,给的服务器都是虚拟化克隆的机器,操作系统安装时默认的分区,现状是根分区只有50G,部署的时候使用软连接创建的部署目录,但是后续升级的同事没有注意,就把部署直接放在根分区,导致近期数据同步时log文件大,使用的log日志删除脚本任务计划未到执行执行时间服务日志文件就把磁盘占满了,处理如下。

一、系统环境

  • 操作系统:Centos_x64 6.5
  • 内核版本:2.6.32-431.el6.X86_64
  • 磁盘格式:EXT4

二、现有分区情况与说明

df -h    #查看当前分区
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root   50G   17G   31G  36% /
tmpfs                         7.8G     0  7.8G   0% /dev/shm
/dev/sda1                     485M   33M  427M   8% /boot
/dev/mapper/VolGroup-lv_home  435G  9.7G  404G   3% /home

说明:可以清楚的看到两个lv卷的分区VolGroup-lv_root挂载为了根分区50G,VolGroup-lv_home挂载为了/home分区,home分区比较大,却没有被使用。

三、释放/home分区的占用并卸载/home分区

1、以为使用fuser -m /home就可以完成但是执行后卸载仍提示/home有占用。情况如下:

# fuser -m /home
/home:               24033ce
# umount /home
umount: /home: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))

2、检查占用的文件,发现甲方提供的系统里有金山的防护软件,将软件进程杀掉后卸载/home分区正常:

# lsof | grep /home          --检查发现占用的是金山的防护软件直接运行了kiil -9 24033
KANLinuxC 24033          root  cwd       DIR              253,2      4096    5636103 /home/kingsoft/kavnet
KANLinuxC 24033          root  txt       REG              253,2   1645332    5636130 /home/kingsoft/kavnet/KANMainModule
KANLinuxC 24033          root  mem       REG              253,2   1369600    5636263 /home/kingsoft/kavnet/libcrypto.so.6
KANLinuxC 24033          root  mem       REG              253,2    323320    5636276 /home/kingsoft/kavnet/libssl.so.6
KANLinuxC 24033          root  mem       REG              253,2     34487    5636129 /home/kingsoft/kavnet/KANLocalComm.so
KANLinuxC 24033          root  mem       REG              253,2    626402    5636131 /home/kingsoft/kavnet/KANNetComm.so
KANLinuxC 24033          root  mem       REG              253,2    163342    5636265 /home/kingsoft/kavnet/libjson.so
KANLinuxC 24033          root    3w      REG              253,2    789537    5636280 /home/kingsoft/kavnet/neterror.log
KANLinuxC 24033          root   10w      REG              253,2    789537    5636280 /home/kingsoft/kavnet/neterror.log
KANLinuxC 24033          root   11w      REG              253,2    789537    5636280 /home/kingsoft/kavnet/neterror.log
KANLinuxC 24033          root   13w      REG              253,2    789537    5636280 /home/kingsoft/kavnet/neterror.log
KANLinuxC 24033          root   20w      REG              253,2    789537    5636280 /home/kingsoft/kavnet/neterror.log
# umount /home          --重新卸载未在报错
未在报错。

三、缩减VolGroup-lv_home这个LV的空间

1、检查这个LV分区的信息是否正常;

# e2fsck -f /dev/mapper/VolGroup-lv_home
e2fsck 1.41.12 (17-May-2010)
第一步: 检查inode,块,和大小
第二步: 检查目录结构
第3步: 检查目录连接性
Pass 4: Checking reference counts
第5步: 检查簇概要信息
/dev/mapper/VolGroup-lv_home: 5779/28950528 files (2.2% non-contiguous), 4334183/115775488 blocks

2、调整VolGroup-lv_home分区大小;

#resize2fs -p /dev/mapper/VolGroup-lv_home 80G
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/mapper/VolGroup-lv_home to 20971520 (4k) blocks.
Begin pass 2 (max = 50904)
正在重定位块            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 3534)
正在扫描inode表          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 838)
正在更新inode引用       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/mapper/VolGroup-lv_home is now 20971520 blocks long.

3、重新挂载home分区并检查空间大小,可以发现/home的空间已经变小;

# mount /home
# df -h
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root   50G   17G   31G  36% /
tmpfs                         7.8G     0  7.8G   0% /dev/shm
/dev/sda1                     485M   33M  427M   8% /boot
/dev/mapper/VolGroup-lv_home   79G  9.6G   66G  13% /home

4、将VolGroup-lv_home缩减出来的分区设置为空闲分区;

# lvreduce -L 80G /dev/mapper/VolGroup-lv_home
  WARNING: Reducing active and open logical volume to 80.00 GiB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv_home? [y/n]: y
  Reducing logical volume lv_home to 80.00 GiB
  Logical volume lv_home successfully resized

5、检查空闲出的空间Free PE已经空出了361G;

# vgdisplay 
  --- Volume group ---
  VG Name               VolGroup
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               499.51 GiB
  PE Size               4.00 MiB
  Total PE              127874
  Alloc PE / Size       35292 / 137.86 GiB
  Free  PE / Size       92582 / 361.65 GiB
  VG UUID               Ur7bJ4-hQKi-xx4R-f9Qt-INvG-fjBf-zcvJ4n

四、将缩减出的空间增加给VolGroup-lv_root这个LV

1、给VolGroup-lv_root增加空间;

# lvresize --size +361G /dev/VolGroup/lv_root 
  Extending logical volume lv_root to 410.71 GiB
  Logical volume lv_root successfully resized

2、让系统重新识别VolGroup-lv_root增加的空间;

# resize2fs -p /dev/mapper/VolGroup-lv_root
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/mapper/VolGroup-lv_root is mounted on /; on-line resizing required
old desc_blocks = 4, new_desc_blocks = 26
Performing an on-line resize of /dev/mapper/VolGroup-lv_root to 107665408 (4k) blocks.
The filesystem on /dev/mapper/VolGroup-lv_root is now 107665408 blocks long.

3、检查最终结果,确认操作成功;

# df -h
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root  405G   23G  362G   6% /
tmpfs                         7.8G     0  7.8G   0% /dev/shm
/dev/sda1                     485M   33M  427M   8% /boot
/dev/mapper/VolGroup-lv_home   79G  3.5G   72G   5% /home

nginx 日志切割的三种方法(logrotate切割、shell脚本切割、Python脚本切割)

nginx 日志切割

PS:nginx日志切割可以通过两种方式进行切割,日志logrotate,脚本

方法一:通过logrotate切割

个人感觉配置麻烦,且结合自己这边的项目的环境的复杂,所以就不使用这种方式。这里我也就不写了

可以参考:https://www.cnblogs.com/ilanni/p/5365420.html

方法二:通过shell脚本切割

1、编写shell脚本

#!/bin/bash
#此脚本用于自动分割Nginx的日志,包括access.log和error.log
#每天00:00执行此脚本 将前一天的access.log重命名为access-xxxx-xx-xx.log格式,并重新打开日志文件
#Nginx日志文件所在目录
LOG_PATH=/opt/nginx/logs
#获取昨天的日期
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
#获取pid文件路径
PID=/var/run/nginx/nginx.pid
#分割日志
mv ${LOG_PATH}access.log ${LOG_PATH}access-${YESTERDAY}.log
mv ${LOG_PATH}error.log ${LOG_PATH}error-${YESTERDAY}.log
#向Nginx主进程发送USR1信号,重新打开日志文件
kill -USR1 `cat ${PID}`

2、配置crontab每天凌晨00:00定时执行这个脚本

crontab -e
# 输入以下内容并保存
00 00 * * * /bin/bash /opt/nginx/sbin/cut_nginx_log.sh

方法三:通过Python脚本切割

未分类

鉴于这种乱情况,日志目录下面还有多个项目的日志,且分别保存在不同的文件下面(下面又分为测试环境的日志,预发布环境的日志),使用shell脚本就不怎么好写,我就采取了通过Python来实现

脚本:

import os, sys, datetime,re

# nginx日志存放的路径
nginxLogPath="/opt/nginx-1.9.5/logs/"
# 获取昨天的日期
yesterday = (datetime.date.today() + datetime.timedelta(days = -1)).strftime("%Y-%m-%d")
# nginx启动的pid文件
PID = "/var/run/nginx.pid"


def cutNginxLog(path):
    """
    切割nginx日志函数
    :param path: 日志文件的第一级目录
    :return: 
    """
    logList = os.listdir(path)    # 判断传入的path是否是目录
    for logName in logList:      # 循环处理目录里面的文件
        logAbsPath = os.path.join(path, logName)
        if os.path.isdir(logAbsPath):   # 如果是目录,递归调用自己,继续处理
            cutNginxLog(logAbsPath)
        else:         # 如果是日志文件,就进行处理
            # 分割日志
            re_Num = re.compile(r'^[a-zA-Z]')
            # 判断日志文件是否是字母开头,如果是日期开头就不切割
            if re_Num.search(logName):
                logNewName = yesterday + "_" + logName          # 新日志文件名称列如:2018-11-8_access.log
                oldLogPath = os.path.join(path, logName)        # 旧日志文件绝对路径
                newLogPath = os.path.join(path, logNewName)     # 新日志文件绝对路径
                os.rename(oldLogPath, newLogPath)

    cmd = " kill -USR1 `cat %s` "% PID
    res = os.system(cmd)
    if res != 0:
        return "重新加载nginx失败"
cutNginxLog(nginxLogPath)

计划任务:

# crontab -e

30 02 * * * /usr/bin/python3.5 /opt/nginx-1.9.5/sbin/cut_nginx_log.py

切割后的效果图:

未分类

使用Logrotate管理日志

Linux使用某些软件的时候会产生日志文件,而这些软件本身对日志不进行分割或者压缩处理,久而久之会导致日志文件异常巨大,影响机器性能,配置不高的机器上尤为严重。而logrotate就是管理这些日志文件的神器。

Logrotate功能

logrotate会周期性的读,压缩,备份,创建新的日志文件。你想对日志文件做的操作,它基本上可以做到。

  • 防止单个日志文件过于庞大

  • 删除旧的日志文件,以防旧日志文件填满你的磁盘。

  • 对单个日志文件或者某个目录下的文件按时间/大小进行切割,压缩操作;指定日志保存数量;还可以在切割之后运行自定义命令。

许多Linux软件都已经内置了logrotate了,例如httpd默认就使用logrotated来帮你管理日志文件。

未分类

httpd logrotate

Logrotate配置

1.首先看logrotate软件包的内容

未分类

logrotate包目录

一般第三方软件包的日志文件管理都放在/etc/logrotate.d目录下。

httpd

[root@250 nginx]# cat /etc/logrotate.d/httpd/var/log/httpd/*log {
    daily
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
    endscript
}

这份配置会处理/var/log/httpd/目录下后缀为log的文件。

  • monthly: 日志文件将按月轮循。其它可用值为‘daily’,‘weekly’或者‘yearly’。

  • missingok: 在日志轮循期间,任何错误将被忽略,例如“文件无法找到”之类的错误。

  • notifempty: 如果日志文件为空,轮循不会进行。

  • sharedscripts: 在所有的日志文件都轮询之后运行postrotate脚本,如果没设置默认会在每个匹配的文件轮询之后运行一次postrotate脚本。

  • compress: 在轮循任务完成后,已轮循的归档将使用gzip进行压缩。

  • delaycompress: 总是与compress选项一起用,delaycompress选项指示logrotate不要将最近的归档压缩,压缩将在下一次轮循周期进行。这在你或任何软件仍然需要读取最新归档时很有用。

  • postrotate/endscript: 在所有其它指令完成后,postrotate和endscript里面指定的命令将被执行。在这种情况下,rsyslogd 进程将立即再次读取其配置并继续运行。

这里解释仅做参考,logrotate中的每个参数可单独进行搜索,明确具体的含义,man手册中也有详细说明。

排障

logrotate [-dv] [-f|--force] [-s|--state file] config_file
[root@250 nginx]# logrotate --help用法: logrotate [OPTION...] <configfile>
  -d, --debug               Don't do anything, just test (implies -v)
  -f, --force               Force file rotation
  -m, --mail=command        Command to send mail (instead of `/bin/mail')
  -s, --state=statefile     Path of state file
  -v, --verbose             Display messages during rotation
  -l, --log=STRING          Log file
  --version                 Display version information

1.以debug模式运行某个logrotate配置文件

未分类

logrotate debug模式

2.强制使用logrotate近轮询日志文件

未分类

logrotate 强制轮询

3.logrotate记录轮询状态的文件

未分类

logrotate状态文件格式

记录某轮询日志到logrotate状态文件中

logrotate -vf -s /var/lib/logrotate/logrotate.status  /etc/logrotate.d/httpd

最后

logrotate在日志处理上功能十分强大,但却十分容易上手,本文只是作为抛砖引玉的作用。在使用logrotate的时候,根据man手册可查寻找想要了解的各种配置信息。

希望能帮助到大家。