数据库

MySQL在线DDL修改表结构的简单经验分享

在线DDL修改生产环境的大表一直是运维、DBA一个很头痛的问题,本文分享一些相关经验,希望对还在头痛的同学能有所帮助,当然更希望路过的大神,如果有更靠谱的方案能够指点一二,不吝赐教。
阅读全文
数据库

gh-ost:在线DDL修改MySQL表结构工具

在之前,我分享过一次pt-online-schema-change在线DDL的工具实践记录,在实际使用过程中,发现部门的很多老系统大量使用了触发器,从而无法使用这个工具,非常遗憾!导致很多DDL变更都必须压到空闲时候做,比如凌晨,非常苦逼。 咨询了做DBA的老同事,他将gh-ost推荐给我,基于golang语言,是github开源的一个DDL工具,gh-ost是gitHub,s Online Schema Transmogrifier/Transfigurator/Transformer/Thingy的缩写,意思是GitHub的在线表定义转换器。============  分割线之间内容摘自网络  ============ gh-ost有如下特点: 无触发器 轻量级 可暂停 动态可控 可审计 可测试 可靠 无触发器gh-ost不使用触发器,它跟踪二进制日志文件,在对原始表的修改提交之后,用异步方式把这修改内容应用到临时表中去。 gh-ost希望二进制文件使用基于行的日志格式,但这并不表示如果主库上使用的是基于语句的日志格式,就不能用它来在线修改表定义了。事实上,我们常用的方式是用一个从库把日志的语句模式转成行模式,再从这个从库上去读日志。搭一个这样的从库并不复杂。 轻量级 因为不需要使用触发器,gh-ost把修改表定义的负载和正常的业务负载解耦开了。它不需要考虑被修改的表上的并发操作和竞争等,这些在二进制日志中都被序列化了,gh-ost只操作临时表,完全与原始表不相干。事实上,gh-ost也把行拷贝的写操作与二进制日志的写操作序列化了,这样,对主库来说只是有一条连接在顺序的向临时表中不断写入数据,这样的行为与常见的ETL相当不同。 可暂停 因为所有写操作都是gh-ost生成的,而读取二进制文件本身就是一个异步操作,所以在暂停时,gh-ost是完全可以把所有对主库的写操作全都暂停的。暂停就意味着对主库没有写入和更新。不过gh-ost也有一张内部状态跟踪表,即使在暂停状态下也会向那张表中不断写入心跳信息,写入量可以忽略不计。 gh-ost提供了比简单的暂停更多的功能,除了暂停之外还可以做: 负载:与pt-online-schema-change相近的一个功能,用户可以设置MySQL指标的阈值,比如设置Threads_running=30。 复制延迟:gh-ost内置了心跳功能来检查复制延迟。用户可以指定查看哪个从库的延迟,gh-ost默认是直接查看它连上的那个从库。 命令:用户可以写一些命令,根据输出结果来决定要不要开始操作。比如:SELECT HOUR(NOW()) BETWEEN 8 and 17. 上述所有指标即使在修改表定义的过程中也可以动态修改。 标志位文件:生成一个标志位文件,gh-ost就会立刻暂停。删除文件,gh-ost又会恢复工作。 用户命令:通过网络连上gh-ost,通过命令让它暂停。 动态可控如果别的工具在修改过程中产生了比较高的负载,DBA只好把它停掉再修改配置,比如把一次拷贝的数据量改小些,然后再从头开始修改过程。这样的反复操作代价非常大。 gh-ost通过监听TCP或者unix socket文件来获取命令。即使有正在进行中的修改工作,用户也可以向gh-ost发出命令修改配置,比如可以这样做: echo throttle | socat - /tmp/gh-ost.sock:这是暂停命令。也可以输入no-throttle 修改运行参数,gh-ost可以接受这样的修改方式来改变它的行为:chunk-size=1500, max-lag-millis=2000, max-load=Thread_running=30 可审计用上面所说的相同接口也可以查看gh-ost的状态,查看当前任务进度、主要配置参数、相关MySQL实例的情况等。这些信息通过网络发送命令就可以得到,因此就给了运维人员极大的灵活性,如果是使用别的工具的话一般只能是通过共享屏幕或者不断跟踪日志文件最新内容。 可测试 读取二进制文件内容的操作完全不会增加主库的负载,在从库上做修改表结构的操作也和在主库上做是非常相象的(当然并不完全一样,但主要来说还是差不多的)。 gh-ost自带了--test-on-replica选项来支持测试功能,它允许你在从库上运行起修改表结构操作,在操作结束时会暂停主从复制,让两张表都处于同步、就绪状态,然后切换表、再切换回来。这样就可以让用户从容不迫地对两张表进行检查和对比。 我们在GitHub是这样在生产环境测试gh-ost的:我们有许多个指定的生产从库,在上面不提供服务,只是周而复始地不断地把所有表定义都改来改去。对于我们生产环境地每一张表,小到空表,大到几百GB,都会通过修改存储引擎的方式来进行修改(engine=innodb),这样并不会真正修改表结构。在每一次这样的修改操作最后我们都会停掉主从复制,再把原始表和临时表的全量数据都各做一次校验和,然后比较两个校验和,要求它们是一致的。然后我们恢复主从复制,再继续测试下一张表。我们生产环境的每一张表都这样用gh-ost在从库上做过好多次修改测试。 可靠的 所有上述讲到的和没讲到的内容,都是为了让你对gh-ost的能力建立信任。毕竟,大家在做这件事的时候已经使用类似工具做了好多年,而gh-ost只是一个新工具。 我们在从库上对gh-ost进行测试,在去主库上做第一次真正改动之前我们在从库上成功地试了几千次。所以,请你也在从库上开始测试,验证数据是完好无损的,然后再把它用到生产环境。我们希望你可以放手去试。 当你执行了gh-ost之后,也许你会看见主库的负载变高了,那你可以发出暂停命令。用echo throttle命令生成一个文件,看看主库的负载会不会又变得正常。试一下这些命令,你就可以知道你可以怎样控制它的行为,你的心里就会安定许多。 你发起了一次修改操作,然后估计完成时间是凌晨2点钟,可是你又非常关心最后的切换操作,非常想看着它切换,这可怎么办?只需要一个标志位文件就可以告诉gh-ost推迟切换了,这样gh-ost会只做完拷贝数据的操作,但不会切换表。它还会仍然继续同步数据,保持临时表的数据处于同步状态。等第二天早上你回到办公室之后,删除标志位文件或者向gh-ost发送命令echo unpostpone,它就会做切换了。我们不希望软件强迫我们看着它做事情,它应该把我们解放出来,让人去做人该做的事。 谈到估计完成时间,--exact-rowcount选项非常有用。在最开始时要在目标表上做个代价比较大的SELECT COUNT(*)操作查出具体要拷多少行数据,gh-ost就会对它要做多少工作有了一个比较准确的估计。接下来在拷贝的过程中,它会不断地尝试更新这个估计值。因为预计完成的时间点总是会不断变化,所以已经完成的百分比就反而比较精确。如果你也曾经有过非常痛苦的经历,看着已经完成99%了可是剩下的一点操作却继续了一个小时也没完,你就会非常喜欢我们提供的这个功能。 gh-ost工作模式【要着重看】gh-ost工作时可以连上多个MySQL实例,同时也把自己以从库的方式连上其中一个实例来获取二进制日志事件。根据你的配置、数据库集群架构和你想在哪里执行修改操作,可以有许多种不同的工作模式。 模式一、连上从库,在主库上修改 这是gh-ost默认的工作模式,它会查看从库情况,找到集群的主库并且连接上去。修改操作的具体步骤是: 在主库上读写行数据; 在从库上读取二进制日志事件,将变更应用到主库上; 在从库上查看表格式、字段、主键、总行数等; 在从库上读取gh-ost内部事件日志(比如心跳); 在主库上完成表切换; 如果主库的二进制日志格式是Statement,就可以使用这种模式。但从库就必须配成启用二进制日志(log_bin, log_slave_updates),还要设成Row格式(binlog_format=ROW),实际上gh-ost会在从库上帮你做这些设置。 事实上,即使把从库改成Row格式,这仍然是对主库侵入最少的工作模式。 模式二、直接在主库上修改 如果没有从库,或者不想在从库上操作,那直接用主库也是可以的。gh-ost就会在主库上直接做所有的操作。仍然可以在上面查看主从复制延迟。 主库必须产生Row格式的二进制日志; 启动gh-ost时必须用--allow-on-master选项来开启这种模式; 模式三、在从库上修改和测试 这种模式会在从库上做修改。gh-ost仍然会连上主库,但所有操作都是在从库上做的,不会对主库产生任何影响。在操作过程中,gh-ost也会不时地暂停,以便从库的数据可以保持最新。 --migrate-on-replica选项让gh-ost直接在从库上修改表。最终的切换过程也是在从库正常复制的状态下完成的。 --test-on-replica表明操作只是为了测试目的。在进行最终的切换操作之前,复制会被停止。原始表和临时表会相互切换,再切换回来,最终相当于原始表没被动过。主从复制暂停的状态下,你可以检查和对比这两张表中的数据。 三种模式各有优缺点,但我只关心缺点:先说模式一的缺点,模式一会在从DB上面读取binlog,可能造成数据库主从数据不一致,原因因为是主库的binlog没有完全在从库执行。所以个人感觉模式一有丢失数据的风险。 模式二任何操作都会在主库操作,或多或少会对主库负载造成影响,但是可以通过调整一些参数降低和时刻关注这些影响,所以个人推荐使用模式二。 至于模式三是偏向测试用的,这里不做过多介绍,但是模式三里有一个细节,cut-over阶段有会stop slave一个操作,其实这个操作风险特别高,有时stop slave 时间会很长,务必会对线上数据库使用造成影响,所以如果使用模式三做测试也要在线下数据库。 gh-ost在GitHub的应用现在GitHub生产环境的表修改操作全都是用gh-ost完成的。每天只要有需求来了,就将它运行起来,有时候一天会做好多次。因为它有审计和控制功能,所以我们还可以把它和我们的Chatops系统整合起来。技术人员可以对它的工作进度有非常清晰的了解,因此可以控制它的行为。在生产环境中各种指标和事件都被收集起来,让大家可以以图形化的方式看到操作情况。 ============  分割线之间内容摘自网络  ============ 下面分享gh-ost的测试使用: 1、下载程序 一直都非常喜欢go语言编写的程序,原因很单纯,大部分情况都是一个二进制就能解决问题了,无任何依赖,简直是IT界的一股清流! 从github发布地址下载最新的binary包:https://github.com/github/gh-ost/releases 解压后就一个 gh-ost 二进制文件,再次献上我坚实的膝盖。 2、常用参数 --max-load 执行过程中,gh-ost会时刻关注负载情况,负载阀值是使用者自己定义,比如数据库的最大连接数,如果超过阀值,gh-ost不会退出,会等待到负载在阀值以下继续执行。 --critical-load 这个指的是gh-ost退出阀值,当负载超过这个阀值,gh-ost会停止并退出 --chunk-size 迁移过程是一步步分批次完成的,这个参数是指事务每次提交的行数,默认是1000。 --max-lag-millis 会监控从库的主从延迟情况,如果延迟秒数超过这个阀值,迁移不会退出,等待延迟秒数低于这个阀值继续迁移。...
阅读全文
WEB应用

