2024年12月

序言:重新训练人工智能大型模型是一项复杂且高成本的任务,尤其对于当前的LLM(大型语言模型)来说,全球99.99%的企业难以承担。这是因为模型训练需要巨大的资源投入、复杂的技术流程以及大量的人力支持。因此,无论在科学研究还是实际应用中,人们通常依赖开源的预训练模型及其已经学习到的各种特征信息,就像使用开源的Linux一样。本节将讲解如何利用这些预训练模型中的“嵌入”信息来解决实际问题。

使用预训练嵌入与RNN

在之前的所有示例中,我们收集了训练集中要使用的完整单词集,然后用它们训练了嵌入。这些嵌入最初是聚合在一起的,然后输入到密集网络中,而在最近的章节中,我们探讨了如何使用RNN来改进结果。在此过程中,我们被限制在数据集中已经存在的单词,以及如何使用该数据集中的标签来学习它们的嵌入。回想一下在前面有一章,我们讨论了迁移学习。如果,您可以不自己学习嵌入,而是使用已经预先学习的嵌入,研究人员已经完成了将单词转化为向量的艰苦工作,并且这些向量是经过验证的呢?其中一个例子是Stanford大学的Jeffrey Pennington、Richard Socher和Christopher Manning开发的GloVe(Global Vectors for Word Representation)模型。

在这种情况下,研究人员分享了他们为各种数据集预训练的单词向量:

• 一个包含60亿个标记、40万个单词的词汇集,维度有50、100、200和300,单词来自维基百科和Gigaword

• 一个包含420亿个标记、190万个单词的词汇集,维度为300,来自通用爬虫

• 一个包含8400亿个标记、220万个单词的词汇集,维度为300,来自通用爬虫

• 一个包含270亿个标记、120万个单词的词汇集,维度为25、50、100和200,来自对20亿条推文的Twitter爬虫

考虑到这些向量已经预训练,我们可以轻松地在TensorFlow代码中重复使用它们,而不必从头开始学习。首先,我们需要下载GloVe数据。这里选择使用Twitter数据集,包含270亿个标记和120万个单词的词汇集。下载的是一个包含25、50、100和200维度的归档文件。

为了让整个过程稍微方便一些,我已经托管了25维版本,您可以像这样将其下载到Colab笔记本中:

!wget --no-check-certificate \

https://storage.googleapis.com/laurencemoroney-blog.appspot.com/glove.twitter.27B.25d.zip
\

-O /tmp/glove.zip

这是一个ZIP文件,您可以像这样解压缩,得到一个名为glove.twitter.27B.25d.txt的文件:

解压GloVe嵌入

import os

import zipfile

local_zip = '/tmp/glove.zip'

zip_ref = zipfile.ZipFile(local_zip, 'r')

zip_ref.extractall('/tmp/glove')

zip_ref.close()

文件中的每一行都是一个单词,后面跟着为其学习到的维度系数。最简单的使用方式是创建一个字典,其中键是单词,值是嵌入。您可以这样设置这个字典:

glove_embeddings = dict()

f = open('/tmp/glove/glove.twitter.27B.25d.txt')

for line in f:

values = line.split()

word = values[0]

coefs = np.asarray(values[1:], dtype='float32')

glove_embeddings[word] = coefs

f.close()

此时,您可以简单地通过使用单词作为键来查找任何单词的系数集。例如,要查看“frog”的嵌入,您可以使用:

glove_embeddings['frog']

有了这个资源,您可以像以前一样使用分词器获取语料库的单词索引——但现在,您可以创建一个新的矩阵,我称之为嵌入矩阵。这个矩阵将使用GloVe集中的嵌入(从glove_embeddings获取)作为其值。因此,如果您检查数据集中单词索引中的单词,如下所示:

