1. 程式人生 > >將MySQL資料對映到Memcached中 收藏

將MySQL資料對映到Memcached中 收藏


測試環境在Linux下進行,版本系統為CentOS5.
以下為相關軟體,包括其版本和下載地址:


mysql-5.1.30 下載
memcached-1.2.6 下載
libevent-1.4.7-stable 下載
memcached_functions_mysql-1.1 下載
libmemcached-0.26 下載

編譯安裝MySQL,安裝因個人細好而定,省略許多與測試無關的編譯細節及引數。

view plaincopy to clipboardprint?
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#tar xzf mysql-5.1.30.tar_001.gz</SPAN>  
<SPAN>[</SPAN>

[email protected] ~<SPAN>]</SPAN><SPAN>#cd mysql-5.1.30</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#./configure --prefix=/usr/local/mysql51</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#make</SPAN>  
<SPAN>[</SPAN>
[email protected]
~<SPAN>]</SPAN><SPAN>#make install</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#./scripts/mysql_install_db --user=mysql --skip-name-resolve</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#/usr/local/mysql51/bin/mysqld_safe</SPAN> 

[[email protected] ~]#tar xzf mysql-5.1.30.tar_001.gz
[[email protected] ~]#cd mysql-5.1.30
[[email protected] ~]#./configure --prefix=/usr/local/mysql51
[[email protected] ~]#make
[[email protected] ~]#make install
[[email protected] ~]#./scripts/mysql_install_db --user=mysql --skip-name-resolve
[[email protected] ~]#/usr/local/mysql51/bin/mysqld_safe省略列出安裝memcached和libevent的相關命令,具體可按照實際情況安裝,測試時我將libevent預設安裝,memcached安裝於/usr/local/memcached目錄下。
啟動memcached.

view plaincopy to clipboardprint?
<SPAN>/</SPAN>usr<SPAN>/</SPAN>local<SPAN>/</SPAN>memcached<SPAN>/</SPAN>bin<SPAN>/</SPAN>memcached <SPAN>-</SPAN>d <SPAN>-</SPAN>m <SPAN>50</SPAN> <SPAN>-</SPAN>u root <SPAN>-</SPAN>p <SPAN>11211</SPAN> 

/usr/local/memcached/bin/memcached -d -m 50 -u root -p 11211編譯安裝libmemcache.

view plaincopy to clipboardprint?
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#tar xzf libmemcached-0.26.tar.gz</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#cd libmemcached-0.26</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN>#./configure --with-memcached=/usr/local/memcached/bin/memcached</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN># make && make install</SPAN> 

[[email protected] ~]#tar xzf libmemcached-0.26.tar.gz
[[email protected] ~]#cd libmemcached-0.26
[[email protected] ~]#./configure --with-memcached=/usr/local/memcached/bin/memcached
[[email protected] ~]# make && make install編譯安裝Memcache UDFs for MySQL.

view plaincopy to clipboardprint?
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN># tar xzf memcached_functions_mysql-1.1.tar.gz</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN># cd memcached_functions_mysql-1.1</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN># ./configure --with-mysql-config=/usr/local/mysql51/bin/mysql_config</SPAN>  
<SPAN>[</SPAN>[email protected] ~<SPAN>]</SPAN><SPAN># make && make install</SPAN> 

[[email protected] ~]# tar xzf memcached_functions_mysql-1.1.tar.gz
[[email protected] ~]# cd memcached_functions_mysql-1.1
[[email protected] ~]# ./configure --with-mysql-config=/usr/local/mysql51/bin/mysql_config
[[email protected] ~]# make && make install編譯完成後將編譯好的庫檔案複製到mysql的外掛目錄下,以便於載入使用。

view plaincopy to clipboardprint?
cp <SPAN>/</SPAN>usr<SPAN>/</SPAN>local<SPAN>/</SPAN>lib<SPAN>/</SPAN>libmemcached_functions_mysql<SPAN>*</SPAN> <SPAN>/</SPAN>usr<SPAN>/</SPAN>local<SPAN>/</SPAN>mysql51<SPAN>/</SPAN>lib<SPAN>/</SPAN>mysql<SPAN>/</SPAN>plugin<SPAN>/</SPAN> 

cp /usr/local/lib/libmemcached_functions_mysql* /usr/local/mysql51/lib/mysql/plugin/進入memcached_functions_mysql的原始碼目錄,在目錄下有相關新增UDF的SQL檔案用於初始化。


在mysql的shell中執行memcached_functions_mysql原始碼目錄下的sql/install_functions.sql
或者執行memcached_functions_mysql原始碼目錄下utils/install.pl這個perl指令碼,把memcache function作為UDF加入mysql。

[[email protected] ~]# mysql <sql/install_functions.sql

檢查安裝是否成功

mysql> select name,dl from mysql.func;

二. 測試用例設計情況:

(1).新建兩張表:urls和results,用來更新urls表裡面的內容,讓系統自動更新memcached的內容。results用來記錄更新memcached失敗的記錄。
sql語句如下:
use tests;
drop table if exists urls;
CREATE TABLE `urls` (
  `id` int(10) NOT NULL,
  `url` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

drop table if exists results;
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). 建立三個trigger.

當向urls表裡面插入資料時,對memcached執行set操作,trigger如下:
DELIMITER //
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 //
DELIMITER ;


當對urls表裡面的資料進行更新時,對memcached執行replace操作,trigger如下:

DELIMITER //
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 //
DELIMITER ;


當對urls表裡面的資料進行刪除操作時,對memcached執行delete操作,trigger如下:

DELIMITER //
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 //
DELIMITER ;


(3). 設定memcached相關引數

設定同時UDF操作的memcaced的機器IP和埠:

mysql> SELECT memc_servers_set('192.168.3.184:11900');
+---------------------------------------+
| memc_servers_set('192.168.3.184:11900') |
+---------------------------------------+
|                                     0 |
+---------------------------------------+
1 row in set (0.00 sec)


mysql> select memc_server_count();
+---------------------+
| memc_server_count() |
+---------------------+
|                   1 |
+---------------------+
1 row in set (0.00 sec)


在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

1 row in set (0.00 sec)


設定MEMCACHED_BEHAVIOR_NO_BLOCK為開啟狀態,這樣在memcached出現問題時(不能連線時)
資料繼續插入到mysql中,報錯提示,如果不設定此值,如果memcached失敗,mysql需要等到timeout
才可以插入到表中。
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)


三. 簡單的功能測試:


1. 向表urls裡面插入資料,然後查memcached是否也set進資料:

mysql> insert into urls (id,url) values (1, 'http://www.sina.com.cn');
Query OK, 1 row affected, 1 warning (0.00 sec)

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


1> telnet 192.168.3.184 11900
Trying 192.168.3.184...
Connected to 192.168.3.184 (192.168.3.184).
Escape character is '^]'.
get 1
VALUE 1 0 22
http://www.sina.com.cn
END


2.更新表urls裡面的資料,然後查詢memcached裡面是否也更新:
mysql> update test.urls set url='http://blog.sina.com.cn' where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0


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

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


1> telnet 192.168.3.184 11900
Trying 192.168.3.184...
Connected to 192.168.3.184 (192.168.3.184).
Escape character is '^]'.
get 1
VALUE 1 0 23
http://blog.sina.com.cn
END


3.刪除表urls裡面的資料,然後查memcached是否也刪除:
mysql> delete from test.urls where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

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


1> telnet 192.168.3.184 11900
Trying 192.168.3.184...
Connected to 192.168.3.184 (192.168.3.184).
Escape character is '^]'.
get 1
END

四. 利用php指令碼insert, update,delete表urls裡面的資料,進行測試。

每條記錄的平均長度是:17K

單獨向表urls裡面插入10萬條記錄需要的時間為:75秒
單獨對錶urls裡面更新10萬條記錄需要的時間為:70秒
單獨對錶urls裡面刪除10萬條記錄需要的時間為:105秒

同時進行30萬資料的insert,update, delete操作需要時間為:241秒

上面操作都沒有memcached失敗情況:
mysql> select * from results;
Empty set (0.00 sec)


測試指令碼如下:

