分类
求职面试

三道常见的MySQL数据库面试题

一,对于关系型数据库而言,索引是相当重要的概念,请回答有关索引的几个问题:

a)、索引的目的是什么?

快速访问数据表中的特定信息,提高检索速度

创建唯一性索引,保证数据库表中每一行数据的唯一性。

加速表和表之间的连接

使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间

b)、索引对数据库系统的负面影响是什么?

负面影响:

创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;当对表进行增、删、改、的时候索引也要动态维护,这样就降低了数据的维护速度。

c)、为数据表建立索引的原则有哪些?

在最频繁使用的、用以缩小查询范围的字段上建立索引。

在频繁使用的、需要排序的字段上建立索引

d)、 什么情况下不宜建立索引?

对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引。

对于一些特殊的数据类型,不宜建立索引,比如文本字段(text)等。

二,简述在MySQL数据库中MyISAM和InnoDB的区别

区别于其他数据库的最重要的特点就是其插件式的表存储引擎。切记:存储引擎是基于表的,而不是数据库。

InnoDB与MyISAM的区别:

InnoDB存储引擎: 主要面向OLTP(Online Transaction Processing,在线事务处理)方面的应用,是第一个完整支持ACID事务的存储引擎(BDB第一个支持事务的存储引擎,已经停止开发)。

特点:

行锁设计、支持外键;

支持类似于Oracle风格的一致性非锁定读(即:默认情况下读取操作不会产生锁);

InnoDB将数据放在一个逻辑的表空间中,由InnoDB自身进行管理。从MySQL4.1版本开始,可以将每个InnoDB存储引擎的表单独存放到一个独立的ibd文件中;

InnoDB通过使用MVCC(多版本并发控制:读不会阻塞写,写也不会阻塞读)来获得高并发性,并且实现了SQL标准的4种隔离级别(默认为REPEATABLE级别);

InnoDB还提供了插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead)等高性能和高可用的功能;

InnoDB采用了聚集(clustered)的方式来存储表中的数据,每张标的存储都按主键的顺序存放(如果没有显式的在建表时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键);

InnoDB表会有三个隐藏字段:除了上面提到了6字节的DB_ROW_ID外,还有6字节的DB_TX_ID(事务ID)和7字节的DB_ROLL_PTR(指向对应回滚段的地址)。这个可以通过innodb monitor看到;

MyISAM存储引擎:是MySQL官方提供的存储引擎,主要面向OLAP(Online Analytical Processing,在线分析处理)方面的应用。

特点:

不支持事务,支持表所和全文索引。操作速度快;

MyISAM存储引擎表由MYD和MYI组成,MYD用来存放数据文件,MYI用来存放索引文件。MySQL数据库只缓存其索引文件,数据文件的缓存交给操作系统本身来完成;

MySQL5.0版本开始,MyISAM默认支持256T的单表数据;

三,解释MySQL外连接、内连接与自连接的区别

先说什么是交叉连接:交叉连接又叫笛卡尔积,它是指不使用任何条件,直接将一个表的所有记录和另一个表中的所有记录一一匹配。

内连接则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合条件的记录不会出现在结果集中,即内连接只连接匹配的行。

外连接其结果集中不仅包含符合连接条件的行,而且还会包括左表、右表或两个表中的所有数据行,

这三种情况依次称之为左外连接,右外连接,和全外连接。

左外连接,也称左连接,左表为主表,左表中的所有记录都会出现在结果集中,对于那些在右表中并没有匹配的记录,仍然要显示,右边对应的那些字段值以NULL来填充。

右外连接,也称右连接,右表为主表,右表中的所有记录都会出现在结果集中。左连接和右连接可以互换,MySQL目前还不支持全外连接。

分类
运维教程

CentOS7安装Postfix

Postfix的简介

是一种电子邮件服务器,它是由任职于IBM华生研究中心的荷兰籍研究员Wietse Venema为改良sendmail邮件服务器而产生的。最早在1990年代晚期出现,是个开放源代码的软件。

Postfix的安装

# yum -y install postfix

Postfix的配置

# vim /etc/postfix/main.cf
  1. myhostname = mail.birdteam.net
  2. #邮局系统的主机名
  3. mydomain = birdteam.net
  4. #邮局系统域名
  5. myorigin = $mydomain
  6. #从本机发出邮件的域名名称
  7. inet_interfaces = all
  8. #监听网卡接口
  9. mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
  10. #可接收邮件的主机名或域名
  11. mynetworks = 127.0.0.0/8192.168.7.0/240.0.0.0/0
  12. #设置可转发哪些主机的邮件
  13. relay_domains = $mydestination
  14. #设置可转发哪些网域的邮件
  15. home_mailbox = Maildir/
  16. #使用邮箱目录
  17. smtpd_sasl_type = dovecot
  18. smtpd_sasl_path = private/auth
  19. smtpd_sasl_auth_enable = yes
  20. smtpd_sasl_security_options = noanonymous
  21. smtpd_sasl_local_domain = $myhostname
  22. smtpd_recipient_restrictions = permit_mynetworks,permit_auth_destination,permit_sasl_authenticated,reject

Dovecot的安装

# yum -y install dovecot

Dovecot的配置

# vim /etc/dovecot/dovecot.conf
  1. protocols = imap pop3 lmtp
  2. listen = *
# vim /etc/dovecot/conf.d/10-auth.conf
  1. disable_plaintext_auth = no
  2. auth_mechanisms = plain login
# vim /etc/dovecot/conf.d/10-mail.conf
  1. mail_location = maildir:~/Maildir
