├── README.md ├── bin ├── SysConfig.properties ├── start.sh └── syncClient.jar └── src ├── META-INF └── MANIFEST.MF ├── SysConfig.properties ├── lib ├── canal.client-1.0.24.jar ├── canal.common-1.0.24.jar ├── canal.protocol-1.0.24.jar ├── commons-beanutils-1.8.2.jar ├── commons-codec-1.9.jar ├── commons-collections-3.2.jar ├── commons-io-2.4.jar ├── commons-lang-2.6.jar ├── commons-lang3-3.7.jar ├── commons-logging-1.0.4.jar ├── commons-pool-1.5.6.jar ├── commons-pool2-2.5.0.jar ├── elasticsearch-rest-client-6.3.2.jar ├── fastjson-1.2.28.jar ├── httpasyncclient-4.1.2.jar ├── httpclient-4.5.2.jar ├── httpcore-4.4.5.jar ├── httpcore-nio-4.4.5.jar ├── jedis-2.9.0.jar ├── kafka-clients-1.0.0.jar ├── protobuf-java-2.6.1.jar ├── slf4j-api-1.7.12.jar ├── ssdb.jar ├── xmemcached-2.4.5.jar ├── zkclient-0.10.jar └── zookeeper-3.4.5.jar └── src └── com └── sync ├── common ├── CanalData.java ├── EsApi.java ├── GetProperties.java ├── HttpClient.java ├── HttpmqApi.java ├── MemApi.java ├── ReadProperties.java ├── RedisApi.java ├── SsdbApi.java ├── TargetData.java ├── Tool.java └── WriteLog.java └── process ├── Cache.java ├── ElasticSearch.java ├── Httpmq.java ├── Kafka.java ├── Prop.java ├── Redis.java ├── Ssdb.java └── task.java /README.md: -------------------------------------------------------------------------------- 1 | ### **syncClient** 2 | 3 | >   syncClient,数据实时同步中间件(同步mysql到kafka、redis、elasticsearch、httpmq)! 4 | 5 | 本项目使用canal,将mysql的表数据实时同步到kafka、redis、elasticsearch、httpmq;   6 | 7 | 基本原理: 8 | canal解析binlog的数据,由syncClient订阅,然后实时推送到kafka或者redis、elasticsearch、httpmq、ssdb;如果kafka、redis、es、httpmq服务异常,syncClient会回滚操作;canal、kafka、redis、es、httpmq的异常退出,都不会影响数据的传输; 9 | 10 | 11 | --- 12 | 13 | **目录:** 14 | bin:已编译二进制项目,可以直接使用; 15 | src:源代码; 16 | 17 | --- 18 | 19 | **配置说明:** 20 | 21 | #common 22 | system.debug=1 # 是否开始调试:1未开启,0为关闭(线上运行请关闭) 23 | 24 | #canal server 25 | canal.ip=127.0.0.1 # canal 服务端 ip; 26 | canal.port=11111 # canal 服务端 端口:默认11111; 27 | canal.destination=one # canal 服务端项目(destinations),多个用逗号分隔,如:redis,kafka; 28 | canal.username= # canal 用户名:默认为空; 29 | canal.password= # canal 密码:默认为空; 30 | 31 | #redis plugin 32 | redis.target_type=redis # 同步插件类型 kafka or redis、elasticsearch、httpmq; 33 | redis.target_ip= # redis服务端 ip; 34 | redis.target_port= # redis端口:默认6379; 35 | redis.target_deep= # 同步到redis的队列名称规则; 36 | redis.target_filter_api= # rest api地址,配置后会根据api返回的数据过滤同步数据; 37 | 38 | #kafka plugin 39 | kafka.target_type=kafka # 同步插件类型 kafka; 40 | kafka.target_ip= # kafka服务端 ip; 41 | kafka.target_port= # kafka端口:默认9092; 42 | kafka.target_deep= # 同步到kafka的集合名称规则; 43 | kafka.target_filter_api= # rest api地址,配置后会根据api返回的数据过滤同步数据; 44 | 45 | #elasticsearch plugin 46 | es.target_type=elasticsearch # 同步插件类型elasticsearch; 47 | es.target_ip=10.5.3.66 # es服务端 ip; 48 | es.target_port= # es端口:默认9200; 49 | es.target_deep= # 同步到es的index名称规则; 50 | es.target_filter_api= # rest api地址,配置后会根据api返回的数据过滤同步数据; 51 | 52 | #httpmq plugin 53 | httpmq.target_type=httpmq # 同步插件类型 httpmq; 54 | httpmq.target_ip=10.5.3.66 # httpmq服务端 ip; 55 | httpmq.target_port=1218 # httpmq端口:默认 1218 56 | httpmq.target_deep= # 同步到httpmq的队列名称规则; 57 | httpmq.target_filter_api= # rest api地址,配置后会根据api返回的数据过滤同步数据; 58 | 59 | #cache plugin 60 | cache.target_type=cache # 缓存同步插件 61 | cache.target_plugin=memcached # 缓存同步类型:暂支持redis、memcached缓存服务器; 62 | cache.target_ip=127.0.0.1 # 缓存服务器ip; 63 | cache.target_port=11211 # 缓存服务器端口; 64 | cache.target_filter_api= # rest api地址,配置后会根据api返回的数据过滤同步数据; 65 | cache.target_version_sign= # 缓存key前缀 66 | 67 | #target_deep参数影响topic规则,默认值1: 68 | 1、sync_{项目名}_{db}_{table}; 69 | 2、sync_{项目名}_{db}; 70 | 3、sync_{项目名}; 71 | 4、sync_{db}_{table}; 72 | 73 | --- 74 | 75 | **使用场景(基于日志增量订阅&消费支持的业务):** 76 | 77 | 数据库镜像 78 | 数据库实时备份 79 | 多级索引 (分库索引) 80 | search build 81 | 业务cache刷新 82 | 数据变化等重要业务消息 83 | 84 | **Kafka:** 85 | 86 | Topic规则:对应配置项目target_deep指定的规则,比如:target_deep=4,数据库的每个表有单独的topic,如数据库admin的user表,对应的kafka主题名为:sync_admin_user   87 | Topic数据字段: 88 | 89 | 插入数据同步格式: 90 | { 91 | "head": { 92 | "binlog_pos": 53036, 93 | "type": "INSERT", 94 | "binlog_file": "mysql-bin.000173", 95 | "db": "sdsw", 96 | "table": "sys_log" 97 | }, 98 | "after": [ 99 | { 100 | "log_id": "1", 101 | }, 102 | { 103 | "log_ip": "27.17.47.100", 104 | }, 105 | { 106 | "log_addtime": "1494204717", 107 | } 108 | ] 109 | } 110 | 111 | 修改数据同步格式: 112 | { 113 | "head": { 114 | "binlog_pos": 53036, 115 | "type": "UPDATE", 116 | "binlog_file": "mysql-bin.000173", 117 | "db": "sdsw", 118 | "table": "sys_log" 119 | }, 120 | "before": [ 121 | { 122 | "log_id": "1", 123 | }, 124 | { 125 | "log_ip": "27.17.47.100", 126 | }, 127 | { 128 | "log_addtime": "1494204717", 129 | } 130 | ], 131 | "after": [ 132 | { 133 | "log_id": "1", 134 | }, 135 | { 136 | "log_ip": "27.17.47.1", 137 | }, 138 | { 139 | "log_addtime": "1494204717", 140 | } 141 | ] 142 | } 143 | 144 | 删除数据同步格式: 145 | { 146 | "head": { 147 | "binlog_pos": 53036, 148 | "type": "DELETE", 149 | "binlog_file": "mysql-bin.000173", 150 | "db": "sdsw", 151 | "table": "sys_log" 152 | }, 153 | "before": [ 154 | { 155 | "log_id": "1", 156 | }, 157 | { 158 | "log_ip": "27.17.47.1", 159 | }, 160 | { 161 | "log_addtime": "1494204717", 162 | } 163 | ] 164 | } 165 | 166 | head.type 类型:INSERT(插入)、UPDATE(修改)、DELETE(删除); 167 | 168 | head.db 数据库; 169 | 170 | head.table 数据库表; 171 | 172 | head.binlog_pos 日志位置; 173 | 174 | head.binlog_file 日志文件;   175 | 176 | before: UPDATE(修改前)、DELETE(删除前)的数据;   177 | 178 | after: INSERT(插入后)、UPDATE(修改后)的数据; 179 | 180 | 181 | **Redis:** 182 | 183 | List规则:对应配置项目target_deep指定的规则,比如:target_deep=4,数据库的每个表有单独的list,如数据库admin的user表,对应的redis list名为:sync_admin_user   184 | 185 | **Elasticsearch** 186 | 187 | 规则:数据库的每个表有单独的Elasticsearch index,如数据库admin的user表,对应的es index名为:sync_admin_user, index type 为default; 188 | 189 | Elasticsearch同步数据的head中有id字段; 190 | 191 | Mysql 同步到 Elasticsearch注意事项: 192 | 193 | 1、表需要有一个唯一id主键; 194 | 2、表时间字段datetime会转为es的时间字段,其他字段对应es的文本类型; 195 | 3、主键、时间字段禁止修改,其他字段尽量提前规划好; 196 | 197 | **Httpmq:** 198 | 199 | List规则:对应配置项目target_deep指定的规则,比如:target_deep=4,数据库的每个表有单独的list,如数据库admin的user表,对应的redis list名为:sync_admin_user   200 | 201 | 202 | **Cache:** 203 | 204 | 缓存同步插件:原理是根据数据库变更同步更新表及字段的版本号,业务sdk根据版本号变化判断是否需要更新数据。同步开发了缓存配置管理中心、缓存版本调用sdk(未开源); 205 | 206 | 207 | Flag Counter 208 | 209 | -------------------------------------------------------------------------------- /bin/SysConfig.properties: -------------------------------------------------------------------------------- 1 | #common 2 | system.debug=1 3 | 4 | #canal server 5 | canal.ip=127.0.0.1 6 | canal.port=11111 7 | canal.destination=httpmq 8 | canal.username= 9 | canal.password= 10 | 11 | #redis plugin 12 | redis.target_type=redis 13 | redis.target_ip=127.0.0.1 14 | redis.target_port=6397 15 | redis.target_filter_api= 16 | redis.target_deep=2 17 | 18 | #elasticsearch plugin 19 | es.target_type=elasticsearch 20 | es.target_ip=127.0.0.1 21 | es.target_port=9200 22 | es.target_filter_api= 23 | es.target_deep=2 24 | 25 | #httpmq plugin 26 | httpmq.target_type=httpmq 27 | httpmq.target_ip=127.0.0.1 28 | httpmq.target_port=1218 29 | httpmq.target_filter_api= 30 | httpmq.target_deep=2 31 | 32 | #kafka plugin 33 | kafka.target_type=kafka 34 | kafka.target_ip=127.0.0.1 35 | kafka.target_port=9092 36 | kafka.target_filter_api= 37 | kafka.target_deep=2 38 | 39 | #cache plugin 40 | cache.target_type=cache 41 | cache.target_plugin=memcached 42 | cache.target_ip=127.0.0.1 43 | cache.target_port=11211 44 | cache.target_filter_api= 45 | cache.target_version_sign=database: -------------------------------------------------------------------------------- /bin/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -jar syncClient.jar & -------------------------------------------------------------------------------- /bin/syncClient.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/bin/syncClient.jar -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.sync.process.task 3 | -------------------------------------------------------------------------------- /src/SysConfig.properties: -------------------------------------------------------------------------------- 1 | #common 2 | system.debug=1 3 | 4 | #canal server 5 | canal.ip=127.0.0.1 6 | canal.port=11111 7 | canal.destination=cache 8 | canal.username= 9 | canal.password= 10 | 11 | #redis plugin 12 | redis.target_type=redis 13 | redis.target_ip=127.0.0.1 14 | redis.target_port=6397 15 | redis.target_deep=3 16 | 17 | #elasticsearch plugin 18 | es.target_type=elasticsearch 19 | es.target_ip=127.0.0.1 20 | es.target_port=9200 21 | es.target_deep=3 22 | 23 | #httpmq plugin 24 | httpmq.target_type=httpmq 25 | httpmq.target_ip=127.0.0.1 26 | httpmq.target_port=1218 27 | httpmq.target_deep=3 28 | 29 | #kafka plugin 30 | httpmq.target_type=kafka 31 | httpmq.target_ip=127.0.0.1 32 | httpmq.target_port=9092 33 | httpmq.target_deep=3 34 | 35 | #cache plugin 36 | cache.target_type=cache 37 | cache.target_plugin=memcached 38 | cache.target_ip=127.0.0.1 39 | cache.target_port=11211 40 | cache.target_field_filter= 41 | cache.target_version_sign=database: -------------------------------------------------------------------------------- /src/lib/canal.client-1.0.24.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/canal.client-1.0.24.jar -------------------------------------------------------------------------------- /src/lib/canal.common-1.0.24.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/canal.common-1.0.24.jar -------------------------------------------------------------------------------- /src/lib/canal.protocol-1.0.24.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/canal.protocol-1.0.24.jar -------------------------------------------------------------------------------- /src/lib/commons-beanutils-1.8.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-beanutils-1.8.2.jar -------------------------------------------------------------------------------- /src/lib/commons-codec-1.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-codec-1.9.jar -------------------------------------------------------------------------------- /src/lib/commons-collections-3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-collections-3.2.jar -------------------------------------------------------------------------------- /src/lib/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-io-2.4.jar -------------------------------------------------------------------------------- /src/lib/commons-lang-2.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-lang-2.6.jar -------------------------------------------------------------------------------- /src/lib/commons-lang3-3.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-lang3-3.7.jar -------------------------------------------------------------------------------- /src/lib/commons-logging-1.0.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-logging-1.0.4.jar -------------------------------------------------------------------------------- /src/lib/commons-pool-1.5.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-pool-1.5.6.jar -------------------------------------------------------------------------------- /src/lib/commons-pool2-2.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/commons-pool2-2.5.0.jar -------------------------------------------------------------------------------- /src/lib/elasticsearch-rest-client-6.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/elasticsearch-rest-client-6.3.2.jar -------------------------------------------------------------------------------- /src/lib/fastjson-1.2.28.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/fastjson-1.2.28.jar -------------------------------------------------------------------------------- /src/lib/httpasyncclient-4.1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/httpasyncclient-4.1.2.jar -------------------------------------------------------------------------------- /src/lib/httpclient-4.5.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/httpclient-4.5.2.jar -------------------------------------------------------------------------------- /src/lib/httpcore-4.4.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/httpcore-4.4.5.jar -------------------------------------------------------------------------------- /src/lib/httpcore-nio-4.4.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/httpcore-nio-4.4.5.jar -------------------------------------------------------------------------------- /src/lib/jedis-2.9.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/jedis-2.9.0.jar -------------------------------------------------------------------------------- /src/lib/kafka-clients-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/kafka-clients-1.0.0.jar -------------------------------------------------------------------------------- /src/lib/protobuf-java-2.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/protobuf-java-2.6.1.jar -------------------------------------------------------------------------------- /src/lib/slf4j-api-1.7.12.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/slf4j-api-1.7.12.jar -------------------------------------------------------------------------------- /src/lib/ssdb.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/ssdb.jar -------------------------------------------------------------------------------- /src/lib/xmemcached-2.4.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/xmemcached-2.4.5.jar -------------------------------------------------------------------------------- /src/lib/zkclient-0.10.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/zkclient-0.10.jar -------------------------------------------------------------------------------- /src/lib/zookeeper-3.4.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/lib/zookeeper-3.4.5.jar -------------------------------------------------------------------------------- /src/src/com/sync/common/CanalData.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | /** 4 | * CanalData 5 | * 6 | * @author sasou web:http://www.php-gene.com/ 7 | * @version 1.0.0 8 | */ 9 | public final class CanalData { 10 | public String ip = "127.0.0.1"; 11 | public int port = 11111; 12 | public String[] destination = null; 13 | public String username = ""; 14 | public String password = ""; 15 | 16 | /** 17 | * @return the ip 18 | */ 19 | public String getIp() { 20 | return ip; 21 | } 22 | 23 | /** 24 | * @param ip 25 | * the ip to set 26 | */ 27 | public void setIp(String ip) { 28 | this.ip = ip; 29 | } 30 | 31 | /** 32 | * @return the port 33 | */ 34 | public int getPort() { 35 | return port; 36 | } 37 | 38 | /** 39 | * @param port 40 | * the port to set 41 | */ 42 | public void setPort(int port) { 43 | this.port = port; 44 | } 45 | 46 | /** 47 | * @return the destination 48 | */ 49 | public String[] getDestination() { 50 | return destination; 51 | } 52 | 53 | /** 54 | * @param destination 55 | * the destination to set 56 | */ 57 | public void setDestination(String destination) { 58 | this.destination = destination.split(","); 59 | } 60 | 61 | /** 62 | * @return the username 63 | */ 64 | public String getUsername() { 65 | return username; 66 | } 67 | 68 | /** 69 | * @param username 70 | * the username to set 71 | */ 72 | public void setUsername(String username) { 73 | this.username = username; 74 | } 75 | 76 | /** 77 | * @return the password 78 | */ 79 | public String getPassword() { 80 | return password; 81 | } 82 | 83 | /** 84 | * @param password 85 | * the password to set 86 | */ 87 | public void setPassword(String password) { 88 | this.password = password; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/src/com/sync/common/EsApi.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.io.IOException; 4 | import java.util.Collections; 5 | import java.util.Map; 6 | 7 | import org.apache.http.HttpEntity; 8 | import org.apache.http.HttpHost; 9 | import org.apache.http.entity.ContentType; 10 | import org.apache.http.nio.entity.NStringEntity; 11 | import org.apache.http.util.EntityUtils; 12 | import org.elasticsearch.client.*; 13 | 14 | import com.alibaba.fastjson.JSON; 15 | 16 | 17 | /** 18 | * EsApi 19 | * 20 | * @author sasou web:http://www.php-gene.com/ 21 | * @version 1.0.0 22 | */ 23 | public final class EsApi { 24 | 25 | private String canal_destination = null; 26 | private static RestClient rs = null; 27 | 28 | public EsApi(String name) throws Exception { 29 | canal_destination = name; 30 | try { 31 | rs = RestClient.builder(new HttpHost(GetProperties.target.get(canal_destination).ip, GetProperties.target.get(canal_destination).port, "http")).build(); 32 | } catch (Exception e) { 33 | rs.close(); 34 | throw new Exception("elasticsearch link fail", e); 35 | } 36 | } 37 | 38 | /** 39 | * @param index 40 | * @param content 41 | * @throws Exception 42 | */ 43 | public boolean sync(String index, String content) throws Exception { 44 | Map data = jsonToMap(content); 45 | Map head = jsonToMap((String) data.get("head").toString()); 46 | String type = (String) head.get("type").toString(); 47 | String id = (String) head.get("id").toString(); 48 | String text = ""; 49 | switch(type) { 50 | case "INSERT": 51 | text = (String) data.get("after").toString(); 52 | if (!"".equals(text)) { 53 | try { 54 | return insert(index, "default", id, text); 55 | } catch (Exception e) { 56 | throw new Exception("elasticsearch insert fail", e); 57 | } 58 | } 59 | break; 60 | case "UPDATE": 61 | text = (String) data.get("after").toString(); 62 | if (!"".equals(id)) { 63 | try { 64 | return update(index, "default", id, text); 65 | } catch (Exception e) { 66 | throw new Exception("elasticsearch update fail", e); 67 | } 68 | } 69 | break; 70 | case "DELETE": 71 | if (!"".equals(id)) { 72 | try { 73 | return delete(index, "default", id); 74 | } catch (Exception e) { 75 | 76 | } 77 | } 78 | break; 79 | } 80 | return true; 81 | } 82 | 83 | /** 84 | * json string to map 85 | * @param jsonObj 86 | * @return 87 | */ 88 | public static Map jsonToMap(String jsonObj) { 89 | @SuppressWarnings("unchecked") 90 | Map maps = (Map) JSON.parse((String) jsonObj); 91 | return maps; 92 | } 93 | 94 | /** 95 | * @param index 96 | * @param type 97 | * @param id 98 | * @param content 99 | * @throws Exception 100 | */ 101 | public boolean insert(String index, String type, String id, String content) throws Exception { 102 | Map params = Collections.emptyMap(); 103 | HttpEntity entity = new NStringEntity(content, ContentType.APPLICATION_JSON); 104 | Response response = rs.performRequest("PUT", "/" + index + "/" + type + "/" + id, params, entity); 105 | String ret = (String) EntityUtils.toString(response.getEntity()); 106 | return ret.contains("created") || ret.contains("updated"); 107 | } 108 | 109 | /** 110 | * @param index 111 | * @param type 112 | * @param id 113 | * @param content 114 | * @throws Exception 115 | */ 116 | public boolean update(String index, String type, String id, String content) throws Exception { 117 | Map params = Collections.emptyMap(); 118 | HttpEntity entity = new NStringEntity(content, ContentType.APPLICATION_JSON); 119 | Response response = rs.performRequest("PUT", "/" + index + "/" + type + "/" + id, params, entity); 120 | String ret = (String) EntityUtils.toString(response.getEntity()); 121 | return ret.contains("created") || ret.contains("updated"); 122 | } 123 | 124 | /** 125 | * @param index 126 | * @param type 127 | * @param id 128 | * @throws Exception 129 | */ 130 | public boolean delete(String index, String type, String id) throws Exception { 131 | Map params = Collections.emptyMap(); 132 | Response response = rs.performRequest("DELETE", "/"+ index + "/" + type + "/" + id, params); 133 | String ret = (String) EntityUtils.toString(response.getEntity()); 134 | return ret.contains("not_found") || ret.contains("deleted"); 135 | } 136 | 137 | /** 138 | * @param index 139 | * @param type 140 | * @param id 141 | * @throws IOException 142 | */ 143 | public String get(String index, String type, String id) throws Exception { 144 | try { 145 | Response response = rs.performRequest("GET", "/" + index + "/" + type + "/" + id, Collections.singletonMap("pretty", "true")); 146 | return EntityUtils.toString(response.getEntity()); 147 | } catch (Exception e) { 148 | e.printStackTrace(); 149 | } 150 | return ""; 151 | } 152 | 153 | /** 154 | * @param index 155 | * @throws IOException 156 | */ 157 | public boolean index(String index) throws Exception { 158 | try { 159 | Response response = rs.performRequest("HEAD", index, Collections.emptyMap()); 160 | return response.getStatusLine().getReasonPhrase().equals("OK"); 161 | } catch (Exception e) { 162 | 163 | } 164 | return false; 165 | } 166 | 167 | /** 168 | * @param index 169 | * @throws IOException 170 | */ 171 | public String getMappings(String index) throws Exception { 172 | try { 173 | Response response = rs.performRequest("GET", "/" + index + "/_mappings", Collections.emptyMap()); 174 | return EntityUtils.toString(response.getEntity()); 175 | } catch (Exception e) { 176 | 177 | } 178 | return ""; 179 | } 180 | 181 | /** 182 | * @param index 183 | * @throws IOException 184 | */ 185 | public String setMappings(String index) throws Exception { 186 | try { 187 | HttpEntity entity = new NStringEntity("{\"mappings\":{\"default\" :{\"properties\":{\"@timestamp\":{\"type\" : \"date\"}}}}}", ContentType.APPLICATION_JSON); 188 | Response response = rs.performRequest("PUT", "/" + index, Collections.emptyMap(), entity); 189 | return EntityUtils.toString(response.getEntity()); 190 | } catch (Exception e) { 191 | e.printStackTrace(); 192 | } 193 | return ""; 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/src/com/sync/common/GetProperties.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Properties; 6 | 7 | import com.alibaba.fastjson.JSONObject; 8 | import com.sync.common.ReadProperties; 9 | 10 | /** 11 | * GetProperties 12 | * 13 | * @author sasou web:http://www.php-gene.com/ 14 | * @version 1.0.0 15 | */ 16 | 17 | public class GetProperties { 18 | // debug 19 | public static int system_debug = 0; 20 | // canal 21 | public static CanalData canal = new CanalData(); 22 | 23 | // target 24 | public static Map target = new HashMap(); 25 | 26 | @SuppressWarnings("unchecked") 27 | public static boolean update() { 28 | // read config 29 | Properties prop = ReadProperties.readProperties(); 30 | String tmp = ""; 31 | 32 | // debug 33 | tmp = prop.getProperty("system.debug", ""); 34 | if (!"".equals(tmp)) { 35 | system_debug = Integer.parseInt(tmp); 36 | } 37 | 38 | // canal 39 | tmp = prop.getProperty("canal.ip", ""); 40 | if (!"".equals(tmp)) { 41 | canal.setIp(tmp); 42 | } 43 | 44 | tmp = prop.getProperty("canal.port", ""); 45 | if (!"".equals(tmp)) { 46 | canal.setPort(Integer.parseInt(tmp)); 47 | } 48 | canal.setDestination(prop.getProperty("canal.destination", "")); 49 | canal.setUsername(prop.getProperty("canal.username", "")); 50 | canal.setPassword(prop.getProperty("canal.password", "")); 51 | 52 | // target 53 | if (canal.destination != null) { 54 | TargetData target_tmp = null; 55 | int num = canal.destination.length; 56 | if (num > 0) { 57 | for (int i = 0; i < num; i++) { 58 | if (target.containsKey(canal.destination[i])) { 59 | target_tmp = target.get(canal.destination[i]); 60 | } else { 61 | target_tmp = new TargetData(); 62 | } 63 | 64 | tmp = prop.getProperty(canal.destination[i] + ".target_type", ""); 65 | if (!"".equals(tmp)) { 66 | target_tmp.setType(tmp); 67 | } 68 | tmp = prop.getProperty(canal.destination[i] + ".target_ip", ""); 69 | if (!"".equals(tmp)) { 70 | target_tmp.setIp(tmp); 71 | } 72 | if ("kafka".equals(target_tmp.type)) { 73 | target_tmp.setPort(9092); 74 | } 75 | if ("redis".equals(target_tmp.type)) { 76 | target_tmp.setPort(6379); 77 | } 78 | if ("elasticsearch".equals(target_tmp.type)) { 79 | target_tmp.setPort(9200); 80 | } 81 | if ("httpmq".equals(target_tmp.type)) { 82 | target_tmp.setPort(1218); 83 | } 84 | tmp = prop.getProperty(canal.destination[i] + ".target_port", ""); 85 | if (!"".equals(tmp)) { 86 | target_tmp.setPort(Integer.parseInt(tmp)); 87 | } 88 | tmp = prop.getProperty(canal.destination[i] + ".target_deep", ""); 89 | if (!"".equals(tmp)) { 90 | target_tmp.setDeep(Integer.parseInt(tmp)); 91 | } 92 | tmp = prop.getProperty(canal.destination[i] + ".target_filter_api", ""); 93 | target_tmp.setFilter(tmp); 94 | if (!"".equals(tmp)) { 95 | try { 96 | String json = HttpClient.sendGet(tmp, ""); 97 | @SuppressWarnings("rawtypes") 98 | Map filterMap = new HashMap(); 99 | syncCache(json, filterMap); 100 | target_tmp.setFilterMap(filterMap); 101 | } catch (Exception e) { 102 | System.out.println(e); 103 | } 104 | } 105 | 106 | if ("cache".equals(target_tmp.type)) { 107 | target_tmp.setPlugin(prop.getProperty(canal.destination[i] + ".target_plugin", "")); 108 | target_tmp.setSign(prop.getProperty(canal.destination[i] + ".target_version_sign", "")); 109 | } 110 | target.put(canal.destination[i], target_tmp); 111 | } 112 | } 113 | } 114 | prop.clear(); 115 | return true; 116 | } 117 | 118 | public static String get(String key) { 119 | // read config 120 | Properties prop = ReadProperties.readProperties(); 121 | return prop.getProperty(key, ""); 122 | } 123 | 124 | 125 | @SuppressWarnings({ "rawtypes", "unchecked" }) 126 | public static void syncCache(String jsonStr, Map cacheMap) { 127 | JSONObject jsonobject = JSONObject.parseObject(jsonStr); 128 | JSONObject db = null; 129 | try { 130 | db = (JSONObject) jsonobject.get("data"); 131 | } catch (Exception e) { 132 | return; 133 | } 134 | 135 | for (String dbName : db.keySet()){ 136 | JSONObject table = (JSONObject) db.get(dbName); 137 | for (String tableName : table.keySet()){ 138 | String key = dbName + "." + tableName; 139 | Map tableMap = null; 140 | if (cacheMap.containsKey(key)) { 141 | tableMap = (Map) cacheMap.get(key); 142 | } else { 143 | tableMap = new HashMap(); 144 | cacheMap.put(key, tableMap); 145 | } 146 | JSONObject field = (JSONObject) table.get(tableName); 147 | for (String fieldName : field.keySet()){ 148 | if (!tableMap.containsKey(fieldName)) { 149 | tableMap.put(fieldName, ""); 150 | } 151 | } 152 | } 153 | } 154 | } 155 | 156 | } -------------------------------------------------------------------------------- /src/src/com/sync/common/HttpClient.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sasou/syncClient/cf0b975b07d82642d7e1c2a83b5509ad29feb2f1/src/src/com/sync/common/HttpClient.java -------------------------------------------------------------------------------- /src/src/com/sync/common/HttpmqApi.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | public class HttpmqApi { 4 | 5 | private String canal_destination = null; 6 | private String url = null; 7 | 8 | public HttpmqApi(String name) { 9 | canal_destination = name; 10 | url = "http://" + GetProperties.target.get(canal_destination).ip + ":" + GetProperties.target.get(canal_destination).port + "?"; 11 | } 12 | 13 | /** 14 | * @param index 15 | * @param content 16 | * @throws Exception 17 | */ 18 | public boolean put(String type, String content) throws Exception { 19 | String ret = null; 20 | ret = HttpClient.sendPost(url + "charset=utf-8&opt=put&name=" + type, content); 21 | if (ret.indexOf("HTTPMQ_PUT_OK") != -1) { 22 | return true; 23 | } 24 | return false; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/src/com/sync/common/MemApi.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.io.IOException; 4 | import java.util.concurrent.TimeoutException; 5 | 6 | import net.rubyeye.xmemcached.MemcachedClient; 7 | import net.rubyeye.xmemcached.MemcachedClientBuilder; 8 | import net.rubyeye.xmemcached.XMemcachedClientBuilder; 9 | import net.rubyeye.xmemcached.exception.MemcachedException; 10 | import net.rubyeye.xmemcached.utils.AddrUtil; 11 | 12 | /** 13 | * MemApi 14 | * 15 | * @author sasou web:http://www.php-gene.com/ 16 | * @version 1.0.0 17 | */ 18 | 19 | public class MemApi { 20 | 21 | /** 22 | * MemCachedClient 23 | */ 24 | protected static MemcachedClient memCachedClient = null; 25 | 26 | 27 | 28 | /** 29 | * MemApi 30 | */ 31 | public MemApi(String name) 32 | { 33 | if (memCachedClient == null) { 34 | MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(GetProperties.target.get(name).ip + ":" + GetProperties.target.get(name).port)); 35 | try { 36 | memCachedClient = builder.build(); 37 | builder.setConnectionPoolSize(5); 38 | memCachedClient.setEnableHeartBeat(false); 39 | } catch (IOException e) { 40 | 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * @param key 47 | * @param value 48 | * @return boolean 49 | * @throws Exception 50 | */ 51 | public boolean set(String key, Object value) throws Exception { 52 | boolean blag = false; 53 | try { 54 | blag = memCachedClient.set(key, 0, value); 55 | } catch (MemcachedException e) { 56 | throw new Exception("MemcachedClient operation fail"); 57 | } catch (TimeoutException e) { 58 | throw new Exception("MemcachedClient operation timeout"); 59 | } catch (InterruptedException e) { 60 | // ignore 61 | } 62 | return blag; 63 | } 64 | 65 | /** 66 | * @param key 67 | * @param value 68 | * @param expiry 69 | * @return boolean 70 | * @throws Exception 71 | */ 72 | public boolean set(String key, Object value, int expiry) throws Exception{ 73 | boolean blag = false; 74 | try { 75 | blag = memCachedClient.set(key, expiry, value); 76 | } catch (MemcachedException e) { 77 | throw new Exception("MemcachedClient operation fail"); 78 | } catch (TimeoutException e) { 79 | throw new Exception("MemcachedClient operation timeout"); 80 | } catch (InterruptedException e) { 81 | // ignore 82 | } 83 | return blag; 84 | } 85 | 86 | /** 87 | * @param key 88 | * @param value 89 | * @return boolean 90 | * @throws Exception 91 | */ 92 | public boolean add(String key, Object value) throws Exception { 93 | boolean blag = false; 94 | try { 95 | if (get(key) != null) { 96 | return blag; 97 | } else { 98 | blag = memCachedClient.add(key, 0, value); 99 | } 100 | } catch (MemcachedException e) { 101 | throw new Exception("MemcachedClient operation fail"); 102 | } catch (TimeoutException e) { 103 | throw new Exception("MemcachedClient operation timeout"); 104 | } catch (InterruptedException e) { 105 | // ignore 106 | } 107 | return blag; 108 | } 109 | 110 | /** 111 | * @param key 112 | * @param value 113 | * @return boolean 114 | * @throws Exception 115 | */ 116 | public boolean replace(String key, Object value) throws Exception { 117 | boolean blag = false; 118 | try { 119 | blag = memCachedClient.replace(key, 0, value); 120 | } catch (MemcachedException e) { 121 | throw new Exception("MemcachedClient operation fail"); 122 | } catch (TimeoutException e) { 123 | throw new Exception("MemcachedClient operation timeout"); 124 | } catch (InterruptedException e) { 125 | // ignore 126 | } 127 | return blag; 128 | } 129 | 130 | /** 131 | * @param key 132 | * @param value 133 | * @param expiry 134 | * @return boolean 135 | * @throws Exception 136 | */ 137 | public boolean replace(String key, Object value, int expiry) throws Exception { 138 | boolean blag = false; 139 | try { 140 | blag = memCachedClient.replace(key, expiry, value); 141 | } catch (MemcachedException e) { 142 | throw new Exception("MemcachedClient operation fail"); 143 | } catch (TimeoutException e) { 144 | throw new Exception("MemcachedClient operation timeout"); 145 | } catch (InterruptedException e) { 146 | // ignore 147 | } 148 | return blag; 149 | } 150 | 151 | 152 | /** 153 | * 154 | * @param key 155 | * @return boolean 156 | * @throws Exception 157 | */ 158 | public String get(String key) throws Exception { 159 | String blag = ""; 160 | try { 161 | blag = memCachedClient.get(key).toString(); 162 | } catch (MemcachedException e) { 163 | throw new Exception("MemcachedClient operation fail"); 164 | } catch (TimeoutException e) { 165 | throw new Exception("MemcachedClient operation timeout"); 166 | } catch (InterruptedException e) { 167 | // ignore 168 | } 169 | return blag; 170 | } 171 | 172 | /** 173 | * incr 174 | * 175 | * @param key 176 | * @return boolean 177 | * @throws Exception 178 | */ 179 | public boolean incr(String key) throws Exception { 180 | boolean blag = false; 181 | try { 182 | long ret = memCachedClient.incr(key, 1, 1); 183 | if (ret > 0) { 184 | blag = true; 185 | } 186 | } catch (MemcachedException e) { 187 | throw new Exception("MemcachedClient operation fail"); 188 | } catch (TimeoutException e) { 189 | throw new Exception("MemcachedClient operation timeout"); 190 | } catch (InterruptedException e) { 191 | // ignore 192 | } 193 | return blag; 194 | } 195 | 196 | /** 197 | * @param key 198 | * @param value 199 | * @return boolean 200 | * @throws Exception 201 | */ 202 | public boolean delete(String key) throws Exception{ 203 | boolean blag = false; 204 | try { 205 | blag = memCachedClient.delete(key); 206 | } catch (MemcachedException e) { 207 | throw new Exception("MemcachedClient operation fail"); 208 | } catch (TimeoutException e) { 209 | throw new Exception("MemcachedClient operation timeout"); 210 | } catch (InterruptedException e) { 211 | // ignore 212 | } 213 | return blag; 214 | } 215 | 216 | } -------------------------------------------------------------------------------- /src/src/com/sync/common/ReadProperties.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | /** 11 | * config file read 12 | * 13 | * @author sasou web:http://www.php-gene.com/ 14 | * @version 1.0.0 15 | */ 16 | public class ReadProperties { 17 | static final String propertiesFilename = "SysConfig.properties"; 18 | private static Properties props = new Properties(); 19 | 20 | public static Properties readProperties() { 21 | try { 22 | InputStream inputStream = new BufferedInputStream(new FileInputStream(System.getProperty("user.dir") + "/" + propertiesFilename)); 23 | try { 24 | props.load(inputStream); 25 | } catch (IOException e) { 26 | 27 | } 28 | } catch (FileNotFoundException e) { 29 | 30 | } 31 | return props; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/src/com/sync/common/RedisApi.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | import redis.clients.jedis.Jedis; 7 | import redis.clients.jedis.JedisPool; 8 | import redis.clients.jedis.JedisPoolConfig; 9 | import redis.clients.jedis.exceptions.JedisConnectionException; 10 | 11 | /** 12 | * RedisApi 13 | * 14 | * @author sasou web:http://www.php-gene.com/ 15 | * @version 1.0.0 16 | */ 17 | 18 | public class RedisApi { 19 | private String canal_destination = null; 20 | private static JedisPool pool = null; 21 | 22 | public RedisApi(String name) { 23 | canal_destination = name; 24 | if (pool == null) { 25 | JedisPoolConfig config = new JedisPoolConfig(); 26 | config.setBlockWhenExhausted(true); 27 | config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy"); 28 | config.setJmxEnabled(true); 29 | config.setMaxTotal(10); 30 | config.setMaxIdle(5); 31 | config.setMaxWaitMillis(1000 * 100); 32 | config.setTestOnBorrow(true); 33 | pool = new JedisPool(config, GetProperties.target.get(canal_destination).ip, GetProperties.target.get(canal_destination).port, 1000 * 10); 34 | } 35 | } 36 | 37 | /** 38 | * return Resource to pool 39 | * 40 | * @param pool 41 | * @param redis 42 | */ 43 | public void returnResource(Jedis redis) { 44 | if (redis != null) { 45 | redis.close(); 46 | } 47 | } 48 | 49 | /** 50 | * get data 51 | * 52 | * @param key 53 | * @return 54 | */ 55 | public String get(String key) throws Exception { 56 | String value = null; 57 | Jedis jedis = null; 58 | try { 59 | jedis = pool.getResource(); 60 | value = jedis.get(key); 61 | } catch (JedisConnectionException e) { 62 | throw new Exception(" redis link fail", e); 63 | } 64 | returnResource(jedis); 65 | return value; 66 | } 67 | 68 | /** 69 | * zrange data 70 | * 71 | * @param key 72 | * @return 73 | */ 74 | @SuppressWarnings("rawtypes") 75 | public Set zrange(String key) throws Exception { 76 | Set value = null; 77 | Jedis jedis = null; 78 | try { 79 | jedis = pool.getResource(); 80 | value = jedis.zrange(key, 0, -1); 81 | } catch (JedisConnectionException e) { 82 | throw new Exception(" redis link fail", e); 83 | } 84 | returnResource(jedis); 85 | return value; 86 | } 87 | 88 | /** 89 | * lrange data 90 | * 91 | * @param key 92 | * @return 93 | */ 94 | @SuppressWarnings("rawtypes") 95 | public List lrange(String key) throws Exception { 96 | List value = null; 97 | Jedis jedis = null; 98 | try { 99 | jedis = pool.getResource(); 100 | value = jedis.lrange(key, 0, -1); 101 | } catch (JedisConnectionException e) { 102 | throw new Exception(" redis link fail", e); 103 | } 104 | returnResource(jedis); 105 | return value; 106 | } 107 | 108 | /** 109 | * set string 110 | * 111 | * @param key 112 | * @return 113 | * @throws Exception 114 | */ 115 | public void set(String key, String value) throws Exception { 116 | Jedis jedis = null; 117 | try { 118 | jedis = pool.getResource(); 119 | jedis.set(key, value); 120 | } catch (JedisConnectionException e) { 121 | throw new Exception(" redis link fail", e); 122 | } 123 | returnResource(jedis); 124 | } 125 | 126 | /** 127 | * set data 128 | * 129 | * @param key 130 | * @return 131 | */ 132 | public void zadd(String key, String member) throws Exception { 133 | Jedis jedis = null; 134 | try { 135 | jedis = pool.getResource(); 136 | long score = (jedis.exists(key)) ? (jedis.zcard(key)) : 0; 137 | jedis.zadd(key, score, member); 138 | } catch (JedisConnectionException e) { 139 | throw new Exception(" redis link fail", e); 140 | } 141 | returnResource(jedis); 142 | } 143 | 144 | /** 145 | * push list in left 146 | * 147 | * @param key 148 | * @return 149 | */ 150 | public void lpush(String key, String member) throws Exception { 151 | Jedis jedis = null; 152 | try { 153 | jedis = pool.getResource(); 154 | jedis.lpush(key, member); 155 | } catch (JedisConnectionException e) { 156 | throw new Exception(" redis link fail", e); 157 | } 158 | returnResource(jedis); 159 | } 160 | 161 | /** 162 | * push list in right 163 | * 164 | * @param key 165 | * @return 166 | */ 167 | public void rpush(String key, String member) throws Exception { 168 | Jedis jedis = null; 169 | try { 170 | jedis = pool.getResource(); 171 | jedis.rpush(key, member); 172 | } catch (JedisConnectionException e) { 173 | throw new Exception(" redis link fail", e); 174 | } 175 | returnResource(jedis); 176 | } 177 | 178 | /** 179 | * exists 180 | * 181 | * @param key 182 | * @return 183 | */ 184 | public boolean exists(String key) throws Exception { 185 | 186 | Jedis jedis = null; 187 | boolean blag = false; 188 | try { 189 | jedis = pool.getResource(); 190 | blag = jedis.exists(key); 191 | } catch (JedisConnectionException e) { 192 | throw new Exception(" redis link fail", e); 193 | } 194 | returnResource(jedis); 195 | return blag; 196 | } 197 | 198 | /** 199 | * del 200 | * 201 | * @param key 202 | * @return 203 | */ 204 | public void del(String key) throws Exception { 205 | Jedis jedis = null; 206 | try { 207 | jedis = pool.getResource(); 208 | jedis.del(key); 209 | } catch (JedisConnectionException e) { 210 | throw new Exception(" redis link fail", e); 211 | } 212 | returnResource(jedis); 213 | } 214 | 215 | /** 216 | * lrem 217 | * 218 | * @param key 219 | * @return 220 | */ 221 | public void lrem(String key, String member) throws Exception { 222 | Jedis jedis = null; 223 | try { 224 | jedis = pool.getResource(); 225 | jedis.lrem(key, 1, member); 226 | } catch (JedisConnectionException e) { 227 | throw new Exception(" redis link fail", e); 228 | } 229 | returnResource(jedis); 230 | } 231 | 232 | /** 233 | * zrem 234 | * 235 | * @param key 236 | * @return 237 | */ 238 | public void zrem(String key, String member) throws Exception { 239 | Jedis jedis = null; 240 | try { 241 | jedis = pool.getResource(); 242 | jedis.zrem(key, member); 243 | } catch (JedisConnectionException e) { 244 | throw new Exception(" redis link fail", e); 245 | } 246 | returnResource(jedis); 247 | } 248 | 249 | /** 250 | * expire 251 | * 252 | * @param key 253 | * @param num 254 | */ 255 | public void expire(String key, int num) throws Exception { 256 | Jedis jedis = null; 257 | try { 258 | jedis = pool.getResource(); 259 | jedis.expire(key, num * 60); 260 | } catch (JedisConnectionException e) { 261 | throw new Exception(" redis link fail", e); 262 | } 263 | returnResource(jedis); 264 | } 265 | 266 | /** 267 | * incr 1 268 | * 269 | * @param key 270 | */ 271 | public void incr(String key) throws Exception { 272 | Jedis jedis = null; 273 | try { 274 | jedis = pool.getResource(); 275 | jedis.incr(key); 276 | } catch (JedisConnectionException e) { 277 | throw new Exception(" redis link fail", e); 278 | } 279 | returnResource(jedis); 280 | } 281 | 282 | /** 283 | * clear 284 | * 285 | * @param num 286 | */ 287 | public void clear() throws Exception { 288 | Jedis jedis = null; 289 | try { 290 | jedis = pool.getResource(); 291 | jedis.flushDB(); 292 | } catch (JedisConnectionException e) { 293 | throw new Exception(" redis link fail", e); 294 | } 295 | returnResource(jedis); 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /src/src/com/sync/common/SsdbApi.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | 4 | import com.udpwork.ssdb.*; 5 | 6 | 7 | /** 8 | * SsdbApi 9 | * 10 | * @author sasou web:http://www.php-gene.com/ 11 | * @version 1.0.0 12 | */ 13 | 14 | public class SsdbApi { 15 | private String canal_destination = null; 16 | private static SSDB ssdb = null; 17 | 18 | public SsdbApi(String name) { 19 | canal_destination = name; 20 | } 21 | 22 | public SSDB instance() throws Exception { 23 | if (ssdb == null) { 24 | ssdb = new SSDB(GetProperties.target.get(canal_destination).ip ,GetProperties.target.get(canal_destination).port, 1000 * 10); 25 | } 26 | return ssdb; 27 | } 28 | 29 | 30 | /** 31 | * get data 32 | * 33 | * @param key 34 | * @return 35 | * @throws Exception 36 | */ 37 | public String get(String key) throws Exception { 38 | byte[] resp = null; 39 | try { 40 | instance(); 41 | if (ssdb != null) { 42 | resp = ssdb.get(key); 43 | } 44 | } catch (Exception e) { 45 | if (ssdb != null) { 46 | ssdb.close(); 47 | ssdb = null; 48 | } 49 | throw new Exception(" ssdb link fail", e); 50 | } 51 | return resp.toString(); 52 | } 53 | 54 | 55 | /** 56 | * push list in right 57 | * 58 | * @param key 59 | * @return 60 | * @return 61 | */ 62 | public void rpush(String key, String member) throws Exception { 63 | try { 64 | instance(); 65 | if (ssdb != null) { 66 | ssdb.request("qpush", key, member); 67 | } 68 | } catch (Exception e) { 69 | if (ssdb != null) { 70 | ssdb.close(); 71 | ssdb = null; 72 | } 73 | throw new Exception(" ssdb link fail", e); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/src/com/sync/common/TargetData.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * TargetData 8 | * 9 | * @author sasou web:http://www.php-gene.com/ 10 | * @version 1.0.0 11 | */ 12 | public final class TargetData { 13 | public String type = ""; 14 | public String ip = ""; 15 | public int port = 0; 16 | public int deep = 1; 17 | public String plugin = ""; 18 | public String filter = ""; 19 | public String sign = ""; 20 | 21 | @SuppressWarnings("rawtypes") 22 | public Map filterMap = new HashMap(); 23 | 24 | /** 25 | * @return the type 26 | */ 27 | public String getType() { 28 | return type; 29 | } 30 | 31 | /** 32 | * @param type 33 | * the type to set 34 | */ 35 | public void setType(String type) { 36 | this.type = type; 37 | } 38 | 39 | /** 40 | * @return the ip 41 | */ 42 | public String getIp() { 43 | return ip; 44 | } 45 | 46 | /** 47 | * @param ip 48 | * the ip to set 49 | */ 50 | public void setIp(String ip) { 51 | this.ip = ip; 52 | } 53 | 54 | /** 55 | * @return the port 56 | */ 57 | public int getPort() { 58 | return port; 59 | } 60 | 61 | /** 62 | * @param port 63 | * the port to set 64 | */ 65 | public void setPort(int port) { 66 | this.port = port; 67 | } 68 | 69 | /** 70 | * @return the deep 71 | */ 72 | public int getDeep() { 73 | return deep; 74 | } 75 | 76 | /** 77 | * @param deep 78 | * the deep to set 79 | */ 80 | public void setDeep(int deep) { 81 | this.deep = deep; 82 | } 83 | 84 | /** 85 | * @return the plugin 86 | */ 87 | public String getPlugin() { 88 | return plugin; 89 | } 90 | 91 | /** 92 | * @param plugin 93 | * the plugin to set 94 | */ 95 | public void setPlugin(String plugin) { 96 | this.plugin = plugin; 97 | } 98 | 99 | /** 100 | * @return the filter 101 | */ 102 | public String getFilter() { 103 | return filter; 104 | } 105 | 106 | /** 107 | * @param filter 108 | * the filter to set 109 | */ 110 | public void setFilter(String filter) { 111 | this.filter = filter; 112 | } 113 | 114 | /** 115 | * @return the sign 116 | */ 117 | public String getSign() { 118 | return sign; 119 | } 120 | 121 | /** 122 | * @param sign 123 | * the sign to set 124 | */ 125 | public void setSign(String sign) { 126 | this.sign = sign; 127 | } 128 | 129 | /** 130 | * @return the filterMap 131 | */ 132 | @SuppressWarnings("rawtypes") 133 | public Map getFilterMap() { 134 | return filterMap; 135 | } 136 | 137 | /** 138 | * @param filterMap 139 | * the filterMap to set 140 | */ 141 | @SuppressWarnings("rawtypes") 142 | public void setFilterMap(Map filterMap) { 143 | this.filterMap = filterMap; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/src/com/sync/common/Tool.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | import java.security.MessageDigest; 4 | 5 | public class Tool { 6 | 7 | public static boolean checkFilter(String destination, String db, String table) { 8 | if ("".equals(db) || "".equals(table)) { 9 | return false; 10 | } 11 | if (!"".equals(GetProperties.target.get(destination).filter)) { 12 | String key = db + "." + table; 13 | if (GetProperties.target.get(destination).filterMap.containsKey(key)) { 14 | return true; 15 | } 16 | return false; 17 | } 18 | return true; 19 | } 20 | 21 | public static String makeTargetName(String canal_destination, String db, String table) { 22 | int type = GetProperties.target.get(canal_destination).deep; 23 | String ret = null; 24 | switch(type) { 25 | case 1: 26 | ret = "sync_" + canal_destination + "_" + db + "_" + table; 27 | break; 28 | case 2: 29 | ret = "sync_" + canal_destination + "_" + db; 30 | break; 31 | case 3: 32 | ret = "sync_" + canal_destination; 33 | break; 34 | case 4: 35 | ret = "sync_" + "_" + db + "_" + table; 36 | break; 37 | default: 38 | ret = "sync_" + canal_destination + "_" + db + "_" + table; 39 | break; 40 | } 41 | return ret; 42 | } 43 | 44 | public static String md5(String s) { 45 | char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 46 | try { 47 | byte[] btInput = s.getBytes("UTF-8"); 48 | MessageDigest mdInst = MessageDigest.getInstance("MD5"); 49 | mdInst.update(btInput); 50 | byte[] md = mdInst.digest(); 51 | int j = md.length; 52 | char str[] = new char[j * 2]; 53 | int k = 0; 54 | for (int i = 0; i < j; i++) { 55 | byte byte0 = md[i]; 56 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 57 | str[k++] = hexDigits[byte0 & 0xf]; 58 | } 59 | String rec = new String(str); 60 | return rec.toLowerCase(); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | return null; 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/src/com/sync/common/WriteLog.java: -------------------------------------------------------------------------------- 1 | package com.sync.common; 2 | 3 | /** 4 | * WriteLog 5 | * 6 | * @author sasou web:http://www.php-gene.com/ 7 | * @version 1.0.0 8 | */ 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | import java.io.PrintWriter; 13 | import java.io.StringWriter; 14 | import java.util.Calendar; 15 | 16 | /** 17 | * write logString 18 | * 19 | * @param logString 20 | */ 21 | public class WriteLog { 22 | public static String base = null; 23 | 24 | public static void write(String type, String logString) { 25 | if (base == null) { 26 | base = System.getProperty("user.dir"); 27 | } 28 | 29 | String current = base + "/logs/"; 30 | try { 31 | String logFilePathName = null; 32 | Calendar cd = Calendar.getInstance(); 33 | int year = cd.get(Calendar.YEAR); 34 | String month = addZero(cd.get(Calendar.MONTH) + 1); 35 | String day = addZero(cd.get(Calendar.DAY_OF_MONTH)); 36 | String hour = addZero(cd.get(Calendar.HOUR_OF_DAY)); 37 | String min = addZero(cd.get(Calendar.MINUTE)); 38 | String sec = addZero(cd.get(Calendar.SECOND)); 39 | current += year + "-" + month + "-" + day + "/"; 40 | 41 | File fileParentDir = new File(current); 42 | if (!fileParentDir.exists()) { 43 | fileParentDir.mkdirs(); 44 | } 45 | 46 | logFilePathName = current + type + ".log"; 47 | 48 | FileOutputStream fos = new FileOutputStream(logFilePathName, true); 49 | String time = "[" + year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec + "] "; 50 | String content = time + logString + "\r\n"; 51 | fos.write(content.getBytes()); 52 | fos.flush(); 53 | fos.close(); 54 | if (GetProperties.system_debug > 0) { 55 | System.out.println(logString); 56 | } 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | 62 | /** 63 | * add 0 64 | * 65 | * @param i 66 | * @return 67 | */ 68 | public static String addZero(int i) { 69 | if (i < 10) { 70 | String tmpString = "0" + i; 71 | return tmpString; 72 | } else { 73 | return String.valueOf(i); 74 | } 75 | } 76 | 77 | 78 | /** 79 | * eString 80 | * 81 | * @param object e 82 | * @return string 83 | */ 84 | public static String eString(Exception e) { 85 | StringWriter sw = null; 86 | PrintWriter pw = null; 87 | try { 88 | sw = new StringWriter(); 89 | pw = new PrintWriter(sw); 90 | e.printStackTrace(pw); 91 | pw.flush(); 92 | sw.flush(); 93 | } finally { 94 | if (sw != null) { 95 | try { 96 | sw.close(); 97 | } catch (IOException e1) { 98 | e1.printStackTrace(); 99 | } 100 | } 101 | if (pw != null) { 102 | pw.close(); 103 | } 104 | } 105 | return sw.toString(); 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/Cache.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashSet; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import com.alibaba.otter.canal.client.CanalConnector; 10 | import com.alibaba.otter.canal.client.CanalConnectors; 11 | import com.alibaba.otter.canal.protocol.Message; 12 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 13 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 14 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 15 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 16 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 17 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 18 | import com.sync.common.GetProperties; 19 | import com.sync.common.MemApi; 20 | import com.sync.common.RedisApi; 21 | import com.sync.common.Tool; 22 | import com.sync.common.WriteLog; 23 | import com.alibaba.fastjson.JSON; 24 | 25 | /** 26 | * Cache Producer 27 | * 28 | * @author sasou web:http://www.php-gene.com/ 29 | * @version 1.0.0 30 | */ 31 | public class Cache implements Runnable { 32 | private RedisApi RedisPool = null; 33 | private MemApi MemPool = null; 34 | private CanalConnector connector = null; 35 | private String thread_name = null; 36 | private String canal_destination = null; 37 | private String sign = null; 38 | 39 | public Cache(String name) { 40 | thread_name = "canal[" + name + "]:"; 41 | canal_destination = name; 42 | sign = GetProperties.target.get(canal_destination).sign; 43 | } 44 | 45 | public void process() { 46 | int batchSize = 1000; 47 | connector = CanalConnectors.newSingleConnector( 48 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 49 | GetProperties.canal.username, GetProperties.canal.password); 50 | 51 | connector.connect(); 52 | connector.subscribe(); 53 | 54 | try { 55 | if("redis".equals(GetProperties.target.get(canal_destination).plugin)) { 56 | RedisPool = new RedisApi(canal_destination); 57 | } 58 | if("memcached".equals(GetProperties.target.get(canal_destination).plugin)) { 59 | MemPool = new MemApi(canal_destination); 60 | } 61 | 62 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 63 | while (true) { 64 | Message message = connector.getWithoutAck(batchSize); // get batch num 65 | long batchId = message.getId(); 66 | int size = message.getEntries().size(); 67 | if (!(batchId == -1 || size == 0)) { 68 | if (syncEntry(message.getEntries())) { 69 | connector.ack(batchId); // commit 70 | } else { 71 | connector.rollback(batchId); // rollback 72 | } 73 | } 74 | } 75 | } catch (Exception e) { 76 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 77 | } 78 | } 79 | 80 | public void run() { 81 | while (true) { 82 | try { 83 | process(); 84 | } catch (Exception e) { 85 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 86 | } finally { 87 | if (connector != null) { 88 | connector.disconnect(); 89 | connector = null; 90 | } 91 | } 92 | } 93 | } 94 | 95 | private boolean syncEntry(List entrys) { 96 | String table = ""; 97 | boolean ret = true; 98 | for (Entry entry : entrys) { 99 | EntryType type = entry.getEntryType(); 100 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 101 | continue; 102 | } 103 | table = entry.getHeader().getSchemaName() + "." + entry.getHeader().getTableName(); 104 | if (".".equals(table)) { 105 | continue; 106 | } 107 | RowChange rowChage = null; 108 | try { 109 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 110 | } catch (Exception e) { 111 | throw new RuntimeException( 112 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 113 | } 114 | 115 | EventType eventType = rowChage.getEventType(); 116 | HashSet versionField = new HashSet(); 117 | versionField.add(table); 118 | for (RowData rowData : rowChage.getRowDatasList()) { 119 | if (eventType == EventType.DELETE) { 120 | updateColumn(versionField, rowData.getBeforeColumnsList(), table); 121 | } else if (eventType == EventType.INSERT) { 122 | updateColumn(versionField, rowData.getAfterColumnsList(), table); 123 | } else { 124 | updateColumn(versionField, rowData.getBeforeColumnsList(), table); 125 | updateColumn(versionField, rowData.getAfterColumnsList(), table); 126 | } 127 | } 128 | 129 | try { 130 | Iterator iterator = versionField.iterator(); 131 | while (iterator.hasNext()) { 132 | if("redis".equals(GetProperties.target.get(canal_destination).plugin)) { 133 | RedisPool.incr(sign + Tool.md5(iterator.next())); 134 | } 135 | if("memcached".equals(GetProperties.target.get(canal_destination).plugin)) { 136 | MemPool.incr(sign + Tool.md5(iterator.next())); 137 | } 138 | } 139 | if (GetProperties.system_debug > 0) { 140 | String text = JSON.toJSONString(versionField); 141 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + text + ")"); 142 | } 143 | } catch (Exception e) { 144 | WriteLog.write(canal_destination + ".error", thread_name + "cache link failure!" + WriteLog.eString(e)); 145 | ret = false; 146 | } 147 | versionField.clear(); 148 | versionField = null; 149 | } 150 | return ret; 151 | } 152 | 153 | @SuppressWarnings("rawtypes") 154 | private void updateColumn(HashSet versionField, List columns, String table) { 155 | Map field = (Map) GetProperties.target.get(canal_destination).filterMap.get(table); 156 | for (Column column : columns) { 157 | String key = table + "." + column.getName(); 158 | if (column.getIsKey()) { 159 | versionField.add(key + "." + column.getValue()); 160 | } else { 161 | if (field != null && field.containsKey(column.getName())) { 162 | versionField.add(key + "." + column.getValue()); 163 | } 164 | } 165 | } 166 | } 167 | 168 | protected void finalize() throws Throwable { 169 | if (connector != null) { 170 | connector.disconnect(); 171 | connector = null; 172 | } 173 | } 174 | 175 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/ElasticSearch.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import org.apache.commons.lang.time.DateFormatUtils; 11 | 12 | import com.alibaba.otter.canal.client.CanalConnector; 13 | import com.alibaba.otter.canal.client.CanalConnectors; 14 | import com.alibaba.otter.canal.protocol.Message; 15 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 16 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 17 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 18 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 19 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 20 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 21 | import com.sync.common.EsApi; 22 | import com.sync.common.GetProperties; 23 | import com.sync.common.Tool; 24 | import com.sync.common.WriteLog; 25 | import com.alibaba.fastjson.JSON; 26 | 27 | /** 28 | * ElasticSearch Producer 29 | * 30 | * @author sasou web:http://www.php-gene.com/ 31 | * @version 1.0.0 32 | */ 33 | public class ElasticSearch implements Runnable { 34 | private EsApi es = null; 35 | private CanalConnector connector = null; 36 | private String thread_name = null; 37 | private String canal_destination = null; 38 | 39 | public ElasticSearch(String name) { 40 | thread_name = "canal[" + name + "]:"; 41 | canal_destination = name; 42 | } 43 | 44 | public void process() { 45 | int batchSize = 1000; 46 | connector = CanalConnectors.newSingleConnector( 47 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 48 | GetProperties.canal.username, GetProperties.canal.password); 49 | 50 | connector.connect(); 51 | connector.subscribe(); 52 | 53 | try { 54 | es = new EsApi(canal_destination); 55 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 56 | while (true) { 57 | Message message = connector.getWithoutAck(batchSize); // get batch num 58 | long batchId = message.getId(); 59 | int size = message.getEntries().size(); 60 | if (!(batchId == -1 || size == 0)) { 61 | if (syncEntry(message.getEntries())) { 62 | connector.ack(batchId); // commit 63 | } else { 64 | connector.rollback(batchId); // rollback 65 | } 66 | } 67 | } 68 | } catch (Exception e) { 69 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 70 | } 71 | } 72 | 73 | public void run() { 74 | while (true) { 75 | try { 76 | process(); 77 | } catch (Exception e) { 78 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 79 | } finally { 80 | if (connector != null) { 81 | connector.disconnect(); 82 | connector = null; 83 | } 84 | } 85 | } 86 | } 87 | 88 | private boolean syncEntry(List entrys) { 89 | String topic = ""; 90 | int no = 0; 91 | boolean ret = true; 92 | for (Entry entry : entrys) { 93 | EntryType type = entry.getEntryType(); 94 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 95 | continue; 96 | } 97 | String db = entry.getHeader().getSchemaName(); 98 | String table = entry.getHeader().getTableName(); 99 | if (!Tool.checkFilter(canal_destination, db, table)) { 100 | continue; 101 | } 102 | RowChange rowChage = null; 103 | try { 104 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 105 | } catch (Exception e) { 106 | throw new RuntimeException( 107 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 108 | } 109 | 110 | EventType eventType = rowChage.getEventType(); 111 | Map data = new HashMap(); 112 | Map head = new HashMap(); 113 | head.put("binlog_file", entry.getHeader().getLogfileName()); 114 | head.put("binlog_pos", entry.getHeader().getLogfileOffset()); 115 | head.put("db", db); 116 | head.put("table", table); 117 | head.put("type", eventType); 118 | data.put("head", head); 119 | topic = Tool.makeTargetName(canal_destination, db, table); 120 | no = (int) entry.getHeader().getLogfileOffset(); 121 | for (RowData rowData : rowChage.getRowDatasList()) { 122 | if (eventType == EventType.DELETE) { 123 | head.put("id", getIndex(rowData.getBeforeColumnsList())); 124 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 125 | } else if (eventType == EventType.INSERT) { 126 | head.put("id", getIndex(rowData.getAfterColumnsList())); 127 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 128 | } else { 129 | head.put("id", getIndex(rowData.getAfterColumnsList())); 130 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 131 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 132 | } 133 | String text = JSON.toJSONString(data); 134 | try { 135 | ret = es.sync(topic, text); 136 | if (GetProperties.system_debug > 0) { 137 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + topic + "," + no + ", " + text + ")"); 138 | } 139 | } catch (Exception e) { 140 | WriteLog.write(canal_destination + ".error", thread_name + "es link failure!"+ WriteLog.eString(e)); 141 | ret = false; 142 | } 143 | } 144 | data.clear(); 145 | data = null; 146 | } 147 | return ret; 148 | } 149 | 150 | private String getIndex(List columns) { 151 | String ret = ""; 152 | for (Column column : columns) { 153 | if (column.getIsKey()) { 154 | ret = (String) column.getValue().toString(); 155 | break; 156 | } 157 | } 158 | return ret; 159 | } 160 | 161 | private Map makeColumn(List columns) { 162 | Map one = new HashMap(); 163 | String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS"; 164 | for (Column column : columns) { 165 | String mt = column.getMysqlType(); 166 | if (mt.contains("timestamp") || mt.contains("datetime")) { 167 | if (!"".equals(column.getValue())) { 168 | Date date = stringToDate(column.getValue()); 169 | one.put(column.getName(), DateFormatUtils.format(date, pattern) + "+0800"); 170 | } 171 | } else { 172 | one.put(column.getName(), column.getValue()); 173 | } 174 | } 175 | one.put("@timestamp", DateFormatUtils.format(new Date(), pattern) + "+0800"); 176 | return one; 177 | } 178 | 179 | public static Date stringToDate(String source) { 180 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 181 | Date date = null; 182 | try { 183 | date = simpleDateFormat.parse(source); 184 | } catch (Exception e) { 185 | } 186 | return date; 187 | } 188 | 189 | protected void finalize() throws Throwable { 190 | if (connector != null) { 191 | connector.disconnect(); 192 | connector = null; 193 | } 194 | } 195 | 196 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/Httpmq.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import com.alibaba.otter.canal.client.CanalConnector; 8 | import com.alibaba.otter.canal.client.CanalConnectors; 9 | import com.alibaba.otter.canal.protocol.Message; 10 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 11 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 12 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 13 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 14 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 15 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 16 | import com.sync.common.GetProperties; 17 | import com.sync.common.HttpmqApi; 18 | import com.sync.common.Tool; 19 | import com.sync.common.WriteLog; 20 | import com.alibaba.fastjson.JSON; 21 | 22 | /** 23 | * Httpmq Producer 24 | * 25 | * @author sasou web:http://www.php-gene.com/ 26 | * @version 1.0.0 27 | */ 28 | public class Httpmq implements Runnable { 29 | private HttpmqApi httpmqApi = null; 30 | private CanalConnector connector = null; 31 | private String thread_name = null; 32 | private String canal_destination = null; 33 | 34 | public Httpmq(String name) { 35 | thread_name = "canal[" + name + "]:"; 36 | canal_destination = name; 37 | } 38 | 39 | public void process() { 40 | int batchSize = 1000; 41 | connector = CanalConnectors.newSingleConnector( 42 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 43 | GetProperties.canal.username, GetProperties.canal.password); 44 | 45 | connector.connect(); 46 | connector.subscribe(); 47 | 48 | try { 49 | httpmqApi = new HttpmqApi(canal_destination); 50 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 51 | while (true) { 52 | Message message = connector.getWithoutAck(batchSize); // get batch num 53 | long batchId = message.getId(); 54 | int size = message.getEntries().size(); 55 | if (!(batchId == -1 || size == 0)) { 56 | if (syncEntry(message.getEntries())) { 57 | connector.ack(batchId); // commit 58 | } else { 59 | connector.rollback(batchId); // rollback 60 | } 61 | } 62 | } 63 | } catch (Exception e) { 64 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 65 | } 66 | } 67 | 68 | public void run() { 69 | while (true) { 70 | try { 71 | process(); 72 | } catch (Exception e) { 73 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 74 | } finally { 75 | if (connector != null) { 76 | connector.disconnect(); 77 | connector = null; 78 | } 79 | } 80 | } 81 | } 82 | 83 | private boolean syncEntry(List entrys) { 84 | int no = 0; 85 | boolean ret = true; 86 | for (Entry entry : entrys) { 87 | EntryType type = entry.getEntryType(); 88 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 89 | continue; 90 | } 91 | String db = entry.getHeader().getSchemaName(); 92 | String table = entry.getHeader().getTableName(); 93 | if (!Tool.checkFilter(canal_destination, db, table)) { 94 | continue; 95 | } 96 | RowChange rowChage = null; 97 | try { 98 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 99 | } catch (Exception e) { 100 | throw new RuntimeException( 101 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 102 | } 103 | 104 | EventType eventType = rowChage.getEventType(); 105 | Map data = new HashMap(); 106 | Map head = new HashMap(); 107 | head.put("binlog_file", entry.getHeader().getLogfileName()); 108 | head.put("binlog_pos", entry.getHeader().getLogfileOffset()); 109 | head.put("db", db); 110 | head.put("table", table); 111 | head.put("type", eventType); 112 | data.put("head", head); 113 | String topic = Tool.makeTargetName(canal_destination, db, table); 114 | no = (int) entry.getHeader().getLogfileOffset(); 115 | for (RowData rowData : rowChage.getRowDatasList()) { 116 | if (eventType == EventType.DELETE) { 117 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 118 | } else if (eventType == EventType.INSERT) { 119 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 120 | } else { 121 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 122 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 123 | } 124 | String text = JSON.toJSONString(data); 125 | try { 126 | if (!httpmqApi.put(topic, text)) { 127 | ret = false; 128 | } 129 | if (GetProperties.system_debug > 0) { 130 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + topic + "," + no + ", " + text + ")"); 131 | } 132 | } catch (Exception e) { 133 | WriteLog.write(canal_destination + ".error", thread_name + "httpmq link failure!" + WriteLog.eString(e)); 134 | ret = false; 135 | } 136 | } 137 | data.clear(); 138 | data = null; 139 | } 140 | return ret; 141 | } 142 | 143 | private Map makeColumn(List columns) { 144 | Map one = new HashMap(); 145 | for (Column column : columns) { 146 | one.put(column.getName(), column.getValue()); 147 | } 148 | return one; 149 | } 150 | 151 | protected void finalize() throws Throwable { 152 | if (connector != null) { 153 | connector.disconnect(); 154 | connector = null; 155 | } 156 | } 157 | 158 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/Kafka.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Properties; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | import org.apache.kafka.clients.producer.KafkaProducer; 11 | import org.apache.kafka.clients.producer.ProducerRecord; 12 | import org.apache.kafka.clients.producer.RecordMetadata; 13 | import com.alibaba.otter.canal.client.CanalConnector; 14 | import com.alibaba.otter.canal.client.CanalConnectors; 15 | import com.alibaba.otter.canal.protocol.Message; 16 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 17 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 18 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 19 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 20 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 21 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 22 | import com.sync.common.GetProperties; 23 | import com.sync.common.Tool; 24 | import com.sync.common.WriteLog; 25 | import com.alibaba.fastjson.JSON; 26 | 27 | /** 28 | * kafka Producer 29 | * 30 | * @author sasou web:http://www.php-gene.com/ 31 | * @version 1.0.0 32 | */ 33 | public class Kafka implements Runnable { 34 | private KafkaProducer producer; 35 | private CanalConnector connector = null; 36 | private String thread_name = null; 37 | private String canal_destination = null; 38 | 39 | public Kafka(String name) { 40 | thread_name = "canal[" + name + "]:"; 41 | canal_destination = name; 42 | } 43 | 44 | public void process() { 45 | Properties props = new Properties(); 46 | props.put("bootstrap.servers", GetProperties.target.get(canal_destination).ip + ":" + GetProperties.target.get(canal_destination).port); 47 | props.put("client.id", canal_destination + "_Producer"); 48 | props.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer"); 49 | props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); 50 | 51 | int batchSize = 1000; 52 | connector = CanalConnectors.newSingleConnector( 53 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 54 | GetProperties.canal.username, GetProperties.canal.password); 55 | 56 | connector.connect(); 57 | connector.subscribe(); 58 | 59 | try { 60 | producer = new KafkaProducer<>(props); 61 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 62 | while (true) { 63 | Message message = connector.getWithoutAck(batchSize); // get batch num 64 | long batchId = message.getId(); 65 | int size = message.getEntries().size(); 66 | if (!(batchId == -1 || size == 0)) { 67 | if (syncEntry(message.getEntries())) { 68 | connector.ack(batchId); // commit 69 | } else { 70 | connector.rollback(batchId); // rollback 71 | } 72 | } 73 | } 74 | } catch (Exception e) { 75 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 76 | } 77 | } 78 | 79 | public void run() { 80 | while (true) { 81 | try { 82 | process(); 83 | } catch (Exception e) { 84 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 85 | } finally { 86 | if (connector != null) { 87 | connector.disconnect(); 88 | connector = null; 89 | } 90 | } 91 | } 92 | } 93 | 94 | private boolean syncEntry(List entrys) { 95 | String topic = ""; 96 | int no = 0; 97 | RecordMetadata metadata = null; 98 | boolean ret = true; 99 | for (Entry entry : entrys) { 100 | EntryType type = entry.getEntryType(); 101 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 102 | continue; 103 | } 104 | String db = entry.getHeader().getSchemaName(); 105 | String table = entry.getHeader().getTableName(); 106 | if (!Tool.checkFilter(canal_destination, db, table)) { 107 | continue; 108 | } 109 | RowChange rowChage = null; 110 | try { 111 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 112 | } catch (Exception e) { 113 | throw new RuntimeException( 114 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 115 | } 116 | 117 | EventType eventType = rowChage.getEventType(); 118 | Map data = new HashMap(); 119 | Map head = new HashMap(); 120 | head.put("binlog_file", entry.getHeader().getLogfileName()); 121 | head.put("binlog_pos", entry.getHeader().getLogfileOffset()); 122 | head.put("db", db); 123 | head.put("table", table); 124 | head.put("type", eventType); 125 | data.put("head", head); 126 | topic = Tool.makeTargetName(canal_destination, db, table); 127 | no = (int) entry.getHeader().getLogfileOffset(); 128 | for (RowData rowData : rowChage.getRowDatasList()) { 129 | if (eventType == EventType.DELETE) { 130 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 131 | } else if (eventType == EventType.INSERT) { 132 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 133 | } else { 134 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 135 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 136 | } 137 | String text = JSON.toJSONString(data); 138 | try { 139 | metadata = producer.send(new ProducerRecord<>(topic, no, text)).get(); 140 | if (metadata == null) { 141 | ret = false; 142 | } 143 | if (GetProperties.system_debug > 0) { 144 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + topic + "," + no + ", " + text + ")"); 145 | } 146 | } catch (InterruptedException | ExecutionException e) { 147 | WriteLog.write(canal_destination + ".error", thread_name + "kafka link failure!"+ WriteLog.eString(e)); 148 | ret = false; 149 | } 150 | } 151 | data.clear(); 152 | data = null; 153 | } 154 | return ret; 155 | } 156 | 157 | private Map makeColumn(List columns) { 158 | Map one = new HashMap(); 159 | for (Column column : columns) { 160 | one.put(column.getName(), column.getValue()); 161 | } 162 | return one; 163 | } 164 | 165 | protected void finalize() throws Throwable { 166 | if (connector != null) { 167 | connector.disconnect(); 168 | connector = null; 169 | } 170 | } 171 | 172 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/Prop.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import com.sync.common.GetProperties; 4 | 5 | public class Prop implements Runnable { 6 | 7 | public void run() { 8 | while (true) { 9 | GetProperties.update(); 10 | try { 11 | Thread.sleep(1000 * 10); 12 | } catch (InterruptedException e) { 13 | 14 | } 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/src/com/sync/process/Redis.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import com.alibaba.otter.canal.client.CanalConnector; 8 | import com.alibaba.otter.canal.client.CanalConnectors; 9 | import com.alibaba.otter.canal.protocol.Message; 10 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 11 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 12 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 13 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 14 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 15 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 16 | import com.sync.common.GetProperties; 17 | import com.sync.common.RedisApi; 18 | import com.sync.common.Tool; 19 | import com.sync.common.WriteLog; 20 | import com.alibaba.fastjson.JSON; 21 | 22 | /** 23 | * Redis Producer 24 | * 25 | * @author sasou web:http://www.php-gene.com/ 26 | * @version 1.0.0 27 | */ 28 | public class Redis implements Runnable { 29 | private RedisApi RedisPool = null; 30 | private CanalConnector connector = null; 31 | private String thread_name = null; 32 | private String canal_destination = null; 33 | 34 | public Redis(String name) { 35 | thread_name = "canal[" + name + "]:"; 36 | canal_destination = name; 37 | } 38 | 39 | public void process() { 40 | int batchSize = 1000; 41 | connector = CanalConnectors.newSingleConnector( 42 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 43 | GetProperties.canal.username, GetProperties.canal.password); 44 | 45 | connector.connect(); 46 | connector.subscribe(); 47 | 48 | try { 49 | RedisPool = new RedisApi(canal_destination); 50 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 51 | while (true) { 52 | Message message = connector.getWithoutAck(batchSize); // get batch num 53 | long batchId = message.getId(); 54 | int size = message.getEntries().size(); 55 | if (!(batchId == -1 || size == 0)) { 56 | if (syncEntry(message.getEntries())) { 57 | connector.ack(batchId); // commit 58 | } else { 59 | connector.rollback(batchId); // rollback 60 | } 61 | } 62 | } 63 | } catch (Exception e) { 64 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 65 | } 66 | } 67 | 68 | public void run() { 69 | while (true) { 70 | try { 71 | process(); 72 | } catch (Exception e) { 73 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 74 | } finally { 75 | if (connector != null) { 76 | connector.disconnect(); 77 | connector = null; 78 | } 79 | } 80 | } 81 | } 82 | 83 | private boolean syncEntry(List entrys) { 84 | String topic = ""; 85 | int no = 0; 86 | boolean ret = true; 87 | for (Entry entry : entrys) { 88 | EntryType type = entry.getEntryType(); 89 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 90 | continue; 91 | } 92 | String db = entry.getHeader().getSchemaName(); 93 | String table = entry.getHeader().getTableName(); 94 | if (!Tool.checkFilter(canal_destination, db, table)) { 95 | continue; 96 | } 97 | RowChange rowChage = null; 98 | try { 99 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 100 | } catch (Exception e) { 101 | throw new RuntimeException( 102 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 103 | } 104 | 105 | EventType eventType = rowChage.getEventType(); 106 | Map data = new HashMap(); 107 | Map head = new HashMap(); 108 | head.put("binlog_file", entry.getHeader().getLogfileName()); 109 | head.put("binlog_pos", entry.getHeader().getLogfileOffset()); 110 | head.put("db", db); 111 | head.put("table", table); 112 | head.put("type", eventType); 113 | data.put("head", head); 114 | topic = Tool.makeTargetName(canal_destination, db, table); 115 | no = (int) entry.getHeader().getLogfileOffset(); 116 | for (RowData rowData : rowChage.getRowDatasList()) { 117 | if (eventType == EventType.DELETE) { 118 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 119 | } else if (eventType == EventType.INSERT) { 120 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 121 | } else { 122 | data.put("before", makeColumn(rowData.getBeforeColumnsList())); 123 | data.put("after", makeColumn(rowData.getAfterColumnsList())); 124 | } 125 | String text = JSON.toJSONString(data); 126 | try { 127 | RedisPool.rpush(topic, text); 128 | if (GetProperties.system_debug > 0) { 129 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + topic + "," + no + ", " + text + ")"); 130 | } 131 | } catch (Exception e) { 132 | WriteLog.write(canal_destination + ".error", thread_name + "redis link failure!" + WriteLog.eString(e)); 133 | ret = false; 134 | } 135 | } 136 | data.clear(); 137 | data = null; 138 | } 139 | return ret; 140 | } 141 | 142 | private Map makeColumn(List columns) { 143 | Map one = new HashMap(); 144 | for (Column column : columns) { 145 | one.put(column.getName(), column.getValue()); 146 | } 147 | return one; 148 | } 149 | 150 | protected void finalize() throws Throwable { 151 | if (connector != null) { 152 | connector.disconnect(); 153 | connector = null; 154 | } 155 | } 156 | 157 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/Ssdb.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import com.alibaba.otter.canal.client.CanalConnector; 8 | import com.alibaba.otter.canal.client.CanalConnectors; 9 | import com.alibaba.otter.canal.protocol.Message; 10 | import com.alibaba.otter.canal.protocol.CanalEntry.Column; 11 | import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 12 | import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 13 | import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 14 | import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 15 | import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 16 | import com.sync.common.GetProperties; 17 | import com.sync.common.SsdbApi; 18 | import com.sync.common.Tool; 19 | import com.sync.common.WriteLog; 20 | import com.alibaba.fastjson.JSON; 21 | 22 | /** 23 | * Ssdb Producer 24 | * 25 | * @author sasou web:http://www.php-gene.com/ 26 | * @version 1.0.0 27 | */ 28 | public class Ssdb implements Runnable { 29 | private SsdbApi ssdb = null; 30 | private CanalConnector connector = null; 31 | private String thread_name = null; 32 | private String canal_destination = null; 33 | 34 | public Ssdb(String name) { 35 | thread_name = "canal[" + name + "]:"; 36 | canal_destination = name; 37 | } 38 | 39 | public void process() { 40 | int batchSize = 1000; 41 | connector = CanalConnectors.newSingleConnector( 42 | new InetSocketAddress(GetProperties.canal.ip, GetProperties.canal.port), canal_destination, 43 | GetProperties.canal.username, GetProperties.canal.password); 44 | 45 | connector.connect(); 46 | connector.subscribe(); 47 | 48 | try { 49 | ssdb = new SsdbApi(canal_destination); 50 | WriteLog.write(canal_destination, thread_name + "Start-up success!"); 51 | while (true) { 52 | Message message = connector.getWithoutAck(batchSize); // get batch num 53 | long batchId = message.getId(); 54 | int size = message.getEntries().size(); 55 | if (!(batchId == -1 || size == 0)) { 56 | if (syncEntry(message.getEntries())) { 57 | connector.ack(batchId); // commit 58 | } else { 59 | connector.rollback(batchId); // rollback 60 | } 61 | } 62 | } 63 | } catch (Exception e) { 64 | WriteLog.write(canal_destination, thread_name + WriteLog.eString(e)); 65 | } 66 | } 67 | 68 | public void run() { 69 | while (true) { 70 | try { 71 | process(); 72 | } catch (Exception e) { 73 | WriteLog.write(canal_destination, thread_name + "canal link failure!"); 74 | } finally { 75 | if (connector != null) { 76 | connector.disconnect(); 77 | connector = null; 78 | } 79 | } 80 | } 81 | } 82 | 83 | private boolean syncEntry(List entrys) { 84 | String topic = ""; 85 | int no = 0; 86 | boolean ret = true; 87 | for (Entry entry : entrys) { 88 | EntryType type = entry.getEntryType(); 89 | if (type == EntryType.TRANSACTIONBEGIN || type== EntryType.TRANSACTIONEND) { 90 | continue; 91 | } 92 | String db = entry.getHeader().getSchemaName(); 93 | String table = entry.getHeader().getTableName(); 94 | String path = db + "." + table; 95 | if (".".equals(path)) { 96 | continue; 97 | } 98 | if (!Tool.checkFilter(canal_destination, db, table)) { 99 | continue; 100 | } 101 | RowChange rowChage = null; 102 | try { 103 | rowChage = RowChange.parseFrom(entry.getStoreValue()); 104 | } catch (Exception e) { 105 | throw new RuntimeException( 106 | thread_name + "parser of eromanga-event has an error , data:" + entry.toString(), e); 107 | } 108 | 109 | EventType eventType = rowChage.getEventType(); 110 | Map data = new HashMap(); 111 | Map head = new HashMap(); 112 | head.put("binlog_file", entry.getHeader().getLogfileName()); 113 | head.put("binlog_pos", entry.getHeader().getLogfileOffset()); 114 | head.put("db", db); 115 | head.put("table", table); 116 | head.put("type", eventType); 117 | data.put("head", head); 118 | topic = Tool.makeTargetName(canal_destination, db, table); 119 | no = (int) entry.getHeader().getLogfileOffset(); 120 | for (RowData rowData : rowChage.getRowDatasList()) { 121 | if (eventType == EventType.DELETE) { 122 | data.put("before", makeColumn(rowData.getBeforeColumnsList(), path)); 123 | } else if (eventType == EventType.INSERT) { 124 | data.put("after", makeColumn(rowData.getAfterColumnsList(), path)); 125 | } else { 126 | data.put("before", makeColumn(rowData.getBeforeColumnsList(), path)); 127 | data.put("after", makeColumn(rowData.getAfterColumnsList(), path)); 128 | } 129 | String text = JSON.toJSONString(data); 130 | try { 131 | ssdb.rpush(topic, text); 132 | if (GetProperties.system_debug > 0) { 133 | WriteLog.write(canal_destination + ".access", thread_name + "data(" + topic + "," + no + ", " + text + ")"); 134 | } 135 | } catch (Exception e) { 136 | WriteLog.write(canal_destination + ".error", thread_name + "ssdb link failure!" + WriteLog.eString(e)); 137 | ret = false; 138 | } 139 | } 140 | data.clear(); 141 | data = null; 142 | } 143 | return ret; 144 | } 145 | 146 | private Map makeColumn(List columns, String table) { 147 | Map one = new HashMap(); 148 | @SuppressWarnings("rawtypes") 149 | Map field = (Map) GetProperties.target.get(canal_destination).filterMap.get(table); 150 | for (Column column : columns) { 151 | if (column.getIsKey()) { 152 | one.put(column.getName(), column.getValue()); 153 | } else { 154 | if (field != null && field.containsKey(column.getName())) { 155 | one.put(column.getName(), column.getValue()); 156 | } 157 | } 158 | } 159 | return one; 160 | } 161 | 162 | protected void finalize() throws Throwable { 163 | if (connector != null) { 164 | connector.disconnect(); 165 | connector = null; 166 | } 167 | } 168 | 169 | } -------------------------------------------------------------------------------- /src/src/com/sync/process/task.java: -------------------------------------------------------------------------------- 1 | package com.sync.process; 2 | 3 | import com.sync.common.GetProperties; 4 | 5 | /** 6 | * config file read 7 | * 8 | * @author sasou web:http://www.php-gene.com/ 9 | * @version 1.0.0 10 | */ 11 | public final class task { 12 | 13 | public static void main(String[] args) { 14 | // init 15 | GetProperties.update(); 16 | if (GetProperties.canal.destination == null) { 17 | System.out.println("error:canal destination is null!"); 18 | return; 19 | } 20 | int num = GetProperties.canal.destination.length; 21 | if (num > 0) { 22 | for (int i = 0; i < num; i++) { 23 | if (!"".equals(GetProperties.canal.destination[i])) { 24 | String type = GetProperties.target.get(GetProperties.canal.destination[i]).type; 25 | switch (type) { 26 | case "kafka": 27 | new Thread(new Kafka(GetProperties.canal.destination[i])).start(); 28 | break; 29 | case "redis": 30 | new Thread(new Redis(GetProperties.canal.destination[i])).start(); 31 | break; 32 | case "elasticsearch": 33 | new Thread(new ElasticSearch(GetProperties.canal.destination[i])).start(); 34 | break; 35 | case "httpmq": 36 | new Thread(new Httpmq(GetProperties.canal.destination[i])).start(); 37 | break; 38 | case "cache": 39 | new Thread(new Cache(GetProperties.canal.destination[i])).start(); 40 | break; 41 | case "ssdb": 42 | new Thread(new Ssdb(GetProperties.canal.destination[i])).start(); 43 | break; 44 | default: 45 | System.out.println("error:not support type!"); 46 | break; 47 | } 48 | } 49 | } 50 | } 51 | new Thread(new Prop()).start(); 52 | } 53 | 54 | } 55 | --------------------------------------------------------------------------------