谈谈ChatGPT

春节期间,试用了ChatGPT,让我被惊艳到了。
大模型的涌现效果,能达到ChatGPT3.5的程度,着实让我有些吃惊,真是大力出奇迹啊。

在此之前,我一直认为本次AI技术革命已经接近尾声了:
1、在影像和视频方面,AI已经可以实现商业化:医疗影像AI诊断、自动驾驶、人脸识别、图像搜索、P图滤镜等;
2、在语音方面,语音识别和语音合成已经很成熟;
3、在NLP方面,简单重复任务可以较好完成,比如机器翻译、文本搜索等。但在复杂任务上,还处于有多少人工就有多少智能的尴尬阶段,距离商业化有较长的路需要走;
而且,无论是哪个领域,大家可以发现,AI还是只是一种能力、一个工具,也就是处于“业务X+AI”的模式。
就算AI是生产力,但想象空间也就那么大,因为领域已经被限制死了。

但ChatGPT改变了这个局面,聊天这个场景,可以让ChatGPT成为一个各种能力的插座。
也就是说,一个类似于ChatGPT的大模型,如果能快速整合各种外部能力,从“业务X+AI”,变成“AI+业务X、业务Y、业务Z”的模式,很可能会成为下一代互联网的入口,并从各种维度给人类带来全新体验。

钢铁侠的贾维斯(J.A.R.V.I.S.)还是保守了,我们有更广阔的空间,十分期待这个时代能尽快到来。

同时,国内大厂的大模型层出不穷,究竟谁能成功,还要看三个地方:
1、要有足够大量的数据
2、要有AI人才储备
3、要有足够算力,如果现在才去买显卡,就很难赶上了
国内满足这几点的有:质谱【从闭源到开源】、阿里【闭源到开源】、百度【已掉队】、字节【已掉队】

最近看了一些ChatGPT资料,整理了一些相关示例:
https://github.com/neohope/NeoDemosChatGPT

其中多数例子,来源于极客时间徐文浩老师的课程《AI大模型之美》:
https://time.geekbang.org/column/intro/100541001?tab=catalog

================
补充0812:
当前国内大模型厂商,在底层方面依赖英伟达,在模型技术层面无法相互拉开差距,只能继续向上做:
1、在基础模型层面,支持各类开源模型,弥补自家模型缺点
2、在行业领域,开展合作,把垂直领域模型吃掉
3、在应用层面,也开始逐步布局
加上外资撤出,投资方的钱更难拿,围剿之下,AI方向国内的创业氛围就比较差了。

几个硬件问题导致的故障

1、更换服务器后,出现网络风暴
表现:
老服务器下架,新服务器上线后,出现网络风暴

原因:
逐步排查网口,猜测一根光纤出现问题

解决:
更换了一根光纤

2、老服务器下架后,新服务器重启后,VM集群无法启动
表现:
三台ESXI主机组了VSAN,重启后,网络互通,但服务器2被独立,无法加入1、3集群
VCSA也在VSAN上,同样无法启动。

原因:
故障时,只知道出现了脑裂,三台主机无法

解决:
重启了VPXA、重启了ESXI,没有解决问题
重建VSAN,然后把三个节点加入,问题就修复了
后续发现,其实时服务器1和服务器3出现了问题,自己组成了一个新的集群

如何通俗解释数字化转型

咱们做技术的人,都喜欢起名字:信息化、数字化、数字平台、数字化转型、数智平台等,让很多人一开始觉得好高大上,然后又开始发懵,这些词之间有什么区别呢?试着通俗解释一下:

1、信息化
把组织线下业务流程,放到线上的过程。
比如,咱们学校上线了考勤系统、选课系统,这就是一个信息化的过程

2、数字化赋能阶段一:数字报表
在信息化的过程中,产生了部分的数据,对这部分数据进行挖掘提炼,得到一些报表,对组织经营起到了一定的提升作用。
比如,大家经常能看到的各类系统报表,通过经营分析报表,指导管理经营行为。