# vim /etc/dovecot/conf.d/10-master.conf
  1. unix_listener /var/spool/postfix/private/auth {
  2.     mode = 0666
  3.     user = postfix
  4.     group = postfix
  5. }
# vim /etc/dovecot/conf.d/10-ssl.conf
  1. ssl = no

Dovecot的启动

# systemctl start dovecot
分类
求职面试

Linux运维工程师技术面试参考答案

如何选择工具

一、对于服务器安全和监控,能推荐一些开源工具吗?监控好像也就nagios/cacti/zabbix,还有其他可以推荐的吗?安全方面如何监控?

监控工具各有各侧重点,zabbix同时支持snmp和自带agent,也支持自定义模板,在大部分场景下都是不错的选择。

另外,别把zabbix视为只能监控服务器信息,通过自定义的模板,也可以监控业务层面的指标。

安全监控分为主动检测,如Tenable Nessus,及IDS/IPS。

二、Linux运维中,系统版本都用什么版本?CentOS还是Ubuntu?为什么会选择这个版本?有做哪些测试?相比来说有啥优势?为什么会选择这个版本?

目前我们以CentOS为主。

不同Linux分支各有各特点,比如Ubuntu新版本发布较快,如果追求内核版本升级速度的话,可以考虑。

CentOS一直是我们的主要使用的Linux发行版,主要考虑到它的稳定性以及熟悉程度最高。

CentOS 一直是我们的主要 Linux 发行版,稳定性以及熟悉程度最高。

选择某个发行版时,要考虑它的生态,比如上下游的支持,还有一点,就是运维人员招聘的方便程度,国内熟悉 CentOS 的稍多一些。

三、对于使用缓存有什么推荐吗?一般就Redis/Codis。还有哪些比较好的开源软件?

对于类似session-id这样的可以非持久存储的数据,可以考虑用memcached,使用一致性哈希算法分布式存储。

四、做自动化发布,除Jenkins持续集成工具,还有哪些好用的工具呢?

目前所知道的,一般都是Hudson或者Jenkins,后者是前者分支出来的。

这些工具有丰富的插件,灵活使用这些插件才是关键所在。

五、问一个MySQL问题,三个版本(MySQL官方版、Percona Server以及MariaDB)建议使用哪个版本,原因?

我们一般使用的是官方版本。

主要是考虑到软件的支持和生态。

六、服务器日志收集和分析有什么好工具推荐?ELK有一点复杂,不太会用,有其他的推荐?

ELK确实是目前使用较广泛的日志收集和分析的工具。

虽然有些学习成本,但还是值得去研究和尝试的。

运维中遇到的问题

一、LVS和HAPROXY后端服务器规模可以做到什么程度,比如有多少个应用,多少台后端服务器?

这个取决于应用的类型,在实际业务场景下,需关注LVS等负载均衡器本身的连接数、PPS数据及延迟。

如果后端吞吐量比较大,可考虑LVS的DR模式。一般情况,负载均衡器不太会成为瓶颈。

二、对于涉及多个平台Unix/Linux/Windows的统一管理(认证,配置,服务)有什么好的解决方案或者思路么?

Unix/Linux支持OpenLDAP认证,这和Windows下的AD是兼容的。

配置和服务可考虑下开源的通用产品,比如Ansible或者Salt。

三、CentOS 6要如何做系统和网络优化?/etc/sysctl.conf中的这个参数net.ipv4.tcp_max_tw_buckets = 6000要如何设置,是越多越好吗?设置成16000?如net.ipv4.tcp_max_tw_buckets = 16000?

对于系统优化来说,要有针对性的。tcp_max_tw_buckets针对的是time wait bucket,如果系统中timewait状态较多,可考虑net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle这2个值调整。

另外,如果使用长连接对于减少该状态的连接数有效。

四、如有100多台服务器,大部分都是在提供业务的服务器,如何升级?除了停机维护,现在有什么比较好的解决方案吗?

如果本身的业务切分比较好,例如采用无状态的微服务等架构,可通过前端负载均衡器进行灰度升级。

如果应用做的不好,只有单台这种,或者集中式数据库,就比较麻烦了。

自动化运维相关工程师思维

一、可以说下什么是自动化运维,如何才算服务器做了自动化运维?包括哪些?自动化发布或是有问题可以回滚?

运维自动化是个仁者见仁智者见智的概念。我的理解运维自动化要打通从代码开发完到正式上线的所有环节,包括版本构建、打通自动测试、自动化上线以及自动化监控。

在这一个大命题下,可根据自己工作环境和自动化水平的不同,选择一两个痛点开始进行自动化实践。最后形成完整体系。

二、请问你主导运维自动化平台的功能设计和实施,是通过Python开发管理工具?另外,你们是重新开发呢,还是根据Saltstack之类的进行二次开发。

底层使用SSH协议建立服务器管理通道,上层使用PHP开发管理界面及封装一些常用操作,比如密码修改、脚本下发和执行等。

Docker与运维结合使用

一、Docker化对运维影响深远吗?

Docker化对运维有影响,它带来的影响包括:持续交付、微服务及DevOps理念的冲击。作为运维,我们要拥抱这一个变化,通过不断学习和实践来迎接这些挑战。

二、为何国内没有一家成熟Docker方案公布细节呢?

Docker还是个新生事物,各家使用的场景和模式有所不同,而且会有一些二次开发的管理系统和调度系统。

技术对比

一、作为运维人员,Python这样的脚本在进行系统管理和监控的时候相比Shell有怎样的优势?

