过程: 得到插件库路径 找对应 *** 作系统的udf库文件 利用udf库文件加载函数并执行命令
1,得到插件库路径
?
1
2
3
4
5
6
7
mysql>show variables like "%plugin%"
+---------------+-----------------------+
| Variable_name | Value |
+---------------+-----------------------+
| plugin_dir | /usr/lib/mysql/plugin |
+---------------+-----------------------+
1 row in set (0.00 sec)
2,找对应 *** 作系统的udf库文件
因为自己测试,看了下自己系统的版本,64位
?
1
2
root@bt:~# uname -a
Linux bt 3.2.6 #1 SMP Fri Feb 17 10:34:20 EST 2012 x86_64 GNU/Linux
对于udf文件,在sqlmap工具中自带就有,只要找对应 *** 作系统的版本即可
?
1
2
3
4
5
6
root@bt:/pentest/database/sqlmap/udf/mysql# ls
linux windows
root@bt:/pentest/database/sqlmap/udf/mysql/linux# ls
32 64
root@bt:/pentest/database/sqlmap/udf/mysql/linux/64# ls
lib_mysqludf_sys.so
3,利用udf库文件加载函数并执行命令
首先要得到udf库文件的十六进制格式,可在本地通过
对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached、FileSystem等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的NoSQL数据库,就非常适合担任实时数据的容器。但是往往又有数据可靠性的需求,采用MySQL作为数据存储,不会因为内存问题而引起数据丢失,同时也可以利用关系数据库的特性实现很多功能。所以就会很自然的想到是否可以采用MySQL作为数据存储引擎,Redis则作为Cache。而这种需求目前还没有看到有特别成熟的解决方案或工具,因此采用Gearman+PHP+MySQLUDF的组合异步实现MySQL到Redis的数据复制。MySQL到Redis数据复制方案无论MySQL还是Redis,自身都带有数据同步的机制,比较常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog来实现的,这样的数据复制其实还是一个异步过程,只不过当服务器都在同一内网时,异步的延迟几乎可以忽略。那么理论上也可以用同样方式,分析MySQL的binlog文件并将数据插入Redis。但是这需要对binlog文件以及MySQL有非常深入的理解,同时由于binlog存在Statement/Row/Mixedlevel多种形式,分析binlog实现同步的工作量是非常大的。因此这里选择了一种开发成本更加低廉的方式,借用已经比较成熟的MySQLUDF,将MySQL数据首先放入Gearman中,然后通过一个自己编写的PHPGearmanWorker,将数据同步到Redis。比分析binlog的方式增加了不少流程,但是实现成本更低,更容易 *** 作。Gearman的安装与使用Gearman是一个支持分布式的任务分发框架。设计简洁,获得了非常广泛的支持。一个典型的Gearman应用包括以下这些部分:GearmanJobServer:Gearman核心程序,需要编译安装并以守护进程形式运行在后台GearmanClient:可以理解为任务的收件员,比如在后台执行一个发送邮件的任务,可以在程序中调用一个GearmanClient并传入邮件的信息,然后就可以将执行结果立即展示给用户,而任务本身会慢慢在后台运行。GearmanWorker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行,GearmanWorker接收到GearmanClient传递的任务内容后,会按顺序处理。以前曾经介绍过类似的后台任务处理项目Resque。两者的设计其实非常接近,简单可以类比为:GearmanJobServer:对应Resque的Redis部分GearmanClient:对应Resque的Queue *** 作GearmanWorker:对应Resque的Worker和Job这里之所以选择Gearman而不是Resque是因为Gearman提供了比较好用的MySQLUDF,工作量更小。安装Gearman及PHPGearman扩展以下均以Ubuntu12.04为例。apt-getinstallgearmangearman-serverlibgearman-dev检查Gearman的运行状况:/etc/init.d/gearman-job-serverstatus*gearmandisrunning说明Gearman已经安装成功。PHP的Gearman扩展可以通过pecl直接安装peclinstallgearmanecho"extension=gearman.so">/etc/php5/conf.d/gearman.iniservicephp5-fpmrestart但是实测发现ubuntu默认安装的gearman版本过低,直接运行peclinstallgearman会报错configure:error:libgearmanversion1.1.0orlaterrequired因此Gearman+PHP扩展建议通过编译方式安装,这里为了简单说明,选择安装旧版本扩展:peclinstallgearman-1.0.3Gearman+PHP实例为了更容易理解后文Gearman的运行流程,这里不妨从一个最简单的Gearman实例来说明,比如要进行一个文件处理的 *** 作,首先编写一个GearmanClient并命名为client.php:addServer()$client->doBackground('writeLog','Logcontent')echo'文件已经在后台 *** 作'运行这个文件,相当于模拟用户请求一个Web页面后,将处理结束的信息返回用户:phpclient.php查看一下Gearman的状况:(echostatussleep0.1)|netcat127.0.0.14730可以看到输出为writeLog100.说明已经在Gearman中建立了一个名为writeLog的任务,并且有1个任务在队列等待中。而上面的4列分别代表当前的Gearman的运行状态:任务名称在等待队列中的任务正在运行的任务正在运行的Worker进程可以使用watch进行实时监控:watch-n1"(echostatussleep0.1)|nc127.0.0.14730"然后我们需要编写一个GearmanWorker命名为worker.php:addServer()$worker->addFunction('writeLog','writeLog')while($worker->work())functionwriteLog($job){$log=$job->workload()file_put_contents(__DIR__.'/gearman.log',$log."\n",FILE_APPEND|LOCK_EX)}Worker使用一个while死循环实现守护进程,运行phpworker.php可以看到Gearman状态变为:writeLog001同时查看同目录下gearman.log,内容应为从Client传入的值Logcontent。通过MySQLUDF+Trigger同步数据到GearmanMySQL要实现与外部程序互通的最好方式还是通过MySQLUDF(MySQLuserdefinedfunctions)来实现。为了让MySQL能将数据传入Gearman,这里使用了lib_mysqludf_json和gearman-mysql-udf的组合。安装lib_mysqludf_json使用lib_mysqludf_json的原因是因为Gearman只接受字符串作为入口参数,可以通过lib_mysqludf_json将MySQL中的数据编码为JSON字符串apt-getinstalllibmysqlclient-devwget/mysqludf/lib_mysqludf_json/archive/master.zipunzipmaster.zipcdlib_mysqludf_json-master/rmlib_mysqludf_json.sogcc$(mysql_config--cflags)-shared-fPIC-olib_mysqludf_json.solib_mysqludf_json.c可以看到重新编译生成了lib_mysqludf_json.so文件,此时需要查看MySQL的插件安装路径:mysql-uroot-pPASSWORD--execute="showvariableslike'%plugin%'"+---------------+------------------------+|Variable_name|Value|+---------------+------------------------+|plugin_dir|/usr/lib/mysql/plugin/|+---------------+------------------------+然后将lib_mysqludf_json.so文件复制到对应位置:cplib_mysqludf_json.so/usr/lib/mysql/plugin/最后登入MySQL运行语句注册UDF函数:CREATEFUNCTIONjson_objectRETURNSSTRINGSONAME'lib_mysqludf_json.so'安装gearman-mysql-udf方法几乎一样:apt-getinstalllibgearman-devwgetmake&&makeinstall登入MySQL运行语句注册UDF函数:CREATEFUNCTIONgman_do_backgroundRETURNSSTRINGSONAME'libgearman_mysql_udf.so'CREATEFUNCTIONgman_servers_setRETURNSSTRINGSONAME'libgearman_mysql_udf.so'最后指定Gearman服务器的信息:SELECTgman_servers_set('127.0.0.1:4730')通过MySQL触发器实现数据同步最终同步哪些数据,同步的条件,还是需要根据实际情况决定,比如将数据表data的数据在每次更新时同步,那么编写Trigger如下:DELIMITER$$CREATETRIGGERdatatoredisAFTERUPDATEONdataFOREACHROWBEGINSET@ret=gman_do_background('syncToRedis',json_object(NEW.idas`id`,NEW.volumeas`volume`))END$$DELIMITER尝试在数据库中更新一条数据查看Gearman是否生效。GearmanPHPWorker将MySQL数据异步复制到RedisRedis作为时下当热的NoSQL缓存解决方案无需过多介绍,其安装及使用也非常简单:apt-getinstallredis-serverpeclinstallredisecho"extension=redis.so">/etc/php5/conf.d/redis.ini然后编写一个GearmanWorker:redis_worker.php#!/usr/bin/envphpaddServer()$worker->addFunction('syncToRedis','syncToRedis')$redis=newRedis()$redis->connect('127.0.0.1',6379)while($worker->work())functionsyncToRedis($job){global$redis$workString=$job->workload()$work=json_decode($workString)if(!isset($work->id)){returnfalse}$redis->set($work->id,$workString)}最后需要将Worker在后台运行:nohupphpredis_worker.php&通过这种方式将MySQL数据复制到Redis,经测试单Worker基本可以瞬时完成。背景
在上一篇推文中,我们介绍了 MySQL Group Replication 8.0.16 支持信息碎片化功能来增强大型事务处理能力。
如果您想在组复制中使用该功能,则任何组成员的版本都不能低于 8.0.16!
简单地说就是由于低版本协议上不支持。MySQL 8.0.16 的组通讯开始支持新协议,简称“分段协议”,之前的版本中只有一种“压缩协议”。
如果多个成员想加入复制组,那么在协议匹配上遵循以下原则:
现有复制组成员和新加入成员版本相同,加入成功。
低版本成员想加入高版本的组会被驱逐,加入失败。
高版本的成员想加入低版本的组,单独加入成功,多个加入失败。
例如:
一个 MySQL Server 8.0.16 实例可以成功加入使用通信协议版本 5.7.24 的组。
一个 MySQL Server 5.7.24 实例无法成功加入使用通信协议版本 8.0.16 的组。
两个 MySQL Server 8.0.16 实例无法同时加入使用通信协议版本 5.7.24 的组。
两个 MySQL Server 8.0.16 实例可以同时加入使用通信协议版本 8.0.16 的组。
新增 UDF
为了能让高版本的复制组更便于加入低版本的成员,MySQL 8.0.16 新增两个 UDF。
您可以使用两个新的 UDF 命令去管理组通信协议:
1. group_replication_set_communication_protocol(new_protocol)
设置组复制通讯协议版本
SELECT group_replication_set_communication_protocol("8.0.15")
填入一个所有成员都支持的版本号,即:new_protocol ≤ 所有成员的 MySQL版本。
new_protocol 格式:major.minor.patch (主版本号.次版本号.发布版本号)例如:8.0.15。
2. group_replication_get_communication_protocol()
获取复制中最旧成员的 MySQL 版本号
SELECT group_replication_get_communication_protocol() +------------------------------------------------+ | group_replication_get_communication_protocol() | +------------------------------------------------+ | 5.7.14 | +------------------------------------------------+
获取的版本号可能与设置的值不一致,但不一致的版本之间组复制协议是一样的。
返回结果格式:major.minor.patch (主版本号.次版本号.发布版本号)例如:8.0.15。
以上两个 UDF 对全部组成员有效,主机或从机上均可执行。
结论
若想使用信息碎片功能。建议将组复制成员全部升级为 8.0.16。
若组内成员版本仅有部分为 8.0.16,可以用两个新的函数来让高版本的成员保持与其它成员组协议一致。
请点击输入图片描述
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)