网站集成打字震动特效JS代码改进版

这又是一个拖欠了很久的分享,很早就有朋友留言问评论打字炫彩、震动特效怎么实现的。这功能其实网上早就有人分享N遍了,有点搜索技巧和DIY能力的站长同学也早就实现了。这里还是继续分享一下我这边的一些改进,也许有朋友可以用得到。 简单的改进: 1、移动端关闭震动,移动端震动会显得很卡; 2、添加震动开关,方便不喜欢的朋友进行关闭,采用Cookie记忆同一个浏览器点击关闭一次即可。 Ps:没什么技术含量,略懂JS语法的朋友完全可以自己继续发挥。 以下是简单的部署步骤(不限于WordPress,标准HTML网页均可使用): 1、将以下代码保存为js文件,比如 apm-min.js 上传到网站主题目录: 比如最终得到的JS地址:https://www.domain.com/wp-content/themes/begin/js/apm-min.js 能够在浏览器正常访问即可。 2、WordPress在主题的评论模板文件 comments.php中引入如下代码(位置随意),其他网站程序可以集成到网页的页脚等位置: 3、在想要出现震动开关的位置添加按钮代码: Ps:每个人网站风格不一样,这个按钮样式就不给CSS代码了,自行DIY修改吧。 效果预览:在本页留言即可看到效果。 之前很多朋友留言说震动太难受了,我只能说那么大个红色开关,你却视而不见?说明观察力有待提高啊!
阅读全文
WEB应用