作为高级编程语言,Python有非常丰富的库,包括核心库和第三方库,很多时候不需要自己造轮子;

相比较Shell,它有更好的控制力、重试机制,比如对Socket设置超时等等。

二、想问下只有一台服务器,运行多个应用,是用LVS做负载好还是Nginx?差别大吗?

你说的后端应用是基于HTTP或者HTTPS的吗?如果是的,且吞吐量不大的情况下,用Nginx即可;如果非HTTP或HTTPS的TCP应用,建议用LVS;如果HTTP或者HTTPS吞吐量特别大的情况下,用LVS DR模式。

与备份相关的一些问题

一、1000台机器规模,备份系统应该做到什么程度?

1000台机器,需要区分业务类型,如果类型单一,备份就比较好做了。如果类型较多,那么要考虑的地方包括:数据库更新的频率(全备+增量备份?还是只用全备)及数据备份的大小、数据集中归档要求。

二、备份怎么做的?上百T的图片、附件有什么高雅的备份方案?

在线备份这块,可考虑使用erasure coding算法,在增加一定可靠性的能力下,不至于导致备份存储的成本过高。同时需要考虑离线备份,比如磁带。

运维工程师的职业生涯

一、你觉得在未来,运维核心会是什么,预判、自动化或其他?

我觉得未来运维应该是智能化的。把现在需要人做的容量规划、扩缩容以及排障全部实现智能化。运维的任务是编程,把自己的能力灌输到机器上。

二、运维技术比较杂的,如何看待这种杂呢?给人感觉好像什么都会,对于工作5-6年运维来说,有什么好的学习建议呢?

  1. 加强自己编程能力,系统学习一门高级编程语言;
  2. 对自己技术薄弱点重点学习,比如系统学习网络知识;
  3. 看一些较好的运维技术书籍,学习别人干货。
分类
成长之路

5分钟让你看懂高斯模糊算法

通常,图像处理软件会提供模糊blur滤镜,使图片产生模糊的效果。

模糊的算法有很多,其中有一种叫做高斯模糊Gaussian Blur。它将正态分布(又名高斯分布)用于图像处理。

本文简单的介绍高斯模糊的算法,你会看到这是个非常简单易懂的算法。在本质上,它是一种数据平滑技术,适用多个场合,图像处理恰好提供了一个直观的应用实例。

高斯模糊原理

所谓模糊,可以理解成每一个像素都取周边像素的平均值。

在上图中,2就是中间点,周边点都是1。

中间点取周围点平均值,会变成1。在数值上,这是种平滑化。在图形上,就相当于产生“模糊”效果,使中间点失去细节。

显然,计算平均值时,取值范围越大,模糊效果会越强烈。

上面的分别是原图、模糊半径为3像素、模糊半径10像素的效果。模糊半径越大,图像就越模糊。从数值角度看,是数值越平滑。

接下来的问题就是,既然每个点都要取周边像素的平均值,那么该如何分配权重呢?

如果使用简单平均,显然不是很合理的,因为图像是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更加合理,距离越近的点权重越大,距离越远的点权重越小。

正态分布权重

正态分布显然是一种可取的权重分配模式。

在图形上,正态分布是种钟形曲线,越接近中心点,取值越大,越远离中心点,取值越小。

计算平均值的时候,我们只需将中心点作为原点,其它点按照其在正态曲线上位置,分配权重,就可以得到一个加权平均值。

高斯函数

上面正态分布是一维的,图像是二维的,所以我们需二维的正态分布。

正态分布的密度函数叫做高斯函数Gaussian function。它的一维形式:

其中,μ是x的均值,σ是x的方差。因为计算平均值的时候,中心点是原点,所以μ等于0。

根据一维高斯函数,可以推导得到二维高斯函数:

有了这个函数 ,就可以计算每个点的权重了。

权重矩阵

假定中心点的坐标是0,0,那么距离它最近的8个点的坐标如下:

更远的点以此类推。

为了计算权重矩阵,需要设定σ值。现假定σ=1.5,则模糊半径为1的权重矩阵如下:

这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终权重矩阵。

计算高斯模糊

有了权重矩阵,就可以计算高斯模糊的值了。

假设有9个像素点,灰度值范围0-255如下:

每个点乘以自己权重值:

得到:

将这9个值加起来,就是中心点的高斯模糊的值。

对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图,可对RGB三个通道分别做高斯模糊。

边界点的处理

如果有一个点处于边界,周边没有足够的点,怎么办呢?

一个变通方法,就是把已有的点拷贝到另一面的对应位置,模拟出完整的矩阵。

分类
成长之路

PHP快速入门学习流程图

PHP从入门到精通要多久? PHP学起来难吗?PHP快速入门的学习方法都有哪些?这是很多人在PHP学习阶段都会遇到的问题,完整的PHP学习路线图对于PHP小白的重要性是很有必要的。

学习教程

学习前期,首要的WEB前端基础知识,比如html5/css3/java/jquery有个简单的认识,能够通过html5+div+css3编写基础的WEB前端静态页面就行了。推荐几个主流的WEB前端框架,如bootstrap/foundation/pure等WEB前端框架,可以后期作为PHP入门教程的学习项目,根据个人后期发展规划,自我选择。前端开发基础,对于后期学习入门,有一定的作用。

快速入门

WEB前端开发基础的一些元素,有个简单了解之后,可以更好的实现PHP快速入门,不需对java/jquery/bootstrap教程深究,尽早的确定PHP学习方向,比如:基础语法、基本框架、变量、数组、PHP自定义函数、PHP环境变量等语法。快速入门阶段,不要求深度扩充知识面,有一定的概念就行,学习初期,读懂肯定是不太现实的。