3、数字化赋能阶段二:数字平台
信息化建设后,各个系统之间是割裂的,各系统之间数据是互不相通的。
如何将数据打通,让组织运营者,可以对企业状况一览无余。
比如各类数据平台项目、数字平台项目,一般都会为运营者提供各类“驾驶舱”或Dashboard。
其实就是为管理者开了天眼,有了全局视角。

4、数字化赋能阶段三:自动化平台
当企业数字化建设到一定程度的时候,很多管理规则可以抽象并固化为系统规则,不需要人干预即可处理事情。
比如自动化制造、自动化质控、自动化风控、甚至量化交易等等。

5、数字化赋能阶段四:智能数字化平台,或数智平台
在3的基础上,引入了一些物联网技术、智能终端技术等,一方面让运营者可以快速感知一线情况,一方面可以快速决策反馈。
比如电商平台发现交易异常的时候,会触发智能平台的规则,自动止血;或者一些智能可穿戴设备,实时监控患者病情,及时进行干预。

6、数字化转型
但组织到了一定的发展阶段,传统的运营方式,已经无法支撑组织进一步的快速发展。
需要自上而下的去调整思路,用数字化运营的方式,重塑组织的运营方式,这其中数字化技术只是一个手段。
以华为为例,他们建立了基础IT架构(华为云),打造了统一的数据底座,提供了统一的数字服务,使用了大数据、AI、IoT等技术,最终通过数字化重构了业务运营方式,包括数字化作业、数字化交易、数字化运营、数字化办公等,从而造就了了华为近10年的飞速发展。
对于咱们老年人慢病管理,我们同样需要技术架构,同样需要统一的数据底座,同样需要封装统一的数字服务,同样可以使用大数据、AI、IoT等技术,但最终要重构哪些业务的运营方式,要重构成什么样子,就是咱们课题组要考虑的了。
比如,我们通过数据分析,可以主动为各类患者提供各类服务(比如糖尿病患者),比如:量身定制适合各自的治疗及追踪方式,量身匹配到不同的家庭医生,提前把患者需要的药帮患者准备好,提前把社区医院的耗材准备好等等等等。

7、数字化赋能与数字化转型的区别
7.1、数字化赋能
业务V1.0+数字技术=》业务A V1.1
7.2、数字化转型
业务 V1.0+自上而下的数字化运营体系+技术体系支持=》业务 V2.0

Transformer03:自注意力机制

Transformer模型的核心是自注意力机制(Self-Attention),它允许模型在处理序列时,能够捕捉序列内部不同位置之间的依赖关系。自注意力机制的计算过程可以概括为以下几个步骤:

1. 查询(Query)、键(Key)、值(Value)的生成:
对于输入序列中的每个元素,模型会分别生成对应的查询(Q)、键(K)和值(V)。这通常是通过输入序列与三个不同的权重矩阵相乘来实现的。

2. 注意力分数的计算:
对于序列中的每个元素,计算其查询(Q)与序列中所有元素的键(K)的点积,然后除以一个缩放因子(通常是键向量维度的平方根),得到一个注意力分数。

   
  \[
   \text{Attention Score} = \frac{Q \cdot K^T}{\sqrt{d_k}}
   \]

其中,(Q)和(K)分别是查询和键的向量,\(d_k\) 是键向量的维度。

3. Softmax归一化:
使用Softmax函数对注意力分数进行归一化处理,使得所有元素的注意力分数之和为1。这表示每个元素对其他元素的注意力贡献是相对的。

   
   \[
   \text{Attention Weights} = \text{Softmax}(\text{Attention Score})
   \]

4. 加权求和:
将归一化后的注意力权重与对应的值(V)相乘,然后将所有元素的加权值相加,得到最终的输出。

   
   \[
   \text{Output} = \sum (\text{Attention Weights} \times V)
   \]