Haproxy进阶管理:命令行控制后端节点上下线

很多业务系统都用到了Haproxy这个高性能反向代理负载均衡器。在日常运维当中,Haproxy后端节点的上(接入)、下(剔除)线操作绝对是家常便饭,而且人工重启的时候经常有胆颤心惊的感觉。 下面分享一种命令行操作Haproxy后端节点平滑上下线的技巧。 一、新增配置 Haproxy自带了一个非常实用的管理页面,我们可以在harpxoy.cfg新增如下配置,开启Haproxy监控管理页面功能: 配置后,重启Haproxy,访问 http://ipaddress:8080/admin,使用admin/admin登陆之后就能看到管理页面了: 二、管理功能 因为我们还配置了管理功能,所以在各个backend都能看到如下管理功能: 我们在左侧勾选好对应的后端节点,选择需要转换的状态点击Apply就能完成后端节点的状态切换。 三、平滑发布 对于平滑发布来说,这里用得比较多的2个选项是READY(就绪状态)和MAINT(维护状态)。 READY 表示被勾选的节点已经完成维护,Apply进入就绪状态后,Haproxy会自动发起健康检查,如果检查通过,这些节点将进入映射状态,接受映射请求了。 MAINT 表示被勾选的节点需要进行维护,Apply进入维护状态后,Haproxy将会停止往这些节点转发请求,并等待已有的请求结束连接。 通过这个功能,我们就能对业务进行从容发布了,比如我们有一个业务有2个节点,我们可以先将其中一个节点改为MAINT状态,刷新Haproxy管理页面,当看到Session里面的Cur(当前连接)为0个时,我们就可以从容的对这个节点进行发布、重启等维护操作,完成维护后我们在将这个节点改为READY状态即可。接着,我们同样操作剩下节点即可(节点剔除后带来的性能下降问题,这里就不展开了讨论了)。 四、命令行操作 很明显,这个功能非常实用,但是并不方便,因为需要手工操作,没法嵌入到自动化发布流程当中。不过通过分析POST请求,可以得出curl命令行操作方法: s 表示后端标签名 action 表示状态 b 表示backend标签名 通过测试,得出curl发起请求格式如下: 比如,如果Haproxy有一个后端如下配置: 那么,业务系统发布之前,我们将192.168.1.1这个节点改为维护状态,则如下发起请求即可: Ps:要注意的是,这个POST参数必须URL转码,比如存在冒号【:】,需要转换为 %3A才行。 业务系统发布之后,我们再发起node1上线请求: 后面我们只需要重复操作node2节点的上下线即可完成无损发布了。这一整套动作就可以整合到自动化发布流程当中,不再需要人工介入。 五、小结 本文介绍了Haproxy开启管理功能的配置方法以及命令行操作后端上下线的技巧,为程序平滑部署、系统自动化运维提供了一种更加简单的解决方案。 拓展:在复杂的业务场景中,可能用到了etcd+confd + haproxy的统一配置管理方案,原理是通过更改Haproxy配置,然后热重启Haproxy(-st 指令)来上下线节点,是非常不错的方案!不过,根据我个人经验,在高频业务场景中,剔除后端节点再热重启Haproxy,可能出现业务请求异常问题。
阅读全文
WEB应用

