通过UDFs实现Memcached与Mysql的自动更新

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

                           通过UDFs实现Memcached与Mysql的自动更新

一:UDFs使用简介:

    UDFs是User Defined Functions的缩写,表示Mysql的用户定义函数,应用程序可以利用这些函数从Mysql5.0以上的版本的数据库中访问Memcached写入或者获取数据。此外,Mysql从5.1版本开始支持触发器,从而可以在触发器中使用UDFs直接更新Memcached的内容,这种方式降低了应用程序设计与编写的复杂性。

二:UDFs的安装:

    安装UDFs需要在数据库服务器上安装两个包,分别是libmemcached和memcached-functions-mysql,这两个包可以从http://download.tangent.org/下载。

1:源码包编译安装Mysql

安装cmake
MySQL从5.5版本开始,通过./configure进行编译配置方式已经被取消,取而代之的是cmake工具。
因此,我们首先要在系统中源码编译安装cmake工具。

[root@memcached ~]# wget http://www.cmake.org/files/v2.8/cmake-2.8.4.tar.gz

[root@memcached ~]# tar zxvf cmake-2.8.4.tar.gz

[root@memcached ~]# cd cmake-2.8.4
[root@memcached cmake-2.8.4]# ./configure

[root@memcached cmake-2.8.4]# make && make install

确保一下软件已安装

通过 rpm -qa | grep name 的方式验证以下软件包是否已全部安装。
gcc* gcc-c++* autoconf* automake* zlib* libxml* ncurses-devel* libgcrypt* libtool*

安装前的系统设置

建立mysql安装目录及数据存放目录

[root@memcached ~]# mkdir /usr/local/mysql
[root@memcached ~]# mkdir /usr/local/mysql/data

创建用户及组:

[root@memcached ~]# groupadd mysql
[root@memcached ~]# useradd -g mysql mysql

赋予数据存放目录的权限:

[root@memcached ~]# chown -R mysql:mysql /usr/local/mysql/data/

从configure变更为cmake:

[root@memcached ~]# tar zxvf mysql-5.5.20.tar.gz

[root@memcached ~]# cd mysql-5.5.20
[root@memcached mysql-5.5.20]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DSYSCONFDIR=/usr/local/mysql/etc \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DMYSQL_TCP_PORT=3306 \
-DMYSQL_UNIX_ADDR=/tmp/mysqld.sock \
-DMYSQL_USER=mysql \
-DEXTRA_CHARSETS=all \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_EMBEDDED_SERVER=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1

[root@memcached mysql-5.5.20]# make && make install

配置并初始化数据库

[root@memcached ~]# mkdir /usr/local/mysql/log
[root@memcached ~]# mkdir /usr/local/mysql/etc
[root@memcached ~]# cd mysql-5.5.20
[root@memcached mysql-5.5.20]# cp support-files/my-medium.cnf /usr/local/mysql/etc/my.cnf

初始化数据库
执行前需赋给scripts/mysql_install_db文件执行权限:

[root@memcached mysql-5.5.20]# chmod 755 scripts/mysql_install_db

[root@memcached mysql-5.5.20]# scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/

创建管理MySQL数据库的shell脚本:

[root@memcached mysql-5.5.20]# mkdir /usr/local/mysql/init.d

[root@memcached mysql-5.5.20]# cp support-files/mysql.server /usr/local/mysql/init.d/mysql

赋予shell脚本可执行权限:

[root@memcached mysql-5.5.20]# chmod +x /usr/local/mysql/init.d/mysql

启动mysql:

[root@memcached mysql-5.5.20]# /usr/local/mysql/init.d/mysql start
Starting MySQL..                                           [  OK  ]

通过命令行登录管理MySQL服务器(提示输入密码时直接回车):

[root@memcached ~]# /usr/local/mysql/bin/mysql -uroot -p -S /tmp/mysqld.sock

输入以下SQL语句,创建一个具有root权限的用户(admin)和密码(12345678):

mysql> GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' IDENTIFIED BY '12345678';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON *.* TO 'admin'@'127.0.0.1' IDENTIFIED BY '12345678';
Query OK, 0 rows affected (0.00 sec)

为root帐户设置初始密码:

[root@memcached ~]# /usr/local/mysql/bin/mysqladmin -uroot password 'centos'