{'
': 1, 'new': 2, … 'not': 5, 'just': 6, 'will': 7}

那么嵌入矩阵的第一行应该是GloVe中“
”的系数,接下来的行是“new”的系数,依此类推。

您可以使用以下代码创建该矩阵:

embedding_matrix = np.zeros((vocab_size, embedding_dim))

for word, index in tokenizer.word_index.items():

if index > vocab_size - 1:

break

else:

embedding_vector = glove_embeddings.get(word)

if embedding_vector is not None:

embedding_matrix[index] = embedding_vector

这只是创建了一个矩阵,矩阵的维度是您所需的词汇大小和嵌入维度。然后,对于分词器的每个词汇索引项,您会查找GloVe中的系数(从glove_embeddings中获取),并将这些值添加到矩阵中。

接着,您需要修改嵌入层,使用预训练的嵌入,通过设置weights参数,并指定不希望该层被训练,通过设置trainable=False:

model = tf.keras.Sequential([

tf.keras.layers.Embedding(vocab_size, embedding_dim,

weights=[embedding_matrix], trainable=False),

tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim, return_sequences=True)),

tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim)),

tf.keras.layers.Dense(24, activation='relu'),

tf.keras.layers.Dense(1, activation='sigmoid')

])

现在,您可以像之前一样进行训练。然而,您需要考虑您的词汇大小。在上一章中,您为了避免过拟合,做了一些优化,目的是防止嵌入过多地学习低频单词;您通过使用更小的词汇表、仅包含常用单词来避免过拟合。在这种情况下,由于单词嵌入已经通过GloVe为您学习过,您可以扩展词汇表——但扩展多少呢?

首先要探索的是,您的语料库中有多少单词实际上在GloVe集中。GloVe有120万个单词,但不能保证它包含您的所有单词。所以,这里有一些代码,可以快速对比,让您探索您的词汇表应该多大。

首先,整理数据。创建一个包含Xs和Ys的列表,其中X是词汇索引,Y=1表示该单词在嵌入中,0则表示不在。此外,您可以创建一个累计集,在每个时间步计算单词的比例。例如,索引为0的单词“OOV”不在GloVe中,所以它的累计Y值为0。下一个索引的单词“new”在GloVe中,所以它的累计Y值为0.5(即,到目前为止看到的单词中有一半在GloVe中),然后您会继续这样计算整个数据集:

xs = []

ys = []

cumulative_x = []

cumulative_y = []

total_y = 0

for word, index in tokenizer.word_index.items():

xs.append(index)

cumulative_x.append(index)

if glove_embeddings.get(word) is not None:

total_y = total_y + 1

ys.append(1)

else:

ys.append(0)

cumulative_y.append(total_y / index)

然后,您可以使用以下代码绘制Xs与Ys的关系图:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 2))

ax.spines['top'].set_visible(False)

plt.margins(x=0, y=None, tight=True)

plt.axis([13000, 14000, 0, 1])

plt.fill(ys)

这将给您一个单词频率图,看起来像图7-17。

                                                      图7-17. 单词频率图

如图表所示,密度在10,000到15,000之间发生变化。这让您直观地看到,大约在13,000标记的位置,未在GloVe嵌入中的单词的频率开始超过那些已经在GloVe嵌入中的单词。

如果您再绘制累计的cumulative_x与cumulative_y的关系,您将能更好地理解这个变化。以下是代码:

import matplotlib.pyplot as plt

plt.plot(cumulative_x, cumulative_y)

plt.axis([0, 25000, .915, .985])

您可以看到图7-18中的结果。


图7-18. 绘制单词索引频率与GloVe的关系

现在,您可以调整plt.axis中的参数,放大查看拐点,看看未出现在GloVe中的单词是如何开始超过那些在GloVe中的单词的。这是设置词汇大小的一个不错起点。

使用这种方法,我选择了一个词汇大小为13,200(而不是之前为了避免过拟合而使用的2,000),并使用了以下模型架构,其中embedding_dim是25,因为我使用的是GloVe集:

model = tf.keras.Sequential([

tf.keras.layers.Embedding(vocab_size, embedding_dim,

weights=[embedding_matrix], trainable=False),

tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim, return_sequences=True)),

tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim)),

tf.keras.layers.Dense(24, activation='relu'),

tf.keras.layers.Dense(1, activation='sigmoid')

])

然后,使用Adam优化器:

adam = tf.keras.optimizers.Adam(learning_rate=0.00001, beta_1=0.9, beta_2=0.999, amsgrad=False)

model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])