小网站最简单实用的动静分离优化方案

很久没写文章了,博客已经长草了,今天挤点时间分享一些小干货,也是回应一下不少站长朋友的留言问题。 有不少站长朋友问张戈博客的静态文件为啥是另外一个域名?有啥好处?如何实现? 其实这算是一种动静分离的做法,不过我这里用了偷懒的办法实现,而非彻底的动静分离,不过最终效果的区别并不大。 先啰嗦一下动静分离的概念和好处。 一、动静分离 我们的网站简单来说分为2种数据资源,一种是动态的数据,即PHP等程序语言实时吐出来的数据,在网页内容上主要是HTML代码,另一种则是静态资源,比如图片、css、js、视频等(当然,图片等资源也可能是实时动态生成的,比如PHP缩略图,这里就不展开讨论了)。 一般网站初建,因为流量小、业务简单等原因,都默认将两种数据放到一台服务器上提供服务。访问量大到一定程度之后,就可能出现带宽不足、甚至磁盘高IO等问题。这时,作为运维工程师或者架构师就会给出动静分离优化的建议了。做法并不复杂,运维工程师会将图片等静态资源同步到另一台WEB服务器,然后新增绑定一个二级域名,比如static.domain.com,最后让开发将网页代码中的静态资源替换成这个二级域名即可。 这样一来,图片等静态资源的访问就落到了新增的服务器上,从而分担了大部分访问数据流量和IO负载,我们还可以针对性的给静态资源WEB做一些优化,比如JS/CSS/图片压缩、内存缓存、浏览器缓存等等。进一步,我们还可以将静态资源接入CDN,实现资源就近访问。 可以用一张图来表示: 二、好处分析 1、常规做法的好处 从上文的通俗解释来看,很明显的一个好处就是解决带宽问题,像博客圈子里的服务器,绝大部分主机都是国内的小管道云服务器(带宽小于2M),并发访问量上来之后,就能很明显的感觉到带宽成为了瓶颈。 不过,博客圈大部分都是“一穷二白”,一般都不愿意再买一台服务器来专门承载静态资源,而且多台服务器之间的数据同步等日常维护问题也变相提高了折腾门槛。因此,国内大部分小博客都热衷于套一层CDN来解决带宽问题,确实是一个很好的解决方案。在《分享张戈博客的WordPress优化方案,缓解国内云服务器配置低下的问题》一文中,也是特别提到了这一茬。 2、本文分享方案的好处 上文说张戈博客使用了一种偷懒的方案,做法很简单:网站只用一台服务器,但是会新增绑定一个和主站完全不一样的二级域名,比如张戈博客主站是zhang.ge,而二级域名用的是 res.zgboke.com,并且给这个二级域名套了一层CDN。 这样做又有什么好处?和直接套一层CDN(比如云加速)有什么不同? 第1个好处:显而易见比常规动静分离成本更低,分离前后服务器数量不变; 第2个好处:解决主站直接使用一级域名带来的cookies“污染”,即静态资源不会再带上主站的cookies数据,减小了体积。这个在上文提到的优化方案一文中也着重提到,详细就不再赘述; 第3个好处:这个方案对于网站内容没法备案又想体验国内CDN加速快感的网站绝对是福音!很多网站因为内容特殊(邪恶脸)没法完成备案,所以无法使用国内的CDN,那么就可以用本文分享的方法,直接花钱买一个备过案的垃圾域名,做好动静分离,然后将这个二级域名接入国内的CDN,网站速度绝对可以得到质的飞跃,是不是爽歪歪? 第4个好处:这个和第二个比较类似,主要针对在百度云加速购买了付费套餐的朋友。因为,对于一般流量的网站,你只需要在百度云加速给一个域名购买一个专业版,那么就可以分离多个二级域名给N个网站使用,那么多个人合买一个专业版完全不成问题吧?当然,现在百度云加速也学聪明了,现在流量限制50G/天(我开始用这个方案的时候无此限制),但是对于普通网站已经很够用了!!! 第5个好处:CDN配置更加比较简单,因为这种静态二级域名,接入CDN之后,完全不用考虑缓存规则的问题,因为直接设置成全部缓存就好了!简单粗暴。 三、部署教程 啰嗦了好长篇幅,下面给出具体做法! 原理贼简单,就是在服务器上利用反向代理新增了一个新网站,内容则是反向代理了我们的主站,从而实现了2个域名共享相同的网站数据。 Vhost示范规则如下: 这样就在本地新增了和主站共用一份数据的二级域名,只提供静态资源访问,其他访问都跳到主站对应页面。 完成新增后,只需要使用以前分享的七牛CDN代码或者CDN插件,将网站的静态资源替换为这个新二级域名,比如以前分享的纯代码版,加到functions.php即可完成替换: 完成部署后,我们网站的前台页面中的图片、js等静态资源链接就全部换成了新的二级域名了。 Tips:其他部署方法 如果网站未启用https,完全可以更简单,只需要在我们的主站vhost配置的server_name参数中新增一个域名即可,比如: server_name zhang.ge res.zgboke.com; 当然,强迫症患儿们,还可以根据域名判断,来进行上述Vhost类似跳转,此处就不展开了。 同样的,对于虚拟主机来说,只需要在虚拟主机控制面板中新增一个二级域名绑定即可。但是这个方法不适用于https站点,因为一般的https证书并不能用于2个完全不一样域名。 最后,我们将这个二级域名接入CDN即可,接入方法就不啰嗦了,自己折腾吧!
阅读全文
操作系统

替代crontab,统一定时任务管理系统cronsun简介

cronsun 是一个分布式任务系统,单个节点和 Linux 机器上的 crontab 近似。是为了解决多台 Linux  机器上 crontab 任务管理不方便的问题,同时提供任务高可用的支持(当某个节点死机的时候可以自动调度到正常的节点执行)。支持界面管理机器上的任务,支持任务失败邮件提醒,安装简单,使用方便,是替换 crontab 一个不错的选择。
阅读全文