5. 多头注意力:
Transformer模型中的自注意力通常不是只计算一次,而是通过多头注意力(Multi-Head Attention)来实现。这意味着模型会并行地执行多次自注意力机制,每个头都有自己的查询、键和值权重矩阵。最后,这些头的输出会被拼接起来,并通过一个线性层来整合信息。

6. 残差连接和层归一化:
在自注意力层之后,通常会有一个残差连接,它将自注意力层的输入直接添加到输出上,然后通过一个层归一化(Layer Normalization)来稳定训练过程。

整个自注意力机制使得Transformer能够并行处理序列中的所有元素,并且能够捕捉到元素之间的长距离依赖关系,这是它在处理序列数据时非常有效的原因之一。

让我们通过一个简单的例子来说明自注意力机制的计算过程。假设我们有一个由3个词组成的序列:[“I”, “love”, “coding”],并且每个词的词嵌入维度是4。

步骤1: 词嵌入
首先,我们将每个词转换为词嵌入向量。假设词嵌入矩阵已经预先训练好,我们可以直接获取每个词的词嵌入向量:

– “I” -> [0.1, 0.2, 0.3, 0.4]
– “love” -> [0.5, 0.6, 0.7, 0.8]
– “coding” -> [0.9, 1.0, 1.1, 1.2]

步骤2: 添加位置编码
接下来,我们为每个词嵌入向量添加位置编码。假设我们使用标准的正弦和余弦函数生成位置编码,并且序列的最大长度是3。位置编码向量如下:

– 位置1的编码:[sin(0), cos(0), sin(8), cos(8)] (这里8是4*2,因为每个词嵌入维度是4)
– 位置2的编码:[sin(1), cos(1), sin(9), cos(9)]
– 位置3的编码:[sin(2), cos(2), sin(10), cos(10)]

将位置编码向量与词嵌入向量相加:

– “I” (位置1): [0.1+sin(0), 0.2+cos(0), 0.3+sin(8), 0.4+cos(8)]
– “love” (位置2): [0.5+sin(1), 0.6+cos(1), 0.7+sin(9), 0.8+cos(9)]
– “coding” (位置3): [0.9+sin(2), 1.0+cos(2), 1.1+sin(10), 1.2+cos(10)]

步骤3: 自注意力计算
现在我们开始自注意力的计算过程。首先,我们需要为每个词生成查询(Q)、键(K)和值(V)向量。假设我们使用相同的词嵌入向量作为Q、K和V的初始输入,并通过不同的权重矩阵进行转换:

– Q = W^Q * 输入向量
– K = W^K * 输入向量
– V = W^V * 输入向量

这里W^Q、W^K和W^V是模型的可学习参数。

步骤4: 计算注意力分数
对于序列中的每个词,我们计算其查询向量与序列中所有词的键向量的点积,然后除以键向量维度的平方根进行缩放:

– 对于词”I”,其注意力分数是它自己的Q与所有词的K的点积:

   
  \[
  \text{Attention Score}_{I \rightarrow \text{all}} = \frac{Q_I \cdot (K_{I} + K_{love} + K_{coding})^T}{\sqrt{d_k}}
  \]

步骤5: Softmax归一化
使用Softmax函数对每个词的注意力分数进行归一化处理:

– 对于词”I”,归一化后的注意力权重是:

   
  \[
  \text{Attention Weights}_{I \rightarrow \text{all}} = \text{Softmax}(\text{Attention Score}_{I \rightarrow \text{all}})
  \]

步骤6: 加权求和
最后,将归一化后的注意力权重与对应的值向量相乘,并求和得到最终的输出:

– 对于词”I”,其输出是:

   
  \[
  \text{Output}_I = \text{Attention Weights}_{I \rightarrow I} \cdot V_I + \text{Attention Weights}_{I \rightarrow love} \cdot V_{love} + \text{Attention Weights}_{I \rightarrow coding} \cdot V_{coding}
  \]

这个过程对于序列中的每个词都要重复执行,以计算整个序列的输出。自注意力机制允许模型在处理每个词时,都能够考虑到序列中其他所有词的信息,从而捕捉词与词之间的复杂关系。