训练30个epoch后,得到了很好的结果。准确率如图7-19所示。验证准确率与训练准确率非常接近,表明我们不再过拟合。


图7-19. 使用GloVe嵌入的堆叠LSTM准确率

这一点通过损失曲线得到进一步验证,如图7-20所示。验证损失不再发散,这表明尽管我们的准确率只有大约73%,我们可以有信心认为模型的准确性达到了这个程度。

                                                      图7-20. 使用GloVe嵌入的堆叠LSTM损失

训练模型更长时间会得到非常相似的结果,并且表明,尽管大约在第80个epoch左右开始出现过拟合,模型仍然非常稳定。

准确率指标(图7-21)显示模型训练得很好。

损失指标(图7-22)显示大约在第80个epoch左右开始出现发散,但模型仍然拟合得很好。


图7-21. 使用GloVe的堆叠LSTM在150个epoch上的准确率


图7-22. 使用GloVe的堆叠LSTM在150个epoch上的损失

这告诉我们,这个模型是早停的好候选者,您只需要训练它75到80个epoch,就能得到最佳结果。

我用来自《洋葱报》的标题(《洋葱报》是讽刺性标题的来源,也是讽刺数据集的来源),与其他句子进行了测试,测试代码如下:

test_sentences = [

"It Was, For, Uh, Medical Reasons, Says Doctor To Boris Johnson, Explaining Why They Had To Give Him Haircut",

"It's a beautiful sunny day",

"I lived in Ireland, so in high school they made me learn to speak and write in Gaelic",

"Census Foot Soldiers Swarm Neighborhoods, Kick Down Doors To Tally Household Sizes"

]

这些标题的结果如下——记住,接近50%(0.5)的值被认为是中立的,接近0的是非讽刺的,接近1的是讽刺的:

[[0.8170955 ]

[0.08711044]

[0.61809343]

[0.8015281 ]]

来自《洋葱报》的第一句和第四句显示了80%以上的讽刺概率。关于天气的陈述则显得非常非讽刺(9%),而关于在爱尔兰上高中这句话被认为可能是讽刺的,但信心不高(62%)。

总结

本节中我们介绍了循环(递归)神经网络(RNN),它们在设计中使用面向序列的逻辑,可以帮助您理解句子的情感,不仅基于其中的单词,还基于它们出现的顺序。了解了基本的RNN如何工作,以及LSTM如何在此基础上改进,保留长期上下文。您使用这些技术改进了您一直在做的情感分析模型。接着,您研究了RNN的过拟合问题以及改善它们的技术,包括使用从预训练嵌入中进行迁移学习。在接下来的章节中,我们将使用前面全部所学内容探索如何预测单词,进而创建一个能够生成文本的模型,甚至为您写诗!

升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件,宗旨是:
开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。

背景

我在业余时间开发的这个客服系统,有一个问题始终让我饱受困扰,360以及各种国产安全管家十分容易报威胁。即便ESET、卡巴斯基、Windows Defender、小红伞全部一切正常,但360、国产管家就是倔强的报威胁。而这些国产管家的用户基数又很大,非常让人恼火。难道真的必须交保护费吗?

经过长时间的尝试和测试,终于在一定程度上缓解了这个问题(还不敢保证不会再报,继续观察)。

对软件进行数字签名

如果软件被360和国产管家报威胁,可以为其进行数字签名,即使用代码签名证书,用户下载软件时,能通过数字签名验证软件来源,确认软件、代码没有被非法篡改或植入病毒,减少被误报的可能。

Signcode.exe

Signcode.exe 是微软提供的一款用于对代码和软件文件进行数字签名的工具:

  • 支持多种文件类型签名:能够对常见的可执行文件(如.exe、.dll、.ocx)、Cabinet 打包文件(.cab)以及目录文件(.cat)等进行数字签名,确保这些文件的完整性和来源可靠性,防止文件被篡改.
  • 增强软件安全性和可信度:通过数字签名,用户在下载和运行软件时,可以验证软件是否来自合法的开发者,以及软件在传输过程中是否被修改过,从而提高软件的安全性和可信度,减少用户对未知来源软件的担忧.
  • 提供时间戳服务:在签名过程中可添加时间戳,即使代码签名证书过期,只要软件是在证书有效期内签名的,时间戳服务仍能保证该软件的签名在一定时间内继续有效,用户依旧可以放心下载和使用,无需开发者重新对软件进行签名.

生成数字签名证书

生成证书:可以使用 New-SelfSignedCertificate 命令生成自签名证书,例如

New-SelfSignedCertificate -Type Custom -Subject "CN=YourCompanyName" -KeyUsage DigitalSignature -FriendlyName "YourFriendlyName" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") -NotAfter (Get-Date).AddYears(10)

其中CN为证书的主题名称,可根据实际情况修改,此命令会在当前用户的证书存储区生成一个自签名证书.

导出证书:使用 Export-PfxCertificate 命令将证书导出为pfx格式,如

Export-PfxCertificate -cert "Cert:\CurrentUser\My\YourCertificateThumbprint" -FilePath yourcertificate.pfx -Password (ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText)

注意将YourCertificateThumbprint替换为实际的证书指纹,YourPassword替换为设置的密码.

使用 Signtool 签名:找到Signtool.exe工具的路径,一般在 C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe,打开命令提示符,进入该目录,然后执行签名命令,如

C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /f yourcertificate.pfx /p YourPassword /t http://timestamp.digicert.com /v "YourSoftware.exe"

将yourcertificate.pfx、YourPassword和YourSoftware.exe分别替换为实际的证书文件、密码和要签名的软件文件名.

使用 Signcode.exe 工具

制作根证书:在命令提示符中输入

makecert -sv myroot.pvk -ss mysubjectname -n CN=mycompany -r myroot.cer

其中-sv指定私钥文件名,-ss指定主题的证书存储名称,-n指定证书颁发对象,-r指定证书存储位置,回车后设置密码并记住.

制作子证书:输入

makecert -sv test.pvk -iv myroot.pvk -n CN=mycompany -$ commercial -ic myroot.cer test.cer

同样设置并记住密码,此命令中的参数含义与制作根证书类似,只是多了-iv指定根证书的私钥文件和-$指定授权范围.

生成 spc 发行者证书:可选操作,输入

cert2spc test.cer test.spc

可在相应目录下生成test.spc文件.

使用 Signcode 签名:运行 signcode.exe,按照向导依次选择需要签名的文件、证书类型为 “自定义”,然后从文件中选择子证书和私钥文件,并输入相应密码,还可根据需要设置哈希算法、其他证书、数据描述以及时间戳等选项,最后完成数字签名.

注意事项

证书的安全性:制作和使用数字证书时,需妥善保管私钥文件和密码,防止证书被盗用或泄露,以免造成软件被恶意签名或其他安全问题.

准确填写描述信息:填写功能描述和 Web 位置时,必须准确无误且指向证书签名单位网站上有关此软件的介绍页面,否则可能导致证书被吊销.

简介下这个 .net 开发的客服系统

可全天候 7 × 24 小时挂机运行,不掉线不丢消息,欢迎实测。

https://kf.shengxunwei.com/

希望能够打造:
开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。

钟意的话请给个赞支持一下吧,谢谢~

前言

最近有个新同事问了我一个问题,明明通过limit给容器内存限制了4G,为什么进容器看到的还是宿主机的内存32G

▶ docker run -it --rm -m 512m ubuntu:18.04 bash
root@ae00bec75ad7:/# free -m 
              total        used        free      shared  buff/cache   available
Mem:          31954       11482        8487        1708       11983       18305
Swap:          2047           0        2047

这个提问不禁勾起了我的一泡回忆,那是之前在学习《深入剖析kubernetes》的时候提到的知识细节

环境准备

组件 版本
操作系统 Ubuntu 22.04.4 LTS
lxcfs 4.0.3
k8s v1.26.3

lxcfs原理介绍

  • free
    是从
    /proc
    文件系统获取的数据,但是容器启动的时候
    /proc
    还是映射的宿主机,所以
    free
    显示的信息肯定是宿主机的
  • 使用
    lxcfs
    可以解决这个问题,本质就是通过docker启动对于cpu、memory施加的限制行为,手动的挂载
    proc
    (修改过的)文件系统进入容器内
  • 目前项目依然在更新:
    lxcfs
    ,从文档看,支持的文件系统有这些:
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime
/proc/slabinfo
/sys/devices/system/cpu/online

安装lxcfs

1)直接使用apt安装lxcfs工具

▶ sudo apt install lxcfs

2)部署到对应的目录

sudo mkdir -p /var/lib/lxcfs
sudo lxcfs /var/lib/lxcfs &

部署完成之后,lxcfs是以一个后台进程的方式工作

docker 使用

1. 常规启动

▶ docker run -it --rm -m 512m ubuntu:18.04 bash
root@ae00bec75ad7:/# free -m 
              total        used        free      shared  buff/cache   available
Mem:          31954       11482        8487        1708       11983       18305
Swap:          2047           0        2047

2. docker使用lxcfs

先安装lxcfs

▶ sudo apt install lxcfs
▶ docker run -it --rm -m 512m \
      -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
      ubuntu:18.04 bash
root@56e3c146ba4e:/# free -m
              total        used        free      shared  buff/cache   available
Mem:            512           1         510           0           0         510
Swap:             0           0           0

通过lxcfs,让docker正确的识别了限制的内存

k8s 使用

1. 常规启动

▶ echo '          
apiVersion: v1
kind: Pod
metadata:
  name: wilson-test
spec:
  containers:
  - image: ubuntu:18.04
    imagePullPolicy: IfNotPresent
    command: ["sleep", "33333"]
    name: wilson-test
    resources:
      limits:
        memory: 128Mi
      requests:
        memory: 64Mi
' | kubectl apply -f -
pod/wilson-test created

▶ kubectl get pod 
NAME          READY   STATUS    RESTARTS   AGE
wilson-test   1/1     Running   0          3s

▶ kubectl exec -it wilson-test -- free -m
              total        used        free      shared  buff/cache   available
Mem:          31954       11034        6384        1568       14534       18893
Swap:          2047           0        2047

使用lxcfs

▶ echo '                                                                                                                                                                                                                             
apiVersion: v1                                                                                                                                                                                                                       
kind: Pod
metadata:
  name: wilson-test
spec:
  containers:
  - image: ubuntu:18.04
    imagePullPolicy: IfNotPresent
    command: ["sleep", "33333"]
    name: wilson-test
    resources:
      limits:
        memory: 128Mi
      requests:
        memory: 64Mi
    volumeMounts:
    - mountPath: /proc/meminfo
      name: lxcfs-proc-meminfo
      readOnly: true
  volumes:
  - hostPath:
      path: /var/lib/lxcfs/proc/meminfo
      type: ""
    name: lxcfs-proc-meminfo
' | kubectl apply -f -

pod/wilson-test created

▶ kubectl get pod 
NAME          READY   STATUS    RESTARTS   AGE
wilson-test   1/1     Running   0          2s

▶ kubectl exec -it wilson-test -- free -m
              total        used        free      shared  buff/cache   available
Mem:            128           0         127           0           0         127
Swap:          2047           0        2047

内存限制
128m
已经生效

k8s自动注入lxcfs preset

1. 使用k8s preset

  • kubernetes v1.20 把 preset给移除了
  • github上有大佬用CRD给做了回来
    podpreset
    ,但是3年没更新过了

2. 使用k8s
Admission Controller

在github也可以找到大佬现成
lxcfs-admission-webhook
,但是貌似也很久没更新了

小结

  • 本文只演示了内存,关于其他的指标,只需要依葫芦画瓢即可
  • 关于自动挂载,现成的项目都已经很久没有更新过了,后面可以尝试手搓一个
    admission-hook
    ,敬请期待

联系我

联系我,做深入的交流


至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

热点随笔:

·
2024年各编程语言运行100万个并发任务需要多少内存?
(
InCerry
)
·
.NET9 - Swagger平替Scalar详解(四)
(
IT规划师
)
·
《HelloGitHub》第 104 期
(
削微寒
)
·
MySQL用错了,99%的人已中招
(
苏三说技术
)
·
.NET Core 线程池(ThreadPool)底层原理浅谈
(
叫我安不理
)
·
最全ECharts 实战大全(速记版+资源)
(
小阿鑫
)
·
一文详解:项目如何从Docker慢慢演变成了K8s部署
(
努力的小雨
)
·
Redis究竟为什么这么快?
(
seven97_top
)
·
代码编写之道:十条经验引领高效编程之旅
(
waynaqua
)
·
基于 .NET 的开源工作流引擎框架
(
小码编匠
)
·
记一次 .NET某hdp智能柜系统 卡死分析
(
一线码农
)
·
独立开发者应该如何设计产品网站
(
升讯威在线客服系统
)

热点新闻:

·
AI编程在硅谷杀疯了,但国内还长得出自己的Cursor么
·
银河系外恒星特写照片首次发布
·
华为“最强Mate”手机来了!AI能力拉满,售价5499元起
·
小米SU7自动泊车“惊魂一刻”,技术漏洞何时休?
·
高密度、高可靠性:我国科学家实现金刚石光学信息存储
·
网友高速路上偶遇雷军,本人正在测试小米SUV
·
把中国车卖给俄罗斯人,比想象中复杂
·
余承东:尊界车长约5.5米 尺寸可能超越马路上99.99%的轿车
·
第一批用AI的外贸人已经赢麻了
·
华为鸿蒙大势已成!南航、东航、海航鸿蒙原生版办公应用上架:覆盖员工10万+
·
中国大模型生存战:巨头围剿,创业难熬
·
突破生产力天花板,华为纯血鸿蒙平板正式亮相

公司有一套StarRocks的大数据库在大股东的腾讯云环境中,通过腾讯云的对等连接打通,通过dolphinscheduler调度datax离线抽取数据和SQL计算汇总,还有在大股东的特有的Flink集群环境,该环境开发了flink开发程序包部署,实时同步数据。

公司业务帆软报表平台有40张左右的报表连接的Starrocks大数据库。Starrocks大数据库整个库大小
超过13TB+

因各种原因,大股东的腾讯云环境不再让使用,打通的对等连接也会断开,需要把Starrocks及相关的服务等迁移回来:

1,Dolphinscheduler分布式调度:调度Datax抽取脚本和SQL计算汇总脚本

2,重新部署StarRocks数据库集群

3,实时同步几十张实时同步的表

4,同步现有StarRocks的历史数据到新的集群中

5,实时Flink聚合的表

因涉及的报表和东西多,再2023年就公司说要迁回来,但情况一说,太复杂了,就一直拖着不迁移。

但到2024年4,5月份,公司大股东说必须要迁移,公司让尽快研究StarRocks迁移事情,这件事又落自己头上,想想头大,这么多事情,测试方案,部署环境,买机器,实时同步,历史数据处理等等,这次没办法只能向前做,从2024年5月份到现在2024年11月份,迁移工作是被动做做停停的,到现在完成差不多,抽空把过程总结写下来:

1,Dolphinscheduler分布式调度

1.1  为省成本,请大股东的运维远程在公司腾讯云现有机器上部署DS调度,部署的版本一致,在个别机器内存做扩容

1.2  以前海豚的调度元数据库导出,部署到公司的MySQL,这样任务和调度就和以前一样。

1.3  海豚调度的Datax脚本,因以前他们用了CFS服务共享磁盘用一套,这边做不了,只能在3台机器上各部署一套路径一致的datax抽取脚本

2,部署StarRocks数据库集群

考虑兼容问题,没有使用最新的StarRocks 3 版本,用的腾讯云EMR集群的Starrocks2.5版本,省去自建和维护的很多事情。

3,实时同步

1,使用Flink集群

以前做的程序是在其特殊Flink API环境开发,拿以前的程序直接部署到Flink集群就无法使用,要么重新开发,我不擅长Flink这块,
只能放弃!


2,腾讯云---

流计算Oceanus

咨询腾讯云的技术支持,推荐Oceanus,可以实现Flink SQL实现实时同步,发现还有多表同时同步的,觉得终于可以解决这个实时同步问题了,就买了一个月的Oceanus服务,测试了多表,通过Microsoft VS Code搜索目录下的帆软报表,找出实时同步的表,然后按库多表同时同步,但是部署6个任务后,按库多表同时同步,经常报错,不稳定,后来咨询,腾讯云说多表同步不稳定的确不推荐,但我一个表一个job任务,那要多少任务,肯定不行

