【51CTO.com原创稿件】远程控制技术背后有哪些数据需求?如何用缓存技术存储实时数据?新缓存体系不稳定怎么办?MySQL InnoDB memcached plugin出来挺久的了,网上还没见到国内有把它用到生产环境的实例,我们特此邀请到向日葵技术总监张小峰老师做直播分享。
直播间:QQ群370892523、②群312724475、③群542270018、④群627843829
内容简介:应用背景介绍、向日葵远程控制技术的数据需求、缓存优化史、从memcached到ttserver、memcached、Ttserver、MySQL InnoDB memcached plugin等。
昨天看到群里有人说运维就是把程序员的代码copy到服务器上,我觉得完全不是这样的,至少在我们这里不是;只会上程序的运维是不合格的,他要能在现有程序上优化系统结构,能对开发提出当前的不足以及优化方案和为运维服务的开发需求。
(一)应用背景介绍
作为提供各种互联网服务且具有海量用户的的Oray,我们也一直在实践各种新技术新架构;缓存方面我们从memcached、ttserver、redis等都有较多应用,其中redis我们的dns体系中有着很深度的集成使用;MySQL InnoDB memcached plugin出来挺久的了,网上还没见到国内有把它用到生产环境的实例,我今天就给大家说下小白鼠体验。
但很大一部分用户使用我们的花生壳也就是为了远程操作电脑,所以2010年,在我们埋头苦干了1年多后推出了向日葵远程控制产品,这个产品的基本功能就是让用户不需要关心IP端口等技术知识就可以远程管理控制他的所有电脑,这个产品主要依赖以下技术:
通过关系型数据库管理用户主机清单;
使用长连接维持被控在线状态;
P2P通信技术传输控制信号以及图像信号;
优化的算法尽可能的降低用户带宽占用以及提高图像质量;
其他周边技术,如HTML5免插件远程控制、远程开机等。
客户端、操作系统以及相关远控技术问题我们今天先不探讨,向日葵也不是一个简单的C/S结构软件,我们需要像聊天服务器那样与客户端进行实时交互,而客户端在线量一直在凶猛的增长中,我们的系统以及运维和开发团队也就不停的迭代并成长。
(二)向日葵远程控制技术的数据需求
上面提到,向日葵使用关系型数据库存贮某一个用户拥有哪些主机,以及这些主机的具体相关信息;在此同时,我们也需要临时存储一些关键的实时数据:
主机鉴权信息
主机在线状态
如何连接主机
其实刚发布向日葵的几个月我们是把它们同时放在关系数据库里的,那个时候主要考虑的也不是服务端的性能问题,而是整个系统跑通,只是我们的数据库后来吃不消了,这一段经历不长,说真的也没啥好讲的。
(三)缓存优化史
既然存在关系数据库中不合适,我们就开始用各种缓存技术来存储这种实时数据。
(三.1)从memcached到ttserver
(三.1.1)memcached
***代的主机状态数据缓存化,我们把它放在了memcached,整个客户端的登陆过程是这样的(里头略去了各种错误处理及异常以及各种附属架构,比如负载均衡或者备份等):
把状态等需要频繁访问的数据放到缓存后,这个大框架到现在也还基本上是这样,API负责所有跟持久化DB的交互操作,长连接只负责跟memcached的通信,这样也避免了我们的DB有过多角色参与读写;另外这个时候我们只有一台memcached服务器,因为我们算过16G内存大约可以放上亿的主机信息。
在经历了两次memcached崩溃后我们也崩溃了,memcached的数据是完全放在内存里的,崩溃后所有主机全部会变成不在线且只能通过重启所有服务器解决,而重启所有服务器意味着所有原先在线客户端都得全部重新登陆一次,这个过程会极其漫长,以小时计的。
(三.1.2)ttserver
我们要改进了,顺其自然的,我们想到了ttserver,ttserver可以在崩溃重启后恢复数据且具备主备同步功能,而丢失那部分数据我们可以在客户端登陆时从DB里自动恢复出来;
由于ttserver跟memcached通信协议上完全兼容,但为了避免全局性的灾难,我们在完成多cache服务优化后,新系统很快就上线了。
新缓存体系的结构长这样的:
完全堆叠式的设计,理论上也是可以***扩容的,但我们没意识到ttserver几个大问题:
ttserver不支持key过期的,需要开启table database模式,并通过lua脚本的方式来实现,但该模式ttserver的运行性能相当差,并且在数据很大的时候出现不稳定的现象。
这个不稳定现象我们不凑巧也遇到了:由于它会自动把不频繁读写的数据swap到磁盘,它倒不会像memcached那样容易崩溃,但它会偶尔神经质似的卡;卡到什么程度呢:手工上去敲个get,大概要几百ms才会得到结果;而我们对ttserver做了很多优化依旧于事无补。前两次卡死,重启能解决,但后来,我们不得不把它保存的文件彻底删除才能恢复性能,这不又回到了memcached时代吗?怎么办?
(三.2)MySQL InnoDB memcached plugin
在我们出现ttserver危机的时候,已经没有什么能让我更绞尽脑汁的事情了,天天到各社区调研,某个偶然的机会,我看到了MySQL居然支持memcached插件,这真是个神奇的组合:
传统关系型数据库在大数据时代的性能与扩展,离不开内存与分布式这两大主题。
在传统的关系型数据库中,Oracle的Timesten,SQL Server的Hekaton,都是选择与内存数据库相集合,但实际上却少有突出的应用场景。而MySQL嵌入nosql ,在性能与管理、分析上达到互补,则是更为有意义的结合。
MySQL5.6.6后开始内嵌 memcached 的支持,在MySQL 5.7较新的版本性能大幅提升,有测试表明在48核只读环境下QPS可以达到百万以上。
借用下MySQL官方的结构图:
我们先来看一下memcached plugin的安装:
下载mysql5.7.17 源码包 wget http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-community-5.7.17-1.el6.src.rpm
因为是一个插件,开启memcached plugin功能,需要在编译安装时添加:
-DWITH_INNODB_MEMCACHED=ON
安装启动后执行配置:
memcached plugin相关配置表:
innodb_memcache.config_options --配置分割符、引用符
innodb_memcache.cache_policies --根据需要设置缓存策略
innodb_memcache.containers --设置表结构:key、value大小,过期时间等
在mysql的配置文件my.cnf中通常需要设置以下参数(注意在启动插件后配置,否则mysqld启动报错),主要是配置分配给memcached 的内存大小以及开启写binlog,如果需要指定其他端口,如11212 在loose-daemon_memcached_option参数添加 ' -p11212'
而daemon_memcached_r_batch_size、daemon_memcached_w_batch_size 默认为1,这里也建议设置为1:
MySQL memcached plugin 特点:
1.数据直接读写请求innodb存储引擎,不需要经过SQL层,不需要进行解析编译。
2.由MySQL buffer pool 管理内存缓存数据。
3.可以把数据存入多个表,可进行多列数据合并为一个value。
4.可以通过SQL对数据进行查询、分析、维护。(在过期时间字段添加索引,通过mysql job进行过期数据删除)
5.可以利用MySQL灵活的主从架构。
性能测试对比:
我们采用4核进行测试对比,MySQL memcached plugin 与 ttserver (hash模式)性能相当,QPS可以达到7万/秒。比 ttserver (btree模式)高出3倍以上。
memaslap的测试存在一些缺陷,这里仅供大致参考:
实际上,在网络延迟上,QPS性能将大打折扣,所以要将应用部署在同个内网以降低网络延迟瓶颈,轻松应对每天上亿次的QPS请求,在接近1万/s的QPS并发访问下依旧表现稳定。
以下是其中一个MySQL Memcahced 运行情况:
在我们一个很NB的DBA的设计和操控下,新架构上线还是比较顺利的:
大家注意到,图中多了一个角色,magent,在这次架构优化中,我们在应用和MySQL memcached中间加了一层magent,这东西大家百度下到处都有介绍,但原版其实是有不少bug的,比如buffer大小问题;加上这东西的好处:
1、通过对magent的改造,实现HA,当ma后端cache某一台down掉后ma可以自动切换;系统管理员晚上终于可以安心的睡觉了。
2、MySQL memcached plugin 不支持multi get/set (在未来的版本中会支持)。通过magent解决。
3、由于mysql memcached plugin 存在一些bug,5.7.18做了一些修复,但不够完善。借助magent便于控制和维护。
此架构优势:
扩展性强。逐步提升应对高并发,采取多主架构,配合magent实现高可用。
我们做的优化:
MySQL 5.7.17 前的版本,不建议设置 daemon_memcached_r_batch_size 大于1,容易遭遇 bug 导致 MySQL Crashed。同时建议innodb_api_bk_commit_interval设置为稍大一点的值。默认为5。存在get会话的情况下,对 daemon_memcached 插件进行重启,也会导致MySQL Crashed,重启插件时要确保没有其他会话。
禁止flush_all权限操作:
update cache_policies set flush_policy='disabled';
尾声
其实上面说了那么多细节抑或还不够细节的东西,都是围绕着缓存架构的优化。在这么多年从事软硬开发与架构设计的实际工作中,我深刻的体会到架构的重要性,不管多NB的代码和算法,多NB的硬件,系统架构不好的话你的运行结果一样糟糕。这里的架构不仅仅包含服务器层面以及系统运维上的,架构无处不在,从软件架构到硬件架构,从网站架构到数据库架构,从通信架构到服务整体架构,包括本文提到的缓存架构,甚至细化到C++开发层的class封装与相互调用,都有着架构及其优化的存在。做任何一件部署与实际的开发前,我们都要有做好架构这个潜在意识,去考虑一个好的架构再动手构建,当然我们都不可避免的会踩到坑,不要害怕,持续改进就好。
正是这样的态度下,我们又相继推出无网远控的硬件“向日葵控控”这样创新性的产品。有了这一路走来的经验,不管产品从软件延伸硬件,我们也有自己的一套优化方案,有机会我们继续分享。
Q&A
1、Q:PHP-watson-广州::
A:向日葵-技术总监-上海:
redis单线程设计机制只能利用一个核,CPU利用度有限,我认为在高并发上比不上memcached,并且对数据比较大的情况性能不是很好,内存使用率管理上也没有memcached优秀,value在大于1k之后性能下降明显。
Q:python运维开发_howhy:
A:向日葵-技术总监-上海:
Q:python运维开发_howhy:
A:向日葵-技术总监-上海:
Q:数据库管理-矢神-广州:
A:向日葵-技术总监-上海:
【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】