请注意,这个例子是一个简化的版本,实际的Transformer模型可能会使用多头自注意力机制,并且会有多个层来进一步处理信息。此外,词嵌入和位置编码通常是通过预训练得到的,而不是从头开始训练。

Transformer02:词嵌入及位置编码的计算

一句话经过分词和嵌入之后,输入到Transformer模型的过程如下:

1. 构建输入序列:
将分词后得到的词或字符序列转换为对应的词嵌入向量。每个词或字符都有一个对应的嵌入向量,这些向量通常通过预训练的词嵌入模型获得。

2. 添加位置编码:
由于Transformer模型本身不包含递归或卷积结构,因此它无法直接捕捉序列中的位置信息。为了解决这个问题,需要为每个词嵌入向量添加一个位置编码。位置编码通常是根据词在序列中的位置生成的,它与词嵌入向量相加,使得模型能够利用位置信息。

3. 输入到Transformer:
将包含位置编码的词嵌入向量作为输入序列送入Transformer模型。在Transformer模型中,输入序列被处理为一系列向量,每个向量对应序列中的一个元素(词或字符)。

4. 多头自注意力:
Transformer模型使用多头自注意力机制来处理输入序列。在自注意力层中,每个元素的嵌入向量都会与序列中所有其他元素的嵌入向量进行比较,以计算注意力权重。这个过程在多个“头”中并行进行,每个头都有自己的查询(Q)、键(K)和值(V)权重矩阵。

5. 层归一化和前馈网络:
自注意力层的输出会经过层归一化,然后送入前馈神经网络。前馈网络通常由两个线性变换和一个非线性激活函数组成。这个过程在每个Transformer层中重复进行。

6. 堆叠多个Transformer层:
Transformer模型通常由多个相同的层堆叠而成,每个层都包含自注意力机制和前馈网络。通过这种方式,模型可以在不同层捕捉不同级别的特征和依赖关系。

7. 输出处理:
经过多个Transformer层处理后,模型的输出可以用于各种NLP任务,如语言翻译、文本摘要、问答等。对于特定的任务,可能还需要在Transformer模型的顶部添加额外的层,如线性层或分类层。

总之,每个嵌入向量并不是有自己的Transformer,而是所有嵌入向量一起作为输入序列,被送入同一个Transformer模型中进行处理。通过多头自注意力机制,模型能够捕捉序列内部不同位置之间的依赖关系,从而实现对输入句子的深入理解。

通过一个简单的例子来说明词嵌入和位置编码的计算过程。

### 词嵌入(Word Embedding)

假设我们有一个句子:”I love natural language processing”。首先,我们需要将这个句子分词成单词列表:[“I”, “love”, “natural”, “language”, “processing”]。

接下来,每个单词将通过一个词嵌入矩阵转换成一个固定维度的向量。假设我们的词嵌入维度是4,那么每个单词将被映射到一个4维空间中。例如:

– “I” -> [0.1, 0.2, 0.3, 0.4]
– “love” -> [0.5, 0.6, 0.7, 0.8]
– “natural” -> [0.9, 1.0, 1.1, 1.2]
– “language” -> [1.3, 1.4, 1.5, 1.6]
– “processing” -> [1.7, 1.8, 1.9, 2.0]

这里的数字是随机生成的,实际的词嵌入向量是通过训练得到的,能够捕捉单词的语义信息。

### 位置编码(Positional Encoding)

Transformer模型不包含递归或卷积结构,因此无法直接捕捉序列中单词的顺序信息。为了解决这个问题,我们需要为每个词嵌入向量添加位置编码。

位置编码通常是通过正弦和余弦函数的组合来生成的,以确保不同维度的位置编码具有不同的频率。假设我们的词嵌入维度是4,我们可以为每个位置生成一个4维的位置编码向量:

– 位置1的编码:[sin(1/10000), cos(1/10000), sin(2/10000), cos(2/10000)]
– 位置2的编码:[sin(2/10000), cos(2/10000), sin(4/10000), cos(4/10000)]
– 以此类推…

将位置编码向量与相应的词嵌入向量相加,得到最终的输入向量:

– “I” (位置1): [0.1+sin(1/10000), 0.2+cos(1/10000), 0.3+sin(2/10000), 0.4+cos(2/10000)]
– “love” (位置2): [0.5+sin(2/10000), 0.6+cos(2/10000), 0.7+sin(4/10000), 0.8+cos(4/10000)]
– 以此类推…

这样,每个单词的嵌入向量都包含了其在句子中的位置信息,使得Transformer模型能够在处理序列时考虑到单词的顺序。

### 注意事项

– 词嵌入和位置编码的具体计算方法可能因不同的模型和实现而有所不同。
– 实际应用中,词嵌入通常是通过预训练模型(如Word2Vec、GloVe或BERT)得到的,而不是从头开始训练。
– 位置编码的生成方法在不同的Transformer变体中可能有所不同,例如Transformer-XL和XLNet采用了不同的方法来处理长序列。

这个例子展示了词嵌入和位置编码的基本计算过程,以及它们如何帮助Transformer模型理解和处理自然语言序列。

在实际应用中,词嵌入和位置编码可以预先计算并缓存,以提高效率。下面是一些具体的情况:

1. 词嵌入的缓存:
– 词嵌入通常是通过预训练语言模型得到的,这些模型在大规模语料库上训练,学习到的词嵌入向量能够捕捉丰富的语义信息。
– 一旦词嵌入矩阵训练完成,对于任何给定的单词,其对应的词嵌入向量就可以直接从预训练的模型中获取,而不需要每次重新计算。

2. 位置编码的缓存:
– 位置编码的生成方式是固定的,例如使用正弦和余弦函数的组合,这意味着对于给定的维度和最大序列长度,位置编码向量可以预先计算出来。
– 在模型初始化阶段,可以生成一个位置编码矩阵,其中每一行对应一个位置的位置编码。在处理输入序列时,只需根据序列中单词的位置索引来选择相应的位置编码向量。

3. 缓存的优势:
– 缓存词嵌入和位置编码可以显著减少模型在每次前向传播时的计算量,特别是对于大型模型和长序列。
– 缓存还可以减少模型的延迟,因为从内存中读取预先计算好的向量比实时计算要快得多。

4. 实际应用:
– 在实际的深度学习框架中,如TensorFlow或PyTorch,词嵌入和位置编码通常作为模型的参数或静态变量存储,以便在模型训练和推理过程中重复使用。

5. 灵活性:
– 虽然位置编码通常是固定的,但在某些情况下,如果模型需要处理可变长度的序列,位置编码也可以动态生成。但即使如此,对于常见的序列长度,位置编码的计算可以预先完成,并存储在查找表中以供快速访问。

通过这种方式,词嵌入和位置编码的预先计算和缓存,可以使得Transformer模型更加高效地处理输入数据,特别是在处理大量数据或需要快速响应的应用场景中。

Transformer01:总论

在处理自然语言处理(NLP)任务时,输入一句话通常需要经过以下步骤:

1. 分词(Tokenization):
首先,输入的句子需要被分词,即将句子拆分成更小的单元,这些单元可以是单词、字符或者其他语言单位。分词是处理自然语言的第一步,因为大多数模型都是基于离散的词或字符进行操作的。

2. 词嵌入(Embedding):
分词之后,每个词或字符会被转换成词嵌入(Word Embedding)。词嵌入是将离散的词或字符映射到连续的向量空间中的一种表示方法。这些向量能够捕捉词的语义信息,并且通常通过预训练模型(如Word2Vec、GloVe或BERT等)来获得。

3. 位置编码(Positional Encoding):
对于Transformer模型,由于其自注意力机制无法捕捉序列中元素的顺序信息,因此需要添加位置编码。位置编码是一种向量,它与词嵌入相加,以提供序列中每个元素的位置信息。

4. 序列化(序列化处理):
在某些情况下,如果输入序列超过了模型的最大长度限制,可能还需要进行序列化处理,如截断或填充。

5. 模型处理:
经过上述步骤处理后,得到的序列化、嵌入化和编码后的输入数据就可以被送入模型进行进一步的处理和学习了。

因此,当输入一句话时,通常是先进行分词,然后计算词嵌入,最后将分词后的词嵌入与位置编码相结合,形成模型的输入。这个过程使得模型能够理解句子的结构和语义信息,并在此基础上进行各种NLP任务。

微服务性能调优01

近期遇到一些技术问题,记录如下:

1、kafka并发处理量上不去
数据流:
数据生产服务-》kafka-》数据消费服务
表现:
数据消费服务加了很多个实例,但总感觉多数实例不工作
原因:
分析后发现,原来开发小伙伴把所有消息都扔到了同一个topic中,而分区只有3,消费者再多这并发量也上不去啊
解决:
按不同业务,拆分topic,同时增加分区数
同时,建议把一堆操作拆分为多个步骤进行,不要都放到一个方法里全部做掉,宁可多流转几次各司其职

2、数据上报并发处理量上不去
数据流:
DB-》轮询-》HTTP提交数据到数据上报网站【ZF】
表现:
要求4小时上传60W,实际1小时上传5K
原因:
问题很多,主要有两个,一是每次只上传一条数据,二是没有做并发
解决:
一开始准备做很大的调整,但后面项目组怕把开并发把数据上报网站压挂,最后没敢使用
最后,只是改造为批量上传数据,轮询时根据id做了一下简单的并发
数据上报网站,各地接口及要求各不一样,也是各种不容易吧

3、莫名奇妙的403
数据流:
浏览器-》网关-》鉴权服务
表现:
网关偶尔返回403
原因:
一开始日志输出太少,都没有定位到哪里的问题,只能临时在网关补充了一些日志【建议加了开关,定位问题后关闭】
加日志后,发现是一段上古代码,使用信号量进行了并发控制,超出了并发就获取不到用户权限。
而这个Bug暴漏出来,据反馈,居然是升级组件导致的。
遗留系统都是坑啊。
解决:
优化鉴权服务,定位到问题,问题也就解决了

4、无法提升的微服务性能
数据流:
浏览器-》网关-》N个服务来回调用
表现:
服务性能差,有时要几十秒才返回,一堆告警邮件
原因:
微服务拆分粒度太细,形成环状调用链路
开发同学无脑调用微服务,能调用一次的,居然会循环调用N次
解决:
重构,按业务领域合并微服务,微服务数量少了60%,同时干掉环状调用链
评审,找到不合理的循环调用,抓典型,整改

5、批量导出
数据流:
浏览器-》网关-》导出服务-》DB
表现:
批量查询、批量导出性能很差,要按分钟返回的,一堆告警邮件
原因:
数据量太大,DB拉取速度慢,数据回传也慢
解决:
根据业务情况,部分批量查询功能改到只读库查询,大批量导出功能迁移到了数据中台

6、数据批量下发
数据流:
数据中台-》kafka-》数据下发接收服务
表现:
数据中台下发数据,无法更新到下游业务系统
原因:
因安全需求,上游业务系统批量刷新数据库,导致数据中台下发大量数据,数据下发服务处理不及时,积累了大量数据待处理
下游业务系统把一堆业务逻辑放到了接收服务中,处理单条业务数据要按秒计算,数据越积越多
你没想错,kafka并发上不去,和之前原因一样一样的
解决:
接收服务简化,拆分不必要的业务逻辑,服务性能提高了几百倍
优化kafka配置
制定了批量刷新数据库的相关流程,都是泪
历史数据咋处理?和上游系统沟通后,99.9%的数据不必处理,于是忽略了历史积累数据,晚上将0.1%的数据进行了重推,解决了问题

7、Kafka卡顿
数据流:
系统A-》kafka-》系统B
表现:
kafka在半夜性能下降明显,从日志上看,就是工作2分钟,卡5分钟
原因:
kafka的消费者每次取了太多消息去消费,半夜为业务高峰期,部分消费者获取消息无法及时处理完毕,导致kafka会出发rebalance,你懂的
解决:
每次少取一些数据

8、HTTPS通讯失败
数据流:
前置系统A-》云-》云上系统B
表现:
有两家用户的数据无法连通云服务,HTTPS通讯失败
原因:
前置服务的服务器器时间错误,数据包被云的安全策略直接丢弃,被当成重放攻击了
解决:
开启前置服务自动时间同步服务

9、组件升级导致服务性能下降
表现:
系统组件升级后,系统整体服务性能下降,会有部分请求阻塞5S以上
CPU、内存、IO看起来都比较正常
生产环境才有问题,测试环境下无法复现
原因:
通过打印线程信息,发现存在大量网络IO阻塞
后定位到了一个可疑的点,日志同时输出到log文件和命令行时,命令行也发送到了log文件,会有阻塞
解决:
只输出到命令行,有待观察

整体经验:
1、微服务粒度不能太细,也不能一个服务啥都干,最好按业务领域进行拆分。业务量小的领域可以适当合并,业务逻辑复杂的考虑拆分。
2、微服务也应该分层次,不要出现环状调用链路
3、日志要足够判断问题所在,太多影响性能,太少没啥用
4、中间件不能熟练配置,不要随便上生产
5、批量操作要用特殊处理方式,没事别刷库

为何互联网大厂不做医院的信息系统

一、从经济角度
1、付款能力
互联网大厂,大家看下财报,年营收上万亿,人均营收在400万以上。
而医院呢,除去顶尖几家,很好的医院一年营收也就几十亿、十几亿,人均营收几十万。随着疫情,很多医院营收更加困难。

2、付款意愿
互联网大厂中,研发费用投入占比远远高于医院在软件方向投入,大家去看下财报就懂了。

3、产品价格
从经济学角度观察,医疗信息化行业,长期低价值竞争,已经把行业利润搞到快养不起现在的开发了。
大厂进入,势必要引入更多更贵的开发资源入场,一定是个亏本买卖。
行业的强监管导致了没有什么新的花样可以搞,大厂不可能干亏本且没其他收益的买卖。

4、运维成本
大厂2C的高并发架构,在医院
1)是用不到
医院系统一天登录用户最多几千人
2)是成本太高
无论是硬件还是运维成本,医院都接不住:一台服务器能跑起来的项目,不要部署在五台服务器的K8S集群上。
如果服务器挂了,可以重启。但K8S挂了,很多医院自己都重启不了。
不要打炮打蚊子,没有最好的架构,只有在限定经济情况下,局部最优的架构。

经济学角度出发,这个事情就不成立。
所以现状大厂的做法是,赚云的钱,但利润低、受苦受累的医院信息化,是直接做集成的。

二、从技术和产品的角度
大厂对比医院,更像是2C对2B,2B和2C软件逻辑差异很大:

(一)技术困难点不一样
1、互联网大厂技术难度高的多,以并发量来说,医院一天门诊量1万多,住院几千张床,登录用户最多几千人,和双11没法比

2、医院信息化系统,以HIS为例,难度在于,业务需求的复杂度高,如果一位开发同学即对接过微信支付,又对接过医保支付,应该很能理解,微信支付的对接就和玩一样,因为医保支付会从根本上要求医院重构
举个例子:12306初期请了不少大厂专家,解决并发问题,但购票逻辑比网络购物复杂的多,这么多高手,也没有能快速拿下,崩了两年。不是这些专家能力差,而是需求复杂度更高。

(二)需求掌控能力
1、互联网大厂,是有强大的产品和运营的,他们有很清晰的目标,服务和讨好客户,把客户就在平台,并创业更高的商业价值。产品好不好,客户也就是最终用户有一票否决权

2、多数医院没有专职运营,能把业务流程,服务流程,系统流程说清楚的,全医院就没几个人。产品最终用户,医生护士,对于流程没有话语权,只能提出点状要求

3、更可怕的是,外行指导内行的情况,在2B领域更加可怕,很难拒绝一些不靠谱的需求
举个例子:当年IE特别慢,微软有团队准备从一个飞快的开源浏览器改一版替代IE。但当这个团队把一堆IE需求加上去之后,反而比IE还慢,项目就结束了。

三、从组织架构
1、执行力
互联网大厂组织结构更优化,目标十分清晰,执行力强的可怕
医院更偏事业单位风格,需要强大政策导向,才能爆发真正的执行力

2、变革意愿
互联网大厂,从开始就在不停的变革,大家对于失败容忍度较高
医院要抽取资源,做个什么新的项目,太难了:成功不一定有功,失败一定是过

四、为何越升级越难用
1、从经济学角度观察
很大的一个原因是,买单方和使用方不是同一波人,且使用方没有话语权。
买单方花钱升级系统为的是搞管理搞成绩,从来不是为了使用方体验更好。
搞管理,管的越来越多,越来越细,被管理的使用方自然越来越难受,就会憎恶这个带来苦恼的系统。
搞成绩,就要多做事,使用方工作就更多,同样会憎恶这个带来更多工作的系统。
工作多,管得细,发挥空间自然就少了,创新就更难了。
举个例子:钉钉打卡功能其实产品层面并不差,但被管理的人不爽,有人会说钉钉好用吗?

2、什么样的考核,带来什么样的结果,铸就什么样的团队。
系统升级,以管理为导向,时间短任务重,最终用户承担了越来越多的工作,会有人说你好吗?

一次数据库字段加密升级记录

今年个保法发布了,根据安全团队要求,需要对数据库的敏感字段进行加密处理。

当前数据库连接已经加密了,只需要对数据加密。有两种代价较小的方式:
1、在数据库存储引擎层面加密,这样对全部业务系统是无感的。
2、退而求其次,可以在数据库中间件或在驱动层面做加密,这样全部业务系统修改量也是比较小的。
但由于种种原因,这两种方式都没有能推行。

最后采用的方式是,安全团队提供加解密SDK,各业务系统对接。
业务系统启动,通过加解密SDK从密钥分发服务器获取密钥-》写入数据库前加密、读取数据后解密
加密算法都是国密算法,包括对称加密及摘要算法。
这样全部业务系统都需要改造,而且批量操作效率也比较低。
优点是,即使别人攻破数据库,也拿不到明文数据。

改造过程也很痛苦:
1、注册APP ID,申请密钥
2、研发刷库工具
3、在数据库表中增加加密字段,通过刷库工具,将历史敏感数据进行加密,存放到加密字段
4、基于加解密SDK,研发适用于个团队的切面SDK
5、使用切面SDK,对服务进行改造,读明文,写明文+密文(可跳过)
6、使用切面SDK,对服务进行改造,读密文,写明文+密文(可跳过)
7、使用切面SDK,对服务进行改造,读密文,写密文(可跳过)
8、删除明文字段
整个过程十分痛苦。

稳定性保障:
整个密钥下发服务器,是全局的一个大故障点,必须保障可用性。
密钥分发服务器,用到了密码机,提供了同城容灾及异地容灾环境。
支持DC单独部署,也支持云访问。

对应用系统影响:
1、改造量大,且无直接业务收益,资源投入受限
2、性能下降,尤其是批量加解密时,性能下降较多
3、模糊查询受影响较大,只能通过提前计算的摘要信息进行查询了
4、遗留系统、外购系统,改造难度太大,成本太高,无法承受

对数据中台的冲击:
所有依赖于数据库日志的系统,都会受到影响,尤其是数据中台
有两种方式,一是不使用,二是用同样的key