删除本机匿名连接的空密码帐号:

[root@memcached ~]# /usr/local/mysql/bin/mysql -uroot -pcentos mysql

mysql> select Host,User,Password from user; //看下有哪些是空密码的账户

mysql> delete from user where password='';  //执行删除

mysql> select Host,User,Password from user;   //确认下

OK了,mysql安装完毕。

------------------------------------------------------------------------------------------

安装libevent+memcache:

Memcached的安装:

1:安装Memcached前需要先安装libevent:

[root@memcached ~]# wget -b http://www.monkey.org/~provos/libevent-1.4.4-stable.tar.gz

[root@memcached ~]# tail -5 wget-log |sed '/^$/d'   ##查看是否下载正确

[root@memcached ~]# tar zxf libevent-1.4.4-stable.tar.gz 
[root@memcached ~]# cd libevent-1.4.4-stable
[root@memcached libevent-1.4.4-stable]# ./configure 
[root@memcached libevent-1.4.4-stable]# make && make install

2:安装Memcached的过程:

[root@memcached ~]# wget -b http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz

[root@memcached ~]# tail -5 wget-log.1 |sed '/^$/d'

[root@memcached ~]# tar zxf memcached-1.4.5.tar.gz 
[root@memcached ~]# cd memcached-1.4.5
[root@memcached memcached-1.4.5]# ./configure

[root@memcached memcached-1.4.5]# make && make install

##安装完成后,Memcached的默认目录为/usr/local/bin/memcached

3:启动Memcached:

[root@memcached ~]# /usr/local/bin/memcached -m 100m -p 11211 -d -u root -P /var/run/memcached.pid -c 512

有时会出现找不到libevent文件,此时将/usr/local/lib 加入到/etc/ld.so.conf中即可。

[root@memcached ~]# echo "/usr/local/lib" >> /etc/ld.so.conf

[root@memcached ~]# ldconfig

4:关闭Memcached:

[root@memcached ~]# kill `cat /var/run/memcached.pid`

————————————————————————————————————

安装libmencached:

[root@memcached ~]# wget http://download.tangent.org/libmemcached-0.34.tar.gz

[root@memcached ~]# tar zxvf libmemcached-0.34.tar.gz

[root@memcached ~]# cd libmemcached-0.34

[root@memcached libmemcached-0.34]# ./configure --prefix=/usr/local/libmemcached34 --with-memcached=/usr/local/bin/memcached

[root@memcached libmemcached-0.34]# make && make install

[root@memcached libmemcached-0.34]# echo "/usr/local/libmemcached34/" >> /etc/ld.so.conf

[root@memcached libmemcached-0.34]# ldconfig

-------------------------------------------------------------------------------

安装memcached_functions_mysql: 

[root@memcached ~]# wget http://download.tangent.org/memcached_functions_mysql-0.9.tar.gz

[root@memcached ~]# tar zxf memcached_functions_mysql-0.9.tar.gz

[root@memcached ~]# cd memcached_functions_mysql-0.9

[root@memcached memcached_functions_mysql-0.9]# ./configure --prefix=/usr/local/memcache_mysql --with-mysql=/usr/local/mysql/bin/mysql_config --with-libmemcached=/usr/local/libmemcached34

[root@memcached memcached_functions_mysql-0.9]# make && make install

拷贝lib文件到mysql的plugin下面:

[root@memcached memcached_functions_mysql-0.9]# cp /usr/local/memcache_mysql/lib/libmemcached_functions* /usr/local/mysql/lib/plugin

添加memcache UDF 函数:

[root@memcached memcached_functions_mysql-0.9]# /usr/local/mysql/bin/mysql -uroot -pcentos

mysql> source sql/install_functions.sql;

mysql> select * from mysql.func;

