前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高并发情况下使用动态多数据源dynamic-datasource 3.1.0并发问题复盘

高并发情况下使用动态多数据源dynamic-datasource 3.1.0并发问题复盘

原创
作者头像
zhaozhen
修改2023-02-18 23:47:24
1.5K0
修改2023-02-18 23:47:24
举报
文章被收录于专栏:微瞰Java后端开发

最近公司内某个项目出现了因并发问题导致的多数据源串掉的问题,经研究找到了如下解决方案

复现流程

image.png
image.png

A线程切换指定数据源并挂起

image.png
image.png

B线程使用了默认数据源,A线程先于B线程,结果B线程使用了从库数据源(health_bi)

问题原因

image.png
image.png

DynamicDataSourceContextHolder中NamedInheritableThreadLocal导致两个数据源共用同一数据源队列Deque<String> 且NamedInheritableThreadLocal会出现将此子线程的值复制到主线程中

InheritableThreadLocal的类注释

This class extends ThreadLocal to provide inheritance of values from parent thread to child thread: when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values. Normally the child's values will be identical to the parent's; however, the child's value can be made an arbitrary function of the parent's by overriding the childValue method in this class.

Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.

经翻译为

此类扩展ThreadLocal以提供从父线程到子线程的值继承:当创建子线程时,子线程接收父线程具有值的所有可继承线程本地变量的初始值。通常情况下,孩子的值与父母的值相同;但是,通过重写该类中的childValue方法,可以使子级的值成为父级的任意函数。

当变量中维护的每线程属性(例如,用户ID、事务ID)必须自动传输到创建的任何子线程时,可继承线程本地变量优先于普通线程本地变量。

image.png
image.png

子线程创建的时候会获取所有父线程的值。而子线程的值又会传递给父线程,所以就相当于所有子线程的值是共享的,这个问题才会出现。而跟代码的时候你会发现其实所有线程的ArrayDeque都是指向同一个地址

当用new Thread()创建线程时,会走下面的代码,那么inheritThreadLocals就会是true

代码语言:txt
复制
private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize) {
    init(g, target, name, stackSize, null, true);
}

解决方案

升级dynamic-datasource最新版本,使用NamedThreadLocal,NamedThreadLocal并无其他操作仅仅是命名

参考资料

踩坑dynamic-datasource-spring-boot-starter v3.1.0 自动切换数据源失败

dynamic-datasource-spring-boot-starter v3.1.0 自动切换数据源失败源码分析

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 复现流程
  • 问题原因
  • 解决方案
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档