没办法不能使用!

3,Java程序实现实时同步

研发同学,说以前做个单个表的同步,没办法,只能让他通过java程序来实现同步,通过读取binlog程序写到库里,后来把这6个整理的几十个任务表提供,他写java程序同步,
可以使用。

4,StarRocks历史数据同步

咨询大股东,他们迁移StarRocks到腾讯云的EMR,历史数据是通过
StarRocks外部表来做
,但公司说要节省成本折扣更多,把StarRocks买到另外一个腾讯云账号上,再打通到现在公司的腾讯云,这样就有3个腾讯云账号,又没法把新账号腾讯云和大股东腾讯云打通,结果导致2个Starrocks不通,不能通过外部迁移历史数据,没办法,这时就想到用自己做的开源
pydatax
来同步,但要拼接处src_table_column表,直接通过SQL就可以出来如下:

select  TABLE_NAME,GROUP_CONCAT(replace(COLUMN_NAME,'etl_process_time','now() as etl_process_time')) cols from(selectTABLE_NAME,COLUMN_NAME,ORDINAL_POSITIONfrominformation_schema.`columns`where TABLE_SCHEMA='db'
and TABLE_NAME like 'bo_ods%' order by TABLE_NAME asc,ORDINAL_POSITION asc) tGROUP BY  TABLE_NAME order by TABLE_NAME asc

以上表是离线的,实时的也是类似。获取到src_table_column信息,通过下列SQL获取写入到datax_config_wm表

SELECTTABLE_NAMe,
CONCAT("
INSERT INTO datax_config_wm (type, src_table_name, json_id, des_table_name, relation,dcondition, ",
"src_table_column, des_table_column, server_type, ordernum, status, etl_type, etl_column, etl_num, last_etl_date, note, ",
"create_time) VALUES ('1','",TABLE_NAMe,"','",'9',"','",TABLE_NAMe,"',","'t','","1=1","','",GROUP_CONCAT(COLUMN_NAME),"'",'ss#stt')FROM(select * from information_schema.`columns` where TABLE_SCHEMA='report_srdw' and TABLE_NAME in(select TABLE_NAME from information_schema.`tables` where TABLE_SCHEMA='report_srdw' and ENGINE='StarRocks' and TABLE_NAME like 'bo_ods_%')order by TABLE_NAME asc,ORDINAL_POSITION asc) tgroup by TABLE_NAME;

注:这个'
ss#stt'
字符,是用来替换成下列字符:

, '*', 0, 22.001, 1, 0, '', 14, CURRENT_DATE(), 'wm', now());

生成完成后,copy和修改
pydatax
让其读取配置表datax_config_wm,离线是T+1,同步历史数据。

已经部署的海豚调度已经每天在同步数据。历史数据就通过
pydatax
同步数据,遇到特别大的表,导致抽取查询超时,修改参数成6000秒:

set global query_timeout=6000;

但改完个别表大还是超时,这时对这个表分割多次同步,直接修改datax_config_wm的加上范围就可。

几天时间,实时和离线的322张表历史数据就同步完成,部分大表抽取信息如下,看出Datax的能达到12万行+/秒的速度,6.6亿多条同步要 91分钟。

5,实时Flink聚合的表

帆软报表用到实时聚合表,但是研发同学没有实时聚合功能,查询实时报表,分析虽然做了好多聚合表,但实际只有5张表使用,

想想就使用StarRocks 的物化视图,替换原有聚合表,对报表透明无感知,这5张表的聚合对应修改成聚合后的物化视图。

上线后,有3张物化视图的源实时表老是同步出错,不得不取实时表改成T+1的数据表,和产品经理沟通后,对应的报表的显示的"实时"也加上"昨天"。

以上修改后,正式切换线上帆软报表连接成新的StarRocks 库,观察线上的客户使用情况。

总结:

1,该迁移前后花了好几个月时间,有点长!

2,难到不难,大量的细心的工作需要做!

3,数据同步工具
pydatax
又一次出色完成其高效简单的数据迁移任务。