开发环境

很多新手学习阶段,有点盲目,不知道从哪里下手,不知道PHP开发环境搭建流程,更不用说PHP开发环境的使用说明。这个就根据当前的操作系统决定,ubuntu/Linux/windows系统等,开发环境工具稍有差异,常用的一些开发环境有:wampserver/appserv/xampp/lampphpstudy等一键搭建工具。

基本语法

环境搭建完成,就得准备快速入门PHP的基本语法:循环语句、流程控制语句、变量、数据类型、注释、静态常量、匿名函数、PHP运算符、数组、常用函数等等。基本语法,先大概记住一些概念和基本定义,至于基本语法的实际应用就得后期在实例中继续实践巩固了。

实例教程

对PHP基本语法和开发环境能够熟练掌握后,可以考虑实例应用,毕竟,没有实际操作学习肯定很难巩固加深记忆。进行初期的MySQL数据库学习后,可以学习PHP连接数据库,学习后开发博客留言本、网站分页功能,cookie和session实现用户的登陆、注册功能。花时间学习PHP的GD后开始实现验证码。

学习面向对象

面向对象学习及MVC框架,在PHP学习中后期很有必要性,要想算真正意义上的开发工程师,面向对象和MVC框架是必须要学习下的。这阶段的学习内容包括:面向对象基本语法、常用类组合MVC、学习设计模式、学习PSR等。

框架学习

为便于应对公司各种复杂的站点功能,主流的PHP框架是要掌握一到两种,在学习开发过程中,很好提高工作效率。常见的PHP框架有thinkphp/laravel/ci/yii。

Linux服务器学习

Linux服务器在市场上挺受欢迎,用户学习服务器的配置部署,多数考虑Linux服务器,LAMP或者LNMP环境搭建,程序编写完成后怎么搭建到自己部署的服务器上去。都是PHP学习必要的一项任务。前提是要有自己的域名和服务器,完成域名解析、服务器空间的绑定、配置部署,GIT代码管理能够让你更快的熟悉整个流程。

高可用大并发架构学习

PHP学习入门中后期,肯定要多学习下大并发架构,NoSQL/Swoole/keepalived技术等多项不同技术。让自己全面了解服务器集群下代码怎么更好的运行。全面的了解socket、进程、线程、协程等等技术,对学习提升是很有帮助。服务器集群大并发处理,是后期研究的重心工作。

分类
运维教程

SSL通过强制跳转增加网站的安全等级

现在越来越多的网站都在使用SSL协议,提升访客在网站提交数据时的安全度。通常大家在设置好网站的SSL证书后,都会到安全度验证网站测试一下。

一般开启SSL证书后,网站的安全级别都会达到A,但是A的上面还有个A+,那这个A+要如何达到呢?网站上会提示你开启一个叫HSTS的东东,但大家千万别上当,可以看我之前写的文章《开启HSTS后的坑》就会了解有些设置是开不得。

其实开启SSL后,网站可用两种协议访问,一种是http,另一种https,后者会对数据加密,所以更加安全。而HSTS的作用就是将http协议的访问请求屏蔽,使用户只能通过https协议访问。

所以我们可以换个思路解决这个问题,将所有http请求,跳转到https,这样同样可以保障网站数据的安全性。

这里以nginx为例,在配置文件中添加如下内容即可:

  1. if ($server_port !~ 443){
  2.     rewrite ^(/.*)$ https://$host$1 permanent;
  3. }

上面代码的意思是判断访问是否来自443号端口,https对应443,而http对应是80,所以只要不是443过来的请求,都是不安全的,就跳转到https协议来处理。

分类
成长之路

PHP连接MySQL

PHP5及以上版本建议使用以下方式连接MySQL数据库:

  • MySQLi extension这里的i意为improved
  • PDO全称PHP Data Objects

在PHP早期版本中我们使用MySQL扩展,但该扩展在2012年开始不建议使用。

我该用MySQLi,还是PDO呢

如果你需要一个简短的回答,那就“习惯哪个就用哪个”

MySQLi和PDO有它们自己优势:PDO应用在12种不同数据库中,MySQLi只针对MySQL数据库。

所以,如果你的项目需在多种数据库中切换,建议用PDO,这样你只需要修改连接字符串和部分查询语句即可。如使用MySQLi,不同的数据库,需要重新编写所有代码,包括查询。

两者都是面向对象,但MySQLi提供了API接口。

两者都支持预处理语句。预处理语句可以防止SQL注入,对于web项目安全性是非常重要的。

MySQLi和PDO连接MySQL实例

我们用以下三种方式来演示PHP操作MySQL:

  • MySQLi面向对象的方式
  • MySQLi面向过程的方式
  • PDO的方式

MySQLi面向对象的方式:

  1. <?php
  2. $servername = “localhost”;
  3. $username = “username”;
  4. $password = “password”;
  5. // 创建连接
  6. $conn = new mysqli($servername$username$password);
  7. // 检测连接
  8. if ($conn->connect_error) {
  9.     die(“连接失败: “ . $conn->connect_error);
  10. }
  11. echo “连接成功”;
  12. ?>

注意在上面向对象的实例中$connect_error是在PHP5.2.9和5.3.0中添加的。如果你需要兼容更早版本请使用以下代码替换:

  1. // 检测连接
  2. if (mysqli_connect_error()) {
  3.     die(“MySQL数据库连接失败: “ . mysqli_connect_error());
  4. }

MySQLi面向过程的方式:

  1. <?php
  2. $servername = “localhost”;
  3. $username = “username”;
  4. $password = “password”;
  5. // 创建连接
  6. $conn = mysqli_connect($servername$username$password);
  7. // 检测连接
  8. if (!$conn) {
  9.     die(“Connection failed: “ . mysqli_connect_error());
  10. }
  11. echo “连接成功”;
  12. ?>

PDO的方式:

  1. <?php
  2. $servername = “localhost”;
  3. $username = “username”;
  4. $password = “password”;
  5. try {
  6.     $conn = new PDO(“mysql:host=$servername;”$username$password);
  7.     echo “连接成功”;
  8. }
  9. catch(PDOException $e)
  10. {
  11.     echo $e->getMessage();
  12. }
  13. ?>

注意在以上PDO实例中我们已经指定了数据库myDB。PDO在连接过程需要设置数据库名。如果没有指定,则会抛出异常。

关闭连接

MySQLi面向对象的方式:

  1. $conn->close();

MySQLi面向过程的方式:

  1. mysqli_close($conn);

PDO的方式:

  1. $conn = null;
分类
运维教程

MHA的搭建步骤

Master High Availability又称MHA,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的软件。MySQL故障切换过程中,MHA能够做到在30秒之内自动完成数据库的故障切换操作,并在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。

主机及实例IP

  1. Manager : 192.168.18.250
  2. Master : 172.16.18.2:3306
  3. Slave1 : 172.16.18.3:3306
  4. Slave2 : 172.16.18.4:3306
  5. VIP : 172.16.18.5

Slave的配置参数

  1. log_bin=/home/birdteam/log/mysql-bin
  2. read_only=1
  3. relay_log_purge=0
  4. #一主一从不用此项,两从及以上建议打开此参数,防止切换为成主库的从库自动删除中继日志后,无法给其他从库应用这部分日志

配置主从同步

  1. mysql>grant replication slave on *.* to ‘repl_17zuoye’@’%’ identified by ‘office.repl.17zuoye’;
  2. mysql>flush privileges;
  3. #三个节点都要配置,用于当某个slave升为主后其他的从进行同步
  4. mysql>change master to master_host=’172.16.18.2‘,master_user=’dtstack’,master_port=3306,master_password=’abc123′,master_log_file=’logbin.000014‘,master_log_pos=70980879;
  5. mysql>start slave;

配置SSH免秘钥,四台服务器之间可互通

  1. # ssh-keygen -t rsa
  2. # ssh-copy-id -i .ssh/id_rsa.pub root@172.16.18.2

四个节点安装EPEL源以及相关yum包

  1. # rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm          
  2. # yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perlTime-HiRes

下载安装mha包

  1. # wget https://code.google.com/p/mysql-master-ha/wiki/Downloads?tm=2          
  2. manager节点:
  3. # rpm –ivh mha4mysql-manager-0.560.el6.noarch.rpm
  4. # rpm –ivh mha4mysql-node-0.560.el6.noarch.rpm
  5. node 节点:
  6. # rpm –ivh mha4mysql-node-0.560.el6.noarch.rpm

建立与授权mha用户

  1. mysql>GRANT ALL PRIVILEGES ON *.* TO ‘mha’@’%’ IDENTIFIED BY ‘mhamha’;
  2. mysql>flush privileges;

manager节点建立相关目录和配置文件

  1. # tree /mha
  2. /mha
  3. ├── app1
  4. │   ├── app1.conf
  5. │   └── manager.log
  6. └── conf
  7. ├── master_ip_failover_3306
  8. ├── master_ip_online_change
  9. └── send_report
  10. 2 directories, 5 files

相关配置文件内容

  1. # cat app1.conf
  2. [server default]
  3. manager_workdir = /mha/app1
  4. manager_log = /mha/app1/manager.log
  5. remote_workdir = /mha/app1
  6. master_ip_failover_script=/mha/conf/master_ip_failover_3306
  7. #master failover时执行
  8. report_script=/mha/conf/send_report
  9. #master failover时执行,发送邮件使用
  10. master_ip_online_change_script=/mha/conf/master_ip_online_change
  11. #master_switchover时执行(手动切换)
  12. user=mha
  13. password=mhamha
  14. ping_interval=1
  15. ping_type=CONNECT
  16. repl_password=office.repl.17zuoye
  17. repl_user=repl_17zuoye
  18. ssh_port=22
  19. ssh_user=root
  20. [server1]
  21. hostname = 10.200.3.2
  22. port=3306
  23. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  24. candidate_master = 1
  25. #这个服务器有较高的优先级提升为新的master(还要具备:开启binlog使复制没有延迟)
  26. [server2]
  27. hostname = 10.200.3.3
  28. port=3306
  29. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  30. candidate_master =1
  31. ignore_fail=1
  32. [server3]
  33. hostname = 10.200.3.4
  34. port=3306
  35. master_binlog_dir = /database1/data_5.6.17_3306/binlog
  36. candidate_master =1
  37. ignore_fail=1
  38. #如slave存在故障,在主库出现问题时默认情况下mha不会进行故障切换,该参数即设定MHA会在所有的机器有问题的时间也会进行故障切换
  39. no_master=1
  40. #不将这台主机转换为master

主库启动一个虚IP

  1. # /sbin/ifconfig em1:0 10.200.3.5/23 up

失败切换脚本

  1. # cat master_ip_failover_3306
  2. #!/usr/bin/env perl
  3. use strict;
  4. use warnings FATAL => ‘all’;
  5. use Getopt::Long;
  6. my (
  7.     $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
  8.     $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
  9. );
  10. my $vip = ‘10.200.3.5/23‘;  # Virtual IP
  11. my $key = “0”;
  12. my $ssh_start_vip = “/sbin/ifconfig em1:$key $vip”;
  13. my $start_new_master_vip = “/sbin/ifconfig em1:$key $vip”;
  14. my $ssh_stop_vip = “/sbin/ifconfig em1:$key down”;
  15. my $arp = “/usr/sbin/arping -A -q -c 2 -I em1:$key 10.200.3.5”;
  16. #虚IP配置,在哪个网卡上,key编号的对应
  17. GetOptions(
  18.     ‘command=s’          => \$command,
  19.     ‘ssh_user=s’         => \$ssh_user,
  20.     ‘orig_master_host=s’ => \$orig_master_host,
  21.     ‘orig_master_ip=s’   => \$orig_master_ip,
  22.     ‘orig_master_port=i’ => \$orig_master_port,
  23.     ‘new_master_host=s’  => \$new_master_host,
  24.     ‘new_master_ip=s’    => \$new_master_ip,
  25.     ‘new_master_port=i’  => \$new_master_port,
  26. );
  27. exit &main();
  28. sub main {
  29.     print “\n\nIN SCRIPT TEST====$ssh_stop_vip==$start_new_master_vip===\n\n”;
  30.     if ( $command eq “stop” || $command eq “stopssh” ) {
  31.         # $orig_master_host, $orig_master_ip, $orig_master_port are passed.
  32.         # If you manage master ip address at global catalog database,
  33.         # invalidate orig_master_ip here.
  34.         my $exit_code = 1;
  35.         eval {
  36.             print “Disabling the VIP on old master: $orig_master_host \n”;
  37.             &stop_vip();
  38.             $exit_code = 0;
  39.         };
  40.         if ($@) {
  41.             warn “Got Error: $@\n”;
  42.             exit $exit_code;
  43.         }
  44.         exit $exit_code;
  45.     }
  46.     elsif ( $command eq “start” ) {
  47.         # all arguments are passed.
  48.         # If you manage master ip address at global catalog database,
  49.         # activate new_master_ip here.
  50.         # You can also grant write access (create user, set read_only=0, etc) here.
  51.         my $exit_code = 10;
  52.         eval {
  53.             print “Enabling the VIP – $vip on the new master – $new_master_host \n”;
  54.             &start_vip();
  55.             $exit_code = 0;
  56.         };
  57.         if ($@) {
  58.             warn $@;
  59.             exit $exit_code;
  60.         }
  61.         exit $exit_code;
  62.     }
  63.     elsif ( $command eq “status” ) {
  64.        # print “Checking the Status of the script.. OK \n”;
  65.        # `ssh $ssh_user\@tm01.okooo.cn \” $ssh_start_vip \”`;
  66.         exit 0;
  67.     }
  68.     else {
  69.         &usage();
  70.         exit 1;
  71.     }
  72. }
  73. # A simple system call that enable the VIP on the new master
  74. sub start_vip() {
  75.     `ssh root\@$new_master_host \” $ssh_start_vip \”`;
  76.     `ssh root\@$new_master_host \” $arp \”`;
  77. }
  78. # A simple system call that disable the VIP on the old_master
  79. sub stop_vip() {
  80.     return 0 unless ($ssh_user);
  81.     `ssh $ssh_user\@$orig_master_host \” $ssh_stop_vip \”`;
  82. }
  83. sub usage {
  84.     print
  85.     “Usage: master_ip_failover –command=start|stop|stopssh|status –orig_master_host=host –orig_master_ip=ip –orig_master_port=port –new_master_host=host –new_master_ip=ip –new_master_port=port\n”;
  86. }

手动在线切换脚本

  1. # cat master_ip_online_change
  2. #!/usr/bin/env perl
  3. use strict;
  4. use warnings FATAL =>’all’;
  5. use Getopt::Long;
  6. my $vip = ‘10.200.3.5/23‘;  # Virtual IP
  7. my $key = “0”;
  8. my $ssh_start_vip = “/sbin/ifconfig em1:$key $vip”;
  9. my $ssh_stop_vip = “/sbin/ifconfig em1:$key down”;
  10. my $exit_code = 0;
  11. my (
  12.   $command,              $orig_master_is_new_slave, $orig_master_host,
  13.   $orig_master_ip,       $orig_master_port,         $orig_master_user,
  14.   $orig_master_password, $orig_master_ssh_user,     $new_master_host,
  15.   $new_master_ip,        $new_master_port,          $new_master_user,
  16.   $new_master_password,  $new_master_ssh_user,
  17. );
  18. GetOptions(
  19.   ‘command=s’                => \$command,
  20.   ‘orig_master_is_new_slave’ => \$orig_master_is_new_slave,
  21.   ‘orig_master_host=s’       => \$orig_master_host,
  22.   ‘orig_master_ip=s’         => \$orig_master_ip,
  23.   ‘orig_master_port=i’       => \$orig_master_port,
  24.   ‘orig_master_user=s’       => \$orig_master_user,
  25.   ‘orig_master_password=s’   => \$orig_master_password,
  26.   ‘orig_master_ssh_user=s’   => \$orig_master_ssh_user,
  27.   ‘new_master_host=s’        => \$new_master_host,
  28.   ‘new_master_ip=s’          => \$new_master_ip,
  29.   ‘new_master_port=i’        => \$new_master_port,
  30.   ‘new_master_user=s’        => \$new_master_user,
  31.   ‘new_master_password=s’    => \$new_master_password,
  32.   ‘new_master_ssh_user=s’    => \$new_master_ssh_user,
  33. );
  34. exit &main();
  35. sub main {
  36. #print “\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n”;
  37. if ( $command eq “stop” || $command eq “stopssh” ) {
  38.         # $orig_master_host, $orig_master_ip, $orig_master_port are passed.
  39.         # If you manage master ip address at global catalog database,
  40.         # invalidate orig_master_ip here.
  41.         my $exit_code = 1;
  42.         eval {
  43.             print “\n\n\n***************************************************************\n”;
  44.             print “Disabling the VIP – $vip on old master: $orig_master_host\n”;
  45.             print “***************************************************************\n\n\n\n”;
  46. &stop_vip();
  47.             $exit_code = 0;
  48.         };
  49.         if ($@) {
  50.             warn “Got Error: $@\n”;
  51.             exit $exit_code;
  52.         }
  53.         exit $exit_code;
  54. }
  55. elsif ( $command eq “start” ) {
  56.         # all arguments are passed.
  57.         # If you manage master ip address at global catalog database,
  58.         # activate new_master_ip here.
  59.         # You can also grant write access (create user, set read_only=0, etc) here.
  60. my $exit_code = 10;
  61.         eval {
  62.             print “\n\n\n***************************************************************\n”;
  63.             print “Enabling the VIP – $vip on new master: $new_master_host \n”;
  64.             print “***************************************************************\n\n\n\n”;
  65. &start_vip();
  66.             $exit_code = 0;
  67.         };
  68.         if ($@) {
  69.             warn $@;
  70.             exit $exit_code;
  71.         }
  72.         exit $exit_code;
  73. }
  74. elsif ( $command eq “status” ) {
  75.         print “Checking the Status of the script.. OK \n”;
  76.         `ssh $orig_master_ssh_user\@$orig_master_host \” $ssh_start_vip \”`; 
  77.         exit 0; 
  78. }  
  79. else { 
  80. &usage(); 
  81.         exit 1; 
  82.  
  83. # A simple system call that enable the VIP on the new master 
  84. sub start_vip() { 
  85. `ssh $new_master_ssh_user\@$new_master_host \” $ssh_start_vip \”`; 
  86. # A simple system call that disable the VIP on the old_master 
  87. sub stop_vip() { 
  88. `ssh $orig_master_ssh_user\@$orig_master_host \” $ssh_stop_vip \”`; 
  89.  
  90. sub usage { 
  91. print 
  92. Usage: master_ip_failover –command=start|stop|stopssh|status –orig_master_host=host –orig_master_ip=ip –orig_master_port=po
  93. rt –new_master_host=host –new_master_ip=ip –new_master_port=port\n”;
  94. }

failover后发送邮件脚本

  1. # cat send_report
  2. #!/bin/bash
  3. source /root/.bash_profile
  4. orig_master_host=`echo “$1” | awk -F = ‘{print $2}’`
  5. new_master_host=`echo “$2” | awk -F = ‘{print $2}’`
  6. new_slave_hosts=`echo “$3” | awk -F = ‘{print $2}’`
  7. subject=`echo “$4” | awk -F = ‘{print $2}’`
  8. body=`echo “$5” | awk -F = ‘{print $2}’`
  9. #判断日志结尾是否有successfully,有则表示切换成功,成功与否都发邮件
  10. tac /mha/app1/manager.log | sed -n 2p | grep ‘successfully’ > /dev/null
  11. if [ $? -eq 0 ]
  12.   then
  13.   echo -e “MHA $subject 主从切换成功\n master:$orig_master_host –> $new_master_host \n $body \n 当前从库:$new_slave_hosts” | mailx -s “MySQL实例宕掉,MHA $subject 切换成功” noreply@birdteam.net
  14. else
  15.   echo -e “MHA $subject 主从切换失败\n master:$orig_master_host –> $new_master_host \n $body” | mailx -s “MySQL实例宕掉,MHA $subject 切换失败” noreply@birdteam.net
  16. fi

修改脚本属主属组,并且增加执行权限

  1. # chown mysql.mysql ./*
  2. # chmod +x ./*

检查SSH的配置

  1. # masterha_check_ssh –conf=/mha/app1/app1.conf
  2. Tue Jan  5 17:16:41 2016 – [info] All SSH connectiontests passed successfully.

检查MHA的配置

  1. # masterha_check_repl –conf=/mha/app1/app1.conf
  2. MySQL Replication Health is OK.

启动MHA的服务

  1. # masterha_manager –conf=/mha/app1/app1.conf

发生failover主从切换后,MHAmanager服务会自动停掉,且在manager_workdir目录下面生成文件app1.failover.complete,若想要启动MHA,必须先确保没有此文件

  1. # ll
  2. total 80
  3. -rw-r–r– 1 mysql mysql   556 Aug 29 11:23 app1.conf
  4. -rw-r–r– 1 root  root      0 Aug 29 15:33 app1.failover.complete
  5. -rw-r–r– 1 root  root  69838 Aug 29 15:33 manager.log
  6. -rw-r–r– 1 root  root    143 Aug 29 15:33 saved_master_binlog_from_192.168.100.111_3306_20160829153340.binlog

在线手动切换主从,如果MHA在运行,需要先停止MHA,然后再检查MHA当前设置

  1. # masterha_check_repl –conf=/mha/app1/app1.conf

手动切换

  • 如果不指定new_master_host,则会根据配置文件app1.cnf选出new_master_host,但new_master_port默认是3306
  1. masterha_master_switch –master_state=alive –conf=/mha/app1/app1.conf  –orig_master_is_new_slave -running_updates_limit=3600 –interactive=0
  • 以下为切换时指定了new_master_host和new_master_port
  1. masterha_master_switch –master_state=alive –conf=/mha/app1/app1.conf  –orig_master_is_new_slave -running_updates_limit=3600 –interactive=0 –new_master_host=10.200.3.2 –new_master_port=3306
  1. 参数–running_updates_limit如果现在master执行写操作的执行时间大于这个参数,或任何一台slave的Seconds_Behind_Master大于这个参数,那么master switch将自动放弃,默认参数为1s;
  2. 参数–interactive=0非交互切换,建议加上,可以大大加快切换速度,加上后库不忙时大概3秒内切换完成。

注意

  • 如果需要将现有的从库修改为从,再启动mha的时候可能会报错;
  1. Wed Sep  7 12:18:56 2016 – [error][/usr/share/perl5/vendor_perl/MHA/ServerManager.pm, ln671] Master 192.168.100.111:3306 from which slave 10.200.3.2(10.200.3.2:3306) replicates is not defined in the configuration file!
  • 切换脚本可在MHA的官网查看。
分类
运维教程

LNMP实现双主机负载均衡

项目需求

网站创建之初因访问量较少,只放置在一台服务器上。随着访问量的增加,一台服务器已无法负载,打算增加一台服务器做负载均衡。

项目分析

常见的负载均衡有两种,一种基于四层为LVS,一种基于七层为Nginx。两种负载均衡都需要三台服务器才能发挥性能,有悖于预算中的两台服务器,故打算使用动静分离加远程数据库来实现负载均衡。

网络拓扑

设备信息

  1. 客户端192.168.1.250,仅需要浏览器;
  2. 服务器A192.168.1.1,需安装Nginx+PHP,负责分发和动态文件的处理;
  3. 服务器B192.168.1.2,需安装Nginx+MySQL,负责静态文件处理和数据库存储。

实施前提

如上安装好对应的服务,程序以WordPress为例。

项目实施

  • 动静分离

修改服务器A的Nginx配置文件,内容如下:

  1. server
  2. {
  3.     listen 80;
  4.     server_name birdteam.net;
  5.     index index.php;
  6.     root /www/wwwroot/birdteam.net;
  7.     include enable-php-70.conf;
  8.     include /www/server/panel/vhost/rewrite/birdteam.net.conf;
  9.     location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
  10.     {
  11.         proxy_pass http://192.168.1.2;
  12.     }
  13. }
  • 数据调用

wp-config.php文件中

  1. define(‘DB_HOST’, ‘localhost’);

改为

  1. define(‘DB_HOST’, ‘192.168.1.2’);
  • 文件同步

将WordPress中的静态文件,扩展名为gif|jpg|jpeg|png|bmp|swf|js|css复制到服务器B对应的目录中。

数据走向

  1. 服务器组对外公布服务器A的IP地址;
  2. 客户访问服务器A的IP地址;
  3. 服务器A根据请求判断动静解析都有哪些;
  4. 根据请求本地处理动态内容,并把静态请求转发至B;
  5. 如果动态内容需要数据库的支持,则会根据指定地址,找B读取;
  6. B将静态请求、数据信息发送给A,A将所有请求整合返回给客户端。

附加内容

文件同步可使用NFS服务,或RSYNC,这样效率更高!

分类
运维教程

RHEL7的YUM源替换成CentOS

刚装的RHEL7使用命令yum update升级时会提示This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.

这是因为系统自带的YUM需要注册才能使用,我们可以将其替换成CentOS的YUM源。

删除自带YUM包

命令如下:

rpm -qa | grep yum | xargs rpm -e --nodeps
rpm -qa | grep python-urlgrabber | xargs rpm -e --nodeps

效果如下:

下载CentOS的YUM包

命令如下:

[login]

wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/yum-metadata-parser-1.1.4-10.el7.x86_64.rpm
wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/yum-3.4.3-154.el7.centos.noarch.rpm
wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.31-42.el7.noarch.rpm
wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/yum-utils-1.1.31-42.el7.noarch.rpm
wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/python-urlgrabber-3.10-8.el7.noarch.rpm

[/login]

效果如下:

安装CentOS的YUM包

命令如下:

rpm -ivh yum-metadata-parser-1.1.4-10.el7.x86_64.rpm yum-3.4.3-154.el7.centos.noarch.rpm yum-plugin-fastestmirror-1.1.31-42.el7.noarch.rpm yum-utils-1.1.31-42.el7.noarch.rpm python-urlgrabber-3.10-8.el7.noarch.rpm  --nodeps

效果如下:

更换CentOS的YUM源

命令如下:

vim /etc/yum.repos.d/birdteam.repo

代码如下:

[login]

  1. [base]
  2. name=CentOS-7 – Base – mirrors.aliyun.com
  3. baseurl=http://mirrors.aliyun.com/centos/7/os/$basearch/
  4. gpgcheck=0
  5. [updates]
  6. name=CentOS-7 – Updates – mirrors.aliyun.com
  7. baseurl=http://mirrors.aliyun.com/centos/7/updates/$basearch/
  8. gpgcheck=0
  9. [extras]
  10. name=CentOS-7 – Extras – mirrors.aliyun.com
  11. baseurl=http://mirrors.aliyun.com/centos/7/extras/$basearch/
  12. gpgcheck=0

[/login]

效果如下:

调用新的YUM源

代码如下:

yum clean all

效果如下:

测试新的YUM源

代码如下:

yum list

效果如下: