【Java】利用Gearman進行Mysql到Redis的複製
開始的架構圖已經有寫得非常漂亮的。我這裡就不重新再編輯了。java 版本實現job server和worker從第6點開始,紅色部分是我遇到的一些坑。。。
1, 環境
CentOS 64位, MySQL, Redis, Java
mysql安裝通過lnmp進行安裝。所以預設安裝路徑為/usr/local/mysql
2, Redis簡介
Redis是一個開源的K-V記憶體資料庫,它的key可以是string/set/hash/list/...,因為是基於記憶體的,所在訪問速度相當快。
Gearman是一個開源的Map/Reduce分散式計算框架,具有豐富的client sdk,而且它支援MySQL UDF。
Gearman工作圖
Gearman呼叫流程
Gearman叢集
從圖中可以看出貌似Gearman的叢集功能比較弱,Job Server之間沒啥關係好像。
4, MySQL - Redis配合使用方案
首先我們以MySQL資料為主,將insert/update/delete交給MySQL,而select交給redis;
當有資料發生變化時,通過MySQL Trigger實時非同步呼叫Gearman的UDF提交一個job給Job Server,當job執行的時候會去更新redis;從而保證redis與MySQL中的資料是同步的。
5, 軟體安裝
安裝gearman
//安裝依賴
$ yum install -y boost-devel gperf libevent-devel libuuid-devel
//下載gearman 2015-12-10來看都是最新版本
$ wget https://launchpad.net/gearmand/1.2/1.1.12/+download/gearmand-1.1.12.tar.gz
$ tar zxvf gearmand-1.1.12.tar.gz
//編譯安裝,指定mysqlclient的連結路徑
$ ./configure
$ make
$ make install
//啟動gearmand服務端 (啟動之時,在/var/log/下建立gearmand.log日誌檔案。-l 指定日誌檔案 -d後臺執行 -L 0.0.0.0 繫結到IPV4)
$ /usr/local/sbin/gearmand -L 0.0.0.0 -l /var/log/gearmand.log -d
//檢視是否啟動成功
[[email protected] mysql]# ps -ef | grep gearman
root 31142 1 0 17:06 ? 00:00:00 /usr/local/sbin/gearmand -L 0.0.0.0 -l /znwx/logs/gearmand/gearmand.log -d
root 31174 30507 0 17:40 pts/0 00:00:00 grep gearman
//檢視是否安裝成功,檢視gearman版本
$ /usr/local/sbin/gearmand -V
5, MySQL UDF + Trigger同步資料到Gearman
安裝lib_mysqludf_json
lib_mysqludf_json可以把MySQL表的資料以json資料格式輸出
//下載lib_mysqludf_json(地址:https://github.com/mysqludf)
$ cd lib_mysqludf_json
先刪除 lib_mysqludf_json.so
//編譯 mysql_config 這是mysql的配置檔案,可以 find /usr -name mysql_config 搜尋下在什麼位置
$ gcc $(/usr/local/mysql/bin/mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
//拷貝lib_mysqludf_json.so到MySQL的plugin目錄
//可以登陸MySQL,輸入命令"show variables like '%plugin%'"檢視plugin位置
$ cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
//演示lib_mysqludf_json功能
$ mysql -uname -hhost -ppwd
//首先註冊UDF函式
mysql> CREATE FUNCTION json_object RETURNS STRING
SONAME "lib_mysqludf_json.so";
//json_array|json_members|json_values函式註冊方式與json_object一樣.
mysql> use test;
mysql> select * from user_list;
+------+----------+
| NAME | PASSWORD |
+------+----------+
| troy | pwd |
+------+----------+
mysql> select json_object(name,password) as user from user_list;
+----------------------------------+
| user |
+----------------------------------+
| {"name":"troy","password":"pwd"} |
+----------------------------------+
安裝gearman-mysql-udf
//下載 2015年12月10日已知最新版本
$ wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz
$ tar zxvf gearman-mysql-udf-0.6.tar.gz
$ cd gearman-mysql-udf-0.6
//安裝libgearman-devel
$ yum install libgearman-devel
//編譯安裝
//可以登陸MySQL,輸入命令"show variables like '%plugin%'"檢視plugin位置, mysql_config的配置檔案,以及外掛庫所在路徑,編譯之後會在此路徑生成.so檔案
./configure --with-mysql=/usr/local/mysql/bin/mysql_config --libdir=/usr/local/mysql/lib/plugin/
$ make && make install //登入MySQL註冊UDF函式 mysql> CREATEFUNCTION gman_do_background RETURNS STRING SONAME "libgearman_mysql_udf.so"; mysql> CREATEFUNCTION gman_servers_set RETURNS STRING SONAME "libgearman_mysql_udf.so";//函式gman_do|gman_do_high|gman_do_low|gman_do_high_background|gman_do_low_background|gman_sum註冊方式類似,請參考gearman-mysql-udf-0.6/README//指定gearman job server地址 mysql> SELECT gman_servers_set('127.0.0.1:4730');如果出現異常資訊:
ERROR 1126 (HY000): Can't open shared library 'libgearman_mysql_udf.so' (errno: 11 libgearman.so.8: cannot open shared object file: No such file or directory)
表示系統找不到 libgearman.so 檔案,一般so都在/usr/local/lib目錄下,修改配置檔案/etc/ld.so.conf,將/usr/local/lib目錄加入進去即可:
$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/lib
$ /sbin/ldconfig -v | grep gearman*
MySQL Trigger呼叫Gearman UDF實現同步
DELIMITER $$
CREATE TRIGGER user_list_data_to_redis AFTER UPDATE ON user_list
FOR EACH ROW BEGIN
SET @ret=gman_do_background('MySQLToRedis', json_object(NEW.name as 'name', NEW.password as 'password'));
END$$
DELIMITER ;
6、這裡才是重點:java實現job server 和worker或者單worker,網上都是一些php的。可惡啊。。。。。
我上程式碼了:
/**
* mysql 同步到 redis 的工具類。連線遠端gearman job server
* 實現原理
* mysql_udf >>>>> gearman job server>>>> gearm worker(本類) >>>>> redis
* @author 堼宸落宇 2015年12月10日
*
*/
@Component
public class MysqlToRedisWorker implements GearmanFunction{
private static final Logger log = LoggerFactory.getLogger(MysqlToRedisWorker.class);
public static final String ECHO_FUNCTION_NAME = "MySQLToRedis";
@Autowired
private Config config;
/**
* 連線其他jobserver用的。
*/
public void startWorker() {
Gearman gearman = Gearman.createGearman(); //建立gearman物件,無論是client,worker都是由這個物件產生的
log.info("MysqlToRedisWorkder connection:"+config.getEchoHost()+":"+config.getEchoPort()+",function:"+MysqlToRedisWorker.ECHO_FUNCTION_NAME);
GearmanServer server = gearman.createGearmanServer(config.getEchoHost(), config.getEchoPort()); //建立gearman server,主要是server地址和埠
GearmanWorker worker = gearman.createGearmanWorker(); //正題來了,建立work節點。
worker.setReconnectPeriod(2, TimeUnit.SECONDS); //設定超時重連時間
worker.setMaximumConcurrency(5); //最大併發數
worker.addFunction(<span style="color:#cc0000;">ECHO_FUNCTION_NAME</span>, this); //新增function方法
worker.addServer(server); //將work新增到server中
log.info("MysqlToRedisWorkder is started!!!!");
}
@Override
public byte[] work(String func, byte[] data, GearmanFunctionCallback callback)
throws Exception {
log.info("收到mysql的資料:::"+new String(data));
System.out.println("@@@@@ " + new String(data)); //byte[] data是從client傳遞來的引數,我們將引數增加@@@@字串後,原封不動返回
return data;
}
說明以及問題:此類採用了gearman官網的java-gearman-service(地址:https://code.google.com/p/java-gearman-service/),目前release版本是0.6.6。java-gearman-servic.jar包中,即包括gearman server,還包括client和work客戶端API,此包在谷歌上。我這裡上傳了一份:http://download.csdn.net/detail/u012386696/9343319.
問題:config類為spring注入的配置檔案類,在worker.addFunction中,如果通過config類的屬性,並且屬性是從配置檔案來的就會有問題。不知道為啥,寫死就是OK的。此類連線遠端的gearman job server.
jar包需要新增到本地jar倉庫:
mvn install:install-file -Dfile=C:\software\java-gearman-service-0.6.6.jar -DgroupId=org.gearman.jgs -DartifactId=java-gearman-service -Dversion=0.6.6 -Dpackaging=jar
7、建立一個job server並註冊worker,本地服務。
/**
* 建立一個job server 伺服器,並且註冊一個worker。
* @author <span style="font-family: tahoma, helvetica, arial;">堼宸落宇</span><span style="font-family: tahoma, helvetica, arial;"> 2015年12月10日</span>
*
*/
@Component
public class MysqlToRedisJobServer {
private static final Logger log = LoggerFactory.getLogger(MysqlToRedisJobServer.class);
@Autowired
MysqlToRedisWorker mysqlToRedisWorker;
@Autowired
Config config;
public void startJobServer() throws Exception{
/*
* Create a Gearman instance
*/
Gearman gearman = Gearman.createGearman();
try {
/*
* Start a new job server. The resulting server will be running in
* the local address space.
*
* Parameter 1: The port number to listen on
*
* throws IOException
*/
GearmanServer server = gearman.startGearmanServer(config.getEchoPort());
if (server!=null) {
log.info("Start gearm jobServer with java !funcname:"+MysqlToRedisWorker.ECHO_FUNCTION_NAME+" port:"+config.getEchoPort());
}
/*
* Create a gearman worker. The worker poll jobs from the server and
* executes the corresponding GearmanFunction
*/
GearmanWorker worker = gearman.createGearmanWorker();
/*
* Tell the worker how to perform the echo function
*/
worker.addFunction(MysqlToRedisWorker.ECHO_FUNCTION_NAME, mysqlToRedisWorker);
/*
* Tell the worker that it may communicate with the given job server
*/
worker.addServer(server);
} catch (IOException ioe) {
/*
* If an exception occurs, make sure the gearman service is shutdown
*/
gearman.shutdown();
// forward exception
throw ioe;
}
}
說明以及問題:這裡建立一個job server,並設定監聽埠。。
到這裡就完成了java版本的mysql到redis的複製。可沒看到複製到redis中啊。worker類的work方法就是從mysql_udf中傳過來的,這裡就隨便怎麼玩了,不是麼。。。 備註 謹記 2天的成果
相關推薦
【Java】利用Gearman進行Mysql到Redis的複製
開始的架構圖已經有寫得非常漂亮的。我這裡就不重新再編輯了。java 版本實現job server和worker從第6點開始,紅色部分是我遇到的一些坑。。。 1, 環境 CentOS 64位, MySQL, Redis, Java mysql安裝通過lnmp進行安裝。
【Matplotlib】利用Python進行繪圖
官方文檔 ech subplot 表達式 str -m 多條 isp 字符串 【Matplotlib】 教程:https://morvanzhou.github.io/tutorials/data-manipulation/plt/ 官方文檔:https://m
【JAVA】使用Mockito進行單元測試
1. @Mock與@InjectMocks的作用 @Mock:建立一個Mock @InjectMocks:建立一個例項(被測試類的例項,一般只用一次該註解) 在單元測試某個類的時候,需要標註@InjectMocks,該類的變數需要添加註解@Mock,當需要用到被測試類中
【java】利用第三方的IP地址屬地查詢
任務是根據IP地質查詢所述的省份,可以運用第三方的工具。 網上搜了一下,採用了網上的現成程式碼並進行了修改:返回的引數封裝成了DTO,包含所屬國家、地區、省份、城市、網際網路服務提供商。 放到同一個pakage裡,執行Test.java或參照Test.java呼叫即可。
【JAVA】利用反射呼叫不同方法,減少重複程式碼
今天在寫大作業的時候,遇到如下問題:整個方法裡只有資料獲取時的get方法不同,如何通過傳遞進來的不同的例項引數來使用不同的方法,而避免大段的程式碼copy,做到程式碼複用。於是今天粗略地瞭解了反射機制
【Java】利用自帶的file.mkdirs()建立資料夾與file.mkdirs()的注意事項
利用Java的自帶命令file.mkdirs();是可以直接在系統建立資料夾的。比如在d:\1資料夾下建立一個2的資料夾,則這樣寫:import java.io.*; publicclass FileMkdirTest { publicstaticvoid mai
【Java】利用String的compareTo比較兩個時期字串
在《【Java】比對兩個以字串形式表示的時期是否相差超過1天》(點選開啟連結)曾經介紹過,如果利用字串的擷取來比較兩個在資料庫中取出來,被特定格式化的日期。然而,這具有一定的侷限性,最大的缺點出在擷取字串太複雜太麻煩。 其實可以利用String的compareTo比較兩個表
【Java】對文件或文件夾進行重命名
更改 執行 board oid 文件名 file data- pla bsp 在Java中,對文件或文件夾進行重命名是很簡單的,因為Java的File類已經封裝好renameTo的方法。 修改文件或者文件夾的名字都使用這個方法。例如如下的程序: [java
【java】spring項目中 對entity進行本類間的克隆
tor mini cti false display des private rac 重寫 方法1: 【使用spring自帶BeanUtils實現克隆】 【要求:需要被克隆的類實現Cloneable接口並且重寫clone()方法】 》例子: 》》實體: package
【java】【mybatis】在使用mybatis進行批量插入,批量更新等批量操作時,切割In集合List進行分批批量操作的java中的切割代碼
lse span ati 批量更新 次數 sublist 調用 size == 紅字部分代表mybatis的批量操作調用方法: int num = 0; int maxLength = 200; in
【RS】利用局部隱含空間模型進行Top-N推薦
針對 -s pac for chris com ext space 行為 【論文標題】Local Latent Space Models for Top- N Recommendation (KDD-2018 ) 【論文作者】—Evangelia Christak
【JAVA】在SpringBoot 專案中 利用maven 的generate外掛
使用maven 外掛 generate生成MyBatis相關檔案 在專案中增加 maven 依賴 - mybatis-spring-boot-starter - mysql-connector-java - mybatis-generator-maven-plugin 外掛 自
【C++】利用建構函式對類物件進行初始化
一、物件的初始化 每一個物件都應當在它建立之時就有就有確定的內容,否則就會失去物件的意義。 class Time { int hour = 0; int min = 0; int sec = 0; }; 這種是錯誤的,類並不是一個實體,並不佔儲存空間,顯然無處容納
【react】利用prop-types第三方庫對元件的props中的變數進行型別檢測
1.安裝:npm install prop-types --save 2.使用 import React, { Component } from 'react'; import PropTypes
【java】對被final修飾的變數進行賦值的幾種方法
對被final修飾的變數進行賦值的幾種方法 這是精華: 因為當類被載入進記憶體的時候,這個屬性並沒有給其分配記憶體空間,而只是定義了一個變數,只有當類被例項化的時候這個屬性才被分配記憶體空
【ODPS】利用阿里雲ODPS作業進行圓周率Pi的計算
原理: 1.畫一個正方形,邊長為1CM,在此正方形內繪製一個內接圓。 2.假如我們在此正方形內隨機點一個點,這個點落在圓內的概率是P 3.假如我們隨機足夠多的點,那麼我們的P就無限接近於Pi/4(=圓的面積/正方形的面積) 表設計: 1.隨機落點表(記錄隨機點的位置) 2
Java對MySQL資料庫進行操作【java】
資料庫幾乎是每一個應用型的程式都會用到,學會如何高效操作資料庫也是開發一個重點。今天我總結了具體的操作步驟以及注意點。Java訪問資料庫主要用的方法是JDBC,它是java語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面,提供了諸如查詢和更新資料庫中資料的方法,接下來
【Java】對檔案或資料夾進行重新命名
在Java中,對檔案或資料夾進行重新命名是很簡單的,因為Java的File類已經封裝好rename
【iOS】利用CocoaPods建立私有庫進行元件化開發
之前使用CocoaPods管理過第三方庫,前面也有翻譯文章介紹過CocoaPods的配置方法,隨著專案越來越大,很多公司會使用CocoaPods進行元件化開發,下面利用一個demo介紹一下。 什麼是庫 先說下什麼是庫,庫分為靜態庫和動態庫兩種: - 1
【java】陣列的複製System.arraycopy
預設提供的一種陣列複製的方法 System.arraycopy(src, srcPos, dest, destPos, length); src:源陣列 srcPos:源陣列開始位置 dest:目標陣列 destPos:目標陣列開始位置 length:複製的長度 這