插入指令碼:
0> more a.php
<?php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");
//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {
$sql="insert into urls (id,url) values ($i, 'http://$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i.com');";
mysql_query($sql) or die(mysql_error());
}

echo "/n";
echo date("Y-m-d H:i:s");

?>

更新指令碼:
0> more b.php
<?php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");
//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {
$sql="update test.urls set url='http://xxxx.$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i.com' where id=$i;";
mysql_query($sql) or die(mysql_error());
}

echo "/n";
echo date("Y-m-d H:i:s");

?>

刪除指令碼:
0> more c.php
<?php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");
//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {
$sql="delete from test.urls where id=$i;";
mysql_query($sql) or die(mysql_error());
}

echo "/n";
echo date("Y-m-d H:i:s");

?>


五. 結論:
測試依賴的環境比較多,可能資料會不準確。整體來看速度還不錯。
適合專案應用相對比較小的場合。

優點:
觸發器中使用 UDFs 直接更新 Memcached 的內容,減輕了應用程式設計和編寫的複雜性。

缺點:
1. 如果出現mysql服務重啟,需要重新設定連線memcached關係(SELECT memc_servers_set('192.168.3.184:11900'))
2. 有可能存在bug問題,導致mysql的crash(測試時沒遇到:)).


真正的線上環境比這個複雜很多。我想到的需要考慮的問題:
1. 網路因素,mysql和memcached是否放在同一IDC,他們之間的網路效能是否很好。網路效能越好,速度肯定越快,如果使用本機的memcached能適當的減少網路開銷。
2. 插入的資料量,向mysql插入每條記錄的size,以及向memcached裡面更新的資料size大小。更新mysql,memcached的資料size越大,更新的速度越慢。
所以前期規劃好,在memcached裡面存那兩列(key-value)是關鍵。
3. 延時問題需要考慮,mysql所在機器如果資源使用比較狠,會導致更新memcached慢(出現類似m/s的延時問題)。
4. 考慮容災問題,如果兩者中有down出現時,需要考慮怎麼恢復,當前的測試是這樣考慮的:建一張錯誤表,如果在出現更新mc出現問題時,自動把更新錯誤的記錄插到
一張表裡面,通過查這張表,可以知道哪些資料在什麼時間更新錯誤,如果應用於生產環境,需要考慮監控和出現問題時恢復工作(寫好指令碼完善這個工作)。
5. mysql自身因素,例如執行的mysql語句效率,以及連線mysql的client程式(php)的連線開銷等等。

相關推薦

MySQL資料對映Memcached 收藏

測試環境在Linux下進行,版本系統為CentOS5.以下為相關軟體,包括其版本和下載地址: mysql-5.1.30 下載memcached-1.2.6 下載libevent-1.4.7-stable 下載memcached_functions_mysql-1.1 下載li

sqoopMysql資料匯入Hive

注:筆者用的是sqoop1.4.6版本 一、將Mysql資料匯入Hive中 命令: sqoop import -Dorg.apache.sqoop.splitter.allow_text_splitter=true --con

利用python mysql 資料進行抽取並清理成標準格式後 存入MSSql 資料

from pymongo import MongoClientfrom pymysql import connectimport pymssqlfrom datetime import datetime, timedeltaimport time Nagios 資料庫的IP 地址 NagiosDB_IP

通過sqoopmysql資料匯入到hive進行計算示例

hive計算示例 先將資料通過sqoop從mysql匯入hive,在hive執行mysql的查詢語句,得到與mysql一樣的執行結果 步驟: mysql資料準備 account賬號表 detail收支資料表 CREATE TABLE

mysql資料導為csv再匯入到mongodb

shell指令碼 mysql2mongodb.sh #[[email protected] tmp]# vim mysql2mongo.sh mysql -h127.0.0.1 -uroot -p123456 -P3306 -N -e " SELECT

利用sqoophive資料匯入Oracle(踩的坑)

教程很多,這裡只說踩過的坑 1.下載sqoop時,還得下一個bin的包,拿到sqoop-1.4.6.jar 的包,放到hadoop的lib目錄下 2.匯入oracle,執行程式碼時,使用者名稱和表名必須大寫!且資料庫建表時表名必須大寫!  示例程式碼: sqoop expo

資料庫資料入excel併發送郵件

我們有個政府專案,程式碼和資料庫都在政府那邊,我就開了一個後門,每天定時將資料庫資料發到我們這邊來,然後定時把這個檔案再刪除掉,在中秋這一天專案經理給我打電話問我說資料庫資料的情況,並且讓我們這邊一個開發人員幫忙統計增量是多少,我就萌生了一個想發,過節都不讓人過好,還想著公司的事情,於是

使用sqoopmysql 資料匯入hdfs時各種報錯

資訊 18/06/29 10:45:08 ERROR sqoop.Sqoop: Got exception running Sqoop: java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLExcepti

mysql數據庫的單個庫的數據同步到redis數據庫

char delet rpo https lena iter range 操作 cor 實際代碼只有一點,其他的為備忘 # -*- coding:utf-8 -*- import MySQLdb import redis class Config: def __i

mysql資料匯入mongodb

# 把mysql資料庫中的資料匯入mongodb中 import pymysql import pymongo # 建立mysql的資料庫連線 con = pymysql.connect(host='localhost', port=3306, user='root', password='12345

mongodbmysql資料匯入

1、首先將資料從mysql資料庫匯出為xls檔案 SELECT * FROM user INTO OUTFILE "F:\1.xls" 2、notepad++開啟,用utf8編碼儲存資料   3、使用wps或者cvs開啟檔案,並以.cvs格式儲存資料   4、在w

用logstashmysql資料同步到 elasticsearch

最近需要同步mysql資料到ES,參考了 這篇文章,遇到幾個問題 第一個是jdbc驅動路徑 jdbc_driver_library => "../mysql-connector-java-5.1.46/mysql-connector-java-5.1.46-b

利用sqoophive資料匯入Oracle

首先: 如oracle則執行sqoop list-databases --connect jdbc:oracle:thin:@//192.168.27.235:1521/ORCL --username DATACENTER -P 來測試是否能正確連線資料庫  如mysql則執行sq

python3 使用openpyxlmysql資料寫入xlsx

程式設計的生活愈發不容易了,工作越來越難找,說多了都是淚還是給大家貢獻些程式碼比較實際。 python3 連結資料庫需要下載名為pymysql的第三方庫 python3 讀寫xlsx需要下載名為openpyxl的第三方庫 在此我只貢獻連結資料庫和寫入xlsx的程式碼 import p

資料庫資料放到redis並保持資料一致性方案

1、查詢時先查詢快取(redis),如果查詢不到,查詢資料庫,並將會員唯一標識(會員編號),放到redis佇列中(list) 2、啟動一個job從redis佇列中讀取會員唯一標識,並判斷會員編號作為key是否存在於redis中,如果存在,計數器減一,否則直接查詢會員資訊,放

資料載入記憶體檢索字串

<pre name="code" class="cpp"><pre name="code" class="cpp">#define _CRT_SECURE_NO_WARNING

《編寫可維護的JavaScript》讀書筆記之程式設計實踐-配置資料從程式碼分離

將配置資料從程式碼中分離出來 任何時候修改原始碼都會有引入 bug 的風險,且只修改一些資料的值也會帶來一些不必要的風險。精心設計的應用應當將關鍵資料從主要的原始碼中抽離出來,因為資料是不應當影響指令的正常執行。 什麼是配置資料 配置資料是應用中寫死(har

Windows10下使用redis快取(mysql資料快取到redis)

一.安裝redis環境 1.下載redis: 連結:https://pan.baidu.com/s/1SiEzRk7xmpe4wi7y9PmFdw  提取碼:bf5p  這是Windows10 64位的 2.將下載的壓縮包解壓到新建資料夾redis 3.利用cmd

Springmvc-前端資料對映成JAVA物件接收例項

確保前端資料欄位 跟 JAVA物件屬性(欄位) 一致 JQ程式碼: //前端資料 var specListArr = new Array(); specList = []; if

sqoop mysql資料匯入Hive

sqoop import --connect jdbc:mysql://192.168.8.97:3306/db1?charset-utf8  --username root --password 123456 --table pd_info --columns "pid,cid" --fields-term