+------------------------------+-----+---------------------------------+----------+
| name                         | ret | dl                              | type     |
+------------------------------+-----+---------------------------------+----------+
| memc_add                     |   2 | libmemcached_functions_mysql.so | function |
| memc_add_by_key              |   2 | libmemcached_functions_mysql.so | function |
| memc_servers_set             |   2 | libmemcached_functions_mysql.so | function |
| memc_server_count            |   2 | libmemcached_functions_mysql.so | function |
| memc_set                     |   2 | libmemcached_functions_mysql.so | function |
| memc_set_by_key              |   2 | libmemcached_functions_mysql.so | function |
| memc_cas                     |   2 | libmemcached_functions_mysql.so | function |
| memc_cas_by_key              |   2 | libmemcached_functions_mysql.so | function |
| memc_get                     |   0 | libmemcached_functions_mysql.so | function |
| memc_get_by_key              |   0 | libmemcached_functions_mysql.so | function |
| memc_delete                  |   2 | libmemcached_functions_mysql.so | function |
| memc_delete_by_key           |   2 | libmemcached_functions_mysql.so | function |
| memc_append                  |   2 | libmemcached_functions_mysql.so | function |
| memc_append_by_key           |   2 | libmemcached_functions_mysql.so | function |
| memc_prepend                 |   2 | libmemcached_functions_mysql.so | function |
| memc_prepend_by_key          |   2 | libmemcached_functions_mysql.so | function |
| memc_increment               |   2 | libmemcached_functions_mysql.so | function |
| memc_decrement               |   2 | libmemcached_functions_mysql.so | function |
| memc_replace                 |   2 | libmemcached_functions_mysql.so | function |
| memc_replace_by_key          |   2 | libmemcached_functions_mysql.so | function |
| memc_servers_behavior_set    |   2 | libmemcached_functions_mysql.so | function |
| memc_servers_behavior_get    |   0 | libmemcached_functions_mysql.so | function |
| memc_behavior_set            |   2 | libmemcached_functions_mysql.so | function |
| memc_behavior_get            |   0 | libmemcached_functions_mysql.so | function |
| memc_list_behaviors          |   0 | libmemcached_functions_mysql.so | function |
| memc_list_hash_types         |   0 | libmemcached_functions_mysql.so | function |
| memc_list_distribution_types |   0 | libmemcached_functions_mysql.so | function |
| memc_udf_version             |   0 | libmemcached_functions_mysql.so | function |
| memc_libmemcached_version    |   0 | libmemcached_functions_mysql.so | function |
| memc_stats                   |   0 | libmemcached_functions_mysql.so | function |
| memc_stat_get_keys           |   0 | libmemcached_functions_mysql.so | function |
| memc_stat_get_value          |   0 | libmemcached_functions_mysql.so | function |
+------------------------------+-----+---------------------------------+----------+
32 rows in set (0.00 sec)

-------------------------------------------------------------------------------------------------

memcached_functions_mysql应用实例:

下面通过一个具体的实例来演示memcached_functions_mysql的使用方法:

1:创建两张表:

新建两张表:urls和results,更新urls表的内容,使系统自动更新Memcached的内容。results用来记录更新Memcached失败的记录。

mysql> use tests;

mysql> drop table if exists urls;

mysql> create table urls(
    -> id int(10) NOT NULL,
    -> url varchar(255) NOT NULL DEFAULT '',
    -> PRIMARY KEY (id)
    -> );

mysql> drop table if exists results;

mysql> create table results(
    -> id int(10) NOT NULL,
    -> result varchar(255) NOT NULL DEFAULT 'error',
    -> time timestamp NULL DEFAULT CURRENT_TIMESTAMP,
    -> PRIMARY KEY (id)
    -> );

------------------------------------------------------------------------------------

2:建立3个trigger

当向urls表中插入数据时,对Memcached执行set操作。trigger的代码如下:

mysql> DELIMITER //
mysql> DROP TRIGGER IF EXISTS url_mem_insert;
    -> CREATE TRIGGER url_mem_insert
    -> BEFORE INSERT ON urls
    -> FOR EACH ROW BEGIN
    -> set @mm = memc_set(NEW.id, NEW.url);
    -> if @mm <> 0 then
    -> insert into results(id) values(NEW.id);
    -> end if;
    -> END //
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
当对urls表中的数据进行更新时,对Memcached执行replace操作。trigger代码如下:

mysql> DELIMITER //
mysql> DROP TRIGGER IF EXISTS url_mem_update;
    -> CREATE TRIGGER url_mem_update
    -> BEFORE UPDATE ON urls
    -> FOR EACH ROW BEGIN
    -> set @mm = memc_replace(OLD.id,NEW.url);
    -> if @mm <> 0 then
    -> insert into results(id) values(OLD.id);
    -> end if;
    -> END //
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql>DELIMITER ;

当对urls表中的数据进行删除操作时,对Memcached执行delete操作。trigger的代码如下:

mysql> DELIMITER //
mysql> DROP TRIGGER IF EXISTS url_mem_delete;
    -> CREATE TRIGGER url_mem_delete
    -> BEFORE DELETE ON urls
    -> FOR EACH ROW BEGIN
    -> set @mm = memc_delete(OLD.ID);
    -> if @mm <> 0 then
    -> insert into results(id) values(OLD.id);
    -> END if;
    -> END //
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

---------------------------------------------------------------------------------------

3:设置Memcached的相关参数:

设置UDFs操作Memcached服务器的IP地址和端口。

mysql> select memc_servers_set('192.168.0.166:11900');
+-----------------------------------------+
| memc_servers_set('192.168.0.166:11900') |
+-----------------------------------------+
|                                       0 |

mysql> select memc_server_count();
+---------------------+
| memc_server_count() |
+---------------------+
|                   1             1
+---------------------+

在Mysql命令行中列出可以修改Memcached参数行为,执行的命令和输出结果如下:

mysql> select memc_list_behaviors()\G;
*************************** 1. row ***************************
memc_list_behaviors(): 
MEMCACHED SERVER BEHAVIORS
MEMCACHED_BEHAVIOR_SUPPORT_CAS
MEMCACHED_BEHAVIOR_NO_BLOCK
MEMCACHED_BEHAVIOR_TCP_NODELAY
MEMCACHED_BEHAVIOR_HASH
MEMCACHED_BEHAVIOR_CACHE_LOOKUPS
MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE
MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE
MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
MEMCACHED_BEHAVIOR_KETAMA
MEMCACHED_BEHAVIOR_POLL_TIMEOUT
MEMCACHED_BEHAVIOR_RETRY_TIMEOUT
MEMCACHED_BEHAVIOR_DISTRIBUTION
MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
MEMCACHED_BEHAVIOR_USER_DATA
MEMCACHED_BEHAVIOR_SORT_HOSTS
MEMCACHED_BEHAVIOR_VERIFY_KEY
MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT
MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
MEMCACHED_BEHAVIOR_KETAMA_HASH
MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
MEMCACHED_BEHAVIOR_SND_TIMEOUT
MEMCACHED_BEHAVIOR_RCV_TIMEOUT
MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT
MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK
       
MEMCACHED_HASH_DEFAULT
MEMCACHED_HASH_MD5
MEMCA
1 row in set (0.00 sec)

-----------------------------------------------------------------------

设置MEMCACHED_BEHAVIOR_NO_BLOCK为打开状态,这样在Memcached出问题时(不能连接),数据可以继续插入Mysql中,但有报错提示:如果不设置此值,那么Memcached失败时,数据需要等到Memcached失败超时后才可以插入到表中。

通过下面设置,可以避免这种情况的发生:

mysql> select memc_servers_behavior_set('MEMCACHED_BEHAVIOR_NO_BLOCK','1');
+--------------------------------------------------------------+
| memc_servers_behavior_set('MEMCACHED_BEHAVIOR_NO_BLOCK','1') |
+--------------------------------------------------------------+
|                                                            0 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select memc_servers_behavior_set('MEMCACHED_BEHAVIOR_TCP_NODELAY','1');
+-----------------------------------------------------------------+
| memc_servers_behavior_set('MEMCACHED_BEHAVIOR_TCP_NODELAY','1') |
+-----------------------------------------------------------------+
|                                                               0 |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)

---------------------------------------------------------------------------------------------

4:对memcached_functions_mysql的简单功能进行测试

1):向表urls中插入数据,然后查看Memcached是否对数据执行set操作。

mysql> insert into urls (id,url) values (1,'http://www.51newcar.com');

mysql> select memc_get('1');
+-------------------------+
| memc_get('1')           |
+-------------------------+
| http://www.51newcar.com |
+-------------------------+
1 row in set (0.00 sec)


[root@memcached ~]# telnet 192.168.0.166 11900
Trying 192.168.0.166...
Connected to memcached.51auto.com (192.168.0.166).
Escape character is '^]'.
get 1
VALUE 1 0 23
http://www.51newcar.com
END

----------------------------------------------------------------------------

2)更新表urls里面的数据,然后查询Memcached中是否也进行了更新。

mysql> update test.urls set url='http://blog.kuchuli.com' where id =1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select memc_replace('1','http://blog.kuchuli.com');
+---------------------------------------------+
| memc_replace('1','http://blog.kuchuli.com') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql> select memc_get('1');
+-------------------------+
| memc_get('1')           |
+-------------------------+
| http://blog.kuchuli.com |
+-------------------------+
1 row in set (0.00 sec)

[root@memcached ~]# telnet 192.168.0.166 11900
Trying 192.168.0.166...
Connected to memcached.51auto.com (192.168.0.166).
Escape character is '^]'.
get 1
VALUE 1 0 23
http://blog.kuchuli.com
END

------------------------------------------------------------------------------

3)删除urls中的数据,然后查看Memcached是否也将该数据删除了。

mysql> delete from test.urls where id=2;
Query OK, 1 row affected (0.00 sec)

mysql> select memc_get('2');
+---------------+
| memc_get('2') |
+---------------+
| NULL          |
+---------------+
1 row in set (0.00 sec)

[root@memcached ~]# telnet 192.168.0.166 11900
Trying 192.168.0.166...
Connected to memcached.51auto.com (192.168.0.166).
Escape character is '^]'.
get 2
END

-----------------------------------------------------------------------------------------

OK Done!!!总之源码包有很多有bag。

 










本文转自 kuchuli 51CTO博客,原文链接:http://blog.51cto.com/lgdvsehome/820974,如需转载请自行联系原作者
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
关系型数据库 MySQL 数据库
MySQL时间字段设置自动更新
MySQL时间字段设置自动更新
28 0
|
Prometheus 监控 Cloud Native
手把手教你Prometheus + Granafa实现mysql 性能监测部署
数据库性能监控可以说是十分重要,能否自行搭建环境实现像阿里云或是腾讯云那样直观的展示不同维度数据的功能?答案是肯定的。下面详细说明一下安装部署过程以及过程中出现的问题,希望对你有所帮助!
手把手教你Prometheus + Granafa实现mysql 性能监测部署
|
4月前
|
存储 缓存 关系型数据库
【面试问题】Memcached和MySQL的query cache相比,有什么优缺点?
【1月更文挑战第27天】【面试问题】Memcached和MySQL的query cache相比,有什么优缺点?
|
SQL 关系型数据库 MySQL
MySql字符串拆分实现split功能(字段分割转列、转行)
MySql字符串拆分实现split功能(字段分割转列、转行)
MySql字符串拆分实现split功能(字段分割转列、转行)
|
SQL 缓存 关系型数据库
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
|
SQL 关系型数据库 MySQL
C语言连接并实现对MySQL的增删改查
C语言访问数据库并不如Java、Python那般容易。本文介绍C语言连接并实现对MySQL的增删改查的方法。
442 0
|
canal 关系型数据库 MySQL
基于 Docker 结合 Canal 实现 MySQL 实时增量数据传输
基于 Docker 结合 Canal 实现 MySQL 实时增量数据传输
基于 Docker 结合 Canal 实现 MySQL 实时增量数据传输
|
SQL 前端开发 关系型数据库
mysql实现一次将多条不同sql查询结果并封装到一个结果集
最近遇到一个统计查询需求,要求一次性查询多个统计信息,其中两个查询信息不在一个表中,也没有业务关联,表中也没有做连接处理。不考虑产品设计是否合理,完全是实际需求如此,需要一次性查询出来返回给前端进行展示,对于这种“非常规”的统计查询平常肯定会遇见,感觉有点代表性,所以简单记录一下。希望对有相同需求的同学可以作为参考。
mysql实现一次将多条不同sql查询结果并封装到一个结果集
|
SQL 关系型数据库 MySQL
mysql实现统计同一字段不同状态的总数量之case when
直接进入主题,简单说下case when的语法.
|
SQL 关系型数据库 MySQL
脚本实现:从 HIVE 中导入数据到 MYSQL
脚本实现:从 HIVE 中导入数据到 MYSQL

推荐镜像

更多