Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

建议更正一下数据同步ES的Wiki #2160

Closed
yangyiweigege opened this issue Sep 6, 2019 · 7 comments
Closed

建议更正一下数据同步ES的Wiki #2160

yangyiweigege opened this issue Sep 6, 2019 · 7 comments

Comments

@yangyiweigege
Copy link

yangyiweigege commented Sep 6, 2019

先附官网数据同步ES的地址:
https://github.com/alibaba/canal/wiki/Sync-ES
实际上 配置es的时候 遗漏了 key的属性, 应该在ES的文档声明中 加上这个

标准姿势应该如下:

application.yml配置

  • name: es
    key: exampleKey #配置es数据源的key 必须唯一 (这个属性超级无敌重要)
    hosts: 127.0.0.1:9300 # es 集群地址, 逗号分隔
    properties:
    cluster.name: elasticsearch # es cluster name

适配器映射配置:
dataSourceKey: defaultDS # 源数据源的key, 对应上面配置的srcDataSources中的值
destination: example # cannal的instance或者MQ的topic
outerAdapterKey: exampleKey #对应上文中的key 这个key很重要 再强调一次
groupId: # 对应MQ模式下的groupId, 只会同步对应groupId的数据

如果按照官网现在给的那个例子,有概率出现以下问题:
由于es没有配置key 会导致多个 instance 共享 一个 EsAdapater,且EsAdapter 会间接关联到一个非线程安全的final List requests = new ArrayList<>()
1.在多个instance同时写入es的时候 有可能会数据丢失(requests.add操作) 【我自己遇到过,而且极难排查】
2.抛出java.lang.RuntimeException: java.lang.RuntimeException: java.util.ConcurrentModificationException 这是因为 当其中某个 instance在提交的时候 会进行for循环 遍历requests 假如恰好另外一个instance中间 进行了 add操作 就会触发。【有人遇到过这个问题】

顺便附一段 初始化 EsAdapter的代码:
public T getExtension(String name, String key) {
if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
String extKey = name + "-" + StringUtils.trimToEmpty(key);
Holder holder = cachedInstances.get(extKey);
if (holder == null) {
cachedInstances.putIfAbsent(extKey, new Holder<>());
holder = cachedInstances.get(extKey);
}
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createExtension(name, key);
holder.set(instance);
}
}
}
return (T) instance;
}

从这段代码可以看出 不配置key 引用指向的都是同一个EsAdapter.

@xmuyoucai
Copy link

看你研究得比较深,目前投产了吗,有没有发现其它问题?

@yangyiweigege
Copy link
Author

看你研究得比较深,目前投产了吗,有没有发现其它问题?
已经投产了。问题的话。就这个我觉得比较严肃 看issue里 有好多人出现这个问题。。。别的暂时没发现。后续还会持续关注这项目的。

@xmuyoucai
Copy link

看你研究得比较深,目前投产了吗,有没有发现其它问题?
已经投产了。问题的话。就这个我觉得比较严肃 看issue里 有好多人出现这个问题。。。别的暂时没发现。后续还会持续关注这项目的。

OK,感谢!

我还发现一个比较重要的问题,不知道你有没有发现,还是提醒一下:

#2023

这是我提的一个 issue,你那边也注意一下

@rewerma
Copy link
Collaborator

rewerma commented Sep 12, 2019

tks

@rewerma rewerma closed this as completed Sep 12, 2019
@MistRay
Copy link

MistRay commented Sep 17, 2020

感谢~

@czxyzqs
Copy link

czxyzqs commented Nov 24, 2022

这个错误在1.1.6中已经修复,可以参考1.1.6更新的内容,对没有配置key的OuterAdapter,会根据destination+groupId+序号生成一个key,保证这些OuterAdapter不共享
,在1.1.5版本中,可以通过设置key来解决,涉及两个地方,一个是application.yml中增加key,还有个conf/es目录下的配置文件中增加outerAdapterKey,使用的Adapter标识,必须与application.yml中canal.conf: canalAdapters: groups: outerAdapters下key值相同。

@yangyiweigege
Copy link
Author

这个错误在1.1.6中已经修复,可以参考1.1.6更新的内容,对没有配置key的OuterAdapter,会根据destination+groupId+序号生成一个key,保证这些OuterAdapter不共享 ,在1.1.5版本中,可以通过设置key来解决,涉及两个地方,一个是application.yml中增加key,还有个conf/es目录下的配置文件中增加outerAdapterKey,使用的Adapter标识,必须与application.yml中canal.conf: canalAdapters: groups: outerAdapters下key值相同。

👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants