溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

數(shù)據(jù)庫結(jié)構(gòu)同步ElasticSearch索引對象

發(fā)布時(shí)間:2021-06-22 16:30:41 來源:億速云 閱讀:143 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“數(shù)據(jù)庫結(jié)構(gòu)同步ElasticSearch索引對象”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

起因

由于業(yè)務(wù)的特點(diǎn)有時(shí)候數(shù)據(jù)會(huì)需要復(fù)雜的查詢邏輯才能得到,由于數(shù)據(jù)庫本身對于復(fù)雜查詢的支持不足,那么把數(shù)據(jù)同步到能力中間件就成了常用的解決方案,而同步到Elasticsearch就是其中一種。

方案選型

我們使用的數(shù)據(jù)源是MySql,選擇同步到ES,想法是通過訂閱Binlog實(shí)現(xiàn),減少侵入性。 解決方案其實(shí)也有一些,比如:go-mysql-elasticsearch、canal、gravity

然而這些方案通常只支持1對1建索引,也就是一張表一個(gè)索引,而數(shù)據(jù)表中的1對1和1對多關(guān)系則無法在索引中體體現(xiàn)。而業(yè)務(wù)中又常需要這種關(guān)系。因此綜合考慮還是基于gravity做個(gè)插件。

gravity是摩拜開源的數(shù)據(jù)同步中間件,目前數(shù)據(jù)源支持:MySql和Mongo,TiDB和PostgreSQL在開發(fā)中,同步目標(biāo)支持:MySQL/TiDB和Kafka,Elasticsearch還在bate階段,并且支持6.

EsModel同步插件

項(xiàng)目地址:gravity 歡迎star :)。

同步策略

  • 支持主表及一對一和一對多字表的同步,可以同步到一個(gè)索引結(jié)構(gòu)中。

  • 一對一關(guān)系支持以平鋪或子對象形式同步。

  • 支持ES版本:6、7

例如有四張表:studentstudent_class、student_detailstudent_parent 其中student是學(xué)生表(主表),student_class學(xué)生班級(一對一子表),student_detail學(xué)生詳情(一對一子表),student_parent學(xué)生父母(一對多子表)。student_class使用子對象形式同步,student_detail使用平鋪形式同步。

Sql腳本如下:

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` bigint(20) NOT NULL,
  `name` varchar(64) NOT NULL DEFAULT '',
  `birthday` date NOT NULL DEFAULT '1970-01-01',
  `high` int(11) NOT NULL DEFAULT '0',
  `sex` tinyint(4) NOT NULL DEFAULT '1',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES (1, '張三', '2010-02-05', 156, 1, '2019-08-29 19:55:36');
INSERT INTO `student` VALUES (2, '李四', '2010-03-05', 176, 2, '2019-08-29 19:55:36');
INSERT INTO `student` VALUES (3, '王平', '2010-03-05', 176, 2, '2019-08-29 20:09:03');
COMMIT;

-- ----------------------------
-- Table structure for student_class
-- ----------------------------
DROP TABLE IF EXISTS `student_class`;
CREATE TABLE `student_class` (
  `id` bigint(20) NOT NULL,
  `student_id` bigint(20) NOT NULL DEFAULT '0',
  `name` varchar(255) NOT NULL DEFAULT '',
  `student_count` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student_class
-- ----------------------------
BEGIN;
INSERT INTO `student_class` VALUES (1, 1, '一(1)班', 32);
INSERT INTO `student_class` VALUES (2, 2, '二(2)班', 12);
COMMIT;

-- ----------------------------
-- Table structure for student_detail
-- ----------------------------
DROP TABLE IF EXISTS `student_detail`;
CREATE TABLE `student_detail` (
  `id` bigint(20) NOT NULL,
  `student_id` bigint(20) NOT NULL DEFAULT '0',
  `introduce` varchar(255) NOT NULL DEFAULT '',
  `mobile` varchar(64) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student_detail
-- ----------------------------
BEGIN;
INSERT INTO `student_detail` VALUES (1, 1, '張三介紹', '18888888888');
INSERT INTO `student_detail` VALUES (2, 2, '李四介紹', '13333333333');
COMMIT;

-- ----------------------------
-- Table structure for student_parent
-- ----------------------------
DROP TABLE IF EXISTS `student_parent`;
CREATE TABLE `student_parent` (
  `id` bigint(20) NOT NULL,
  `student_id` bigint(20) NOT NULL DEFAULT '0',
  `name` varchar(255) NOT NULL DEFAULT '',
  `birthday` date NOT NULL DEFAULT '1970-01-01',
  `sex` tinyint(11) NOT NULL DEFAULT '1',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student_parent
-- ----------------------------
BEGIN;
INSERT INTO `student_parent` VALUES (1, 1, '張三父親', '1980-02-02', 1, '2019-08-29 20:00:58');
INSERT INTO `student_parent` VALUES (2, 1, '張三母親', '1982-07-07', 2, '2019-08-29 20:00:58');
INSERT INTO `student_parent` VALUES (3, 2, '李四父親', '1979-03-03', 1, '2019-08-29 20:00:58');
INSERT INTO `student_parent` VALUES (4, 2, '李四母親', '1981-06-06', 2, '2019-08-29 20:00:58');
COMMIT;

同步配置如下:

# name 必填
name = "mysql2esmodelDemo"

# 內(nèi)部用于保存位點(diǎn)、心跳等事項(xiàng)的庫名,默認(rèn)為 _gravity
internal-db-name = "_gravity"

#
# Input 插件的定義,此處定義使用 mysql
#
[input]
type = "mysql"
mode = "replication"
[input.config.source]
host = "192.168.1.148"
username = "root"
password = "mysqldev"
port = 3306
max-idle = 10
max-open = 10


[output]
type = "esmodel"

[output.config]
# 忽略 400(bad request)返回
# 當(dāng)索引名不規(guī)范、解析錯(cuò)誤時(shí),Elasticsearch 會(huì)返回 400 錯(cuò)誤
# 默認(rèn)為 false,即遇到失敗時(shí)會(huì)拋出異常,必須人工處理。設(shè)置為 true 時(shí)會(huì)忽略這些請求
ignore-bad-request = true

#
# 目標(biāo)端 Elasticsearch 配置
# - 必選
#
[output.config.server]
# 連接的 Elasticsearch 地址,必選
urls = ["http://192.168.1.152:9200"]
# 是否進(jìn)行節(jié)點(diǎn)嗅探,默認(rèn)為 false
sniff = false
# 超時(shí)時(shí)間,默認(rèn)為 1000ms
timeout = 500

#
# 目標(biāo)端鑒權(quán)配置
# - 可選
#
[output.config.server.auth]
username = ""
password = ""


[[output.config.routes]]
match-schema = "test"
# 主表
match-table = "student"
#索引名
index-name="student_index"
#類型名,es7該項(xiàng)無效
type-name="student"
#分片數(shù)
shards-num=1
#副本數(shù)
replicas-num=0
#失敗重試次數(shù)
retry-count=3
#包含的列,默認(rèn)全部
include-column = []
#排除的列,默認(rèn)沒有
exclude-column = []

# 列名轉(zhuǎn)義策略
[output.config.routes.convert-column]
name = "studentName"


[[output.config.routes.one-one]]
match-schema = "test"
match-table = "student_detail"
#外鍵列
fk-column = "student_id"
#包含的列,默認(rèn)全部
include-column = []
#排除的列,默認(rèn)沒有
exclude-column = []
# 模式,1:子對象,2索引平鋪
mode = 2
# 屬性對象名,模式為1時(shí)有效,默認(rèn)為源表名駝峰結(jié)構(gòu)
property-name = "studentDetail"
# 屬性前綴,模式為2時(shí)有效,默認(rèn)為源表名駝峰結(jié)構(gòu)
property-pre = "sd_"

[output.config.routes.one-one.convert-column]
introduce = "introduceInfo"

[[output.config.routes.one-one]]
match-schema = "test"
match-table = "student_class"
#外鍵列
fk-column = "student_id"
#包含的列,默認(rèn)全部
include-column = []
#排除的列,默認(rèn)沒有
exclude-column = []
# 模式,1:子對象,2索引平鋪
mode = 1
# 屬性對象名,模式為1時(shí)有效,默認(rèn)為源表名駝峰結(jié)構(gòu)
property-name = "studentClass"
# 屬性前綴,模式為2時(shí)有效,默認(rèn)為源表名駝峰結(jié)構(gòu)
property-pre = "sc_"

[output.config.routes.one-one.convert-column]
name = "className"

[[output.config.routes.one-more]]
match-schema = "test"
match-table = "student_parent"
#外鍵列
fk-column = "student_id"
#包含的列,默認(rèn)全部
include-column = []
#排除的列,默認(rèn)沒有
exclude-column = []
# 屬性對象名,默認(rèn)為源表名駝峰結(jié)構(gòu)
property-name = "studentParent"

[output.config.routes.one-more.convert-column]
name = "parentName"

到項(xiàng)目根目錄make編譯,執(zhí)行同步命令

./bin/gravity -config  ./docs/2.0/example-mysql2esmodel.toml

同步后索引結(jié)構(gòu)為:

{
    "state": "open",
    "settings": {
        "index": {
            "creation_date": "1567160065596",
            "number_of_shards": "1",
            "number_of_replicas": "0",
            "uuid": "noe_V-RdTr6QaFDy4fPRjA",
            "version": {
                "created": "7030199"
            },
            "provided_name": "student_index"
        }
    },
    "mappings": {
        "_doc": {
            "properties": {
                "birthday": {
                    "type": "date"
                },
                "studentParent": {
                    "type": "nested",
                    "properties": {
                        "birthday": {
                            "type": "date"
                        },
                        "parentName": {
                            "type": "text",
                            "fields": {
                                "keyword": {
                                    "ignore_above": 256,
                                    "type": "keyword"
                                }
                            }
                        },
                        "create_time": {
                            "type": "date"
                        },
                        "sex": {
                            "type": "long"
                        },
                        "student_id": {
                            "type": "long"
                        },
                        "id": {
                            "type": "long"
                        }
                    }
                },
                "high": {
                    "type": "long"
                },
                "create_time": {
                    "type": "date"
                },
                "sex": {
                    "type": "long"
                },
                "studentName": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "ignore_above": 256,
                            "type": "keyword"
                        }
                    }
                },
                "sd_student_id": {
                    "type": "long"
                },
                "introduceInfo": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "ignore_above": 256,
                            "type": "keyword"
                        }
                    }
                },
                "sd_id": {
                    "type": "long"
                },
                "id": {
                    "type": "long"
                },
                "sd_mobile": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "ignore_above": 256,
                            "type": "keyword"
                        }
                    }
                },
                "studentClass": {
                    "properties": {
                        "sc_id": {
                            "type": "long"
                        },
                        "className": {
                            "type": "text",
                            "fields": {
                                "keyword": {
                                    "ignore_above": 256,
                                    "type": "keyword"
                                }
                            }
                        },
                        "sc_student_count": {
                            "type": "long"
                        },
                        "sc_student_id": {
                            "type": "long"
                        }
                    }
                }
            }
        }
    }
}

數(shù)據(jù)樣例為:

{
    "_index": "student_index",
    "_type": "_doc",
    "_id": "2",
    "_version": 5,
    "_score": 1,
    "_source": {
        "studentClass": {
            "className": "二(2)班",
            "sc_id": 2,
            "sc_student_count": 12,
            "sc_student_id": 2
        },
        "sd_student_id": 2,
        "introduceInfo": "李四介紹",
        "sd_id": 2,
        "sd_mobile": "13333333333",
        "studentParent": [
            {
                "birthday": "1981-06-06T00:00:00+08:00",
                "parentName": "李四母親",
                "create_time": "2019-08-29T20:00:58+08:00",
                "sex": 2,
                "student_id": 2,
                "id": 4
            },
            {
                "birthday": "1979-03-03T00:00:00+08:00",
                "parentName": "李四父親",
                "create_time": "2019-08-29T20:00:58+08:00",
                "sex": 1,
                "student_id": 2,
                "id": 3
            }
        ],
        "birthday": "2010-03-05T00:00:00+08:00",
        "high": 176,
        "create_time": "2019-08-29T19:55:36+08:00",
        "sex": 2,
        "studentName": "李四",
        "id": 2
    }
}

“數(shù)據(jù)庫結(jié)構(gòu)同步ElasticSearch索引對象”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI