无标注数据是鸡肋还是宝藏?阿里工程师这样用它

阿里妹导读:针对业务场景中标注数据不足、大量的无标注数据又难以有效利用的问题,我们提出了一种面向行为序列数据的深度学习风控算法 Auto Risk,提出通过代理任务从无标注数据中学习通用的特征表示。这种思想与目前 NLP 领域前沿的 Bert 等预训练模型不谋而合,但是由于行为序列数据和业务的特点显著区别于 NLP,模型的设计和实现又有很大区别。最终,模型在真实场景中落地并取得了显著的增益;实验验证具有较好的多场景泛化能力;相比纯粹的监督学习,在小样本情况下提升明显。

一、背景

行为序列数据,如淘宝购物,支付宝风控事件等,在内部场景十分常见,也是推荐、风控等问题的源头级输入之一。给定一个用户的交易序列,要求预测他接下来会买什么;给定风控事件序列,要求预测是好人还是黑产,都依赖于将行为序列表示成特征向量,进而实现序列分类的基础能力。

行为序列示意图

传统方法是依据人工经验设计大量的触发、累积等特征,在此基础上训练 GBDT 等分类器。近年来,一个较为成功的方向是使用 RNN、CNN、Attention 等神经网络,直接以原始行为序列作为输入,输出分类结果或者特征向量。这种方法充分发挥 Everything-to-Vector 的思想,避免了繁琐的人工特征工程。例如,我们团队提出的 Detail Risk 框架,将一个用户的行为序列经过离散字段 embedding、文本卷积、多字段融合、事件卷积、Attention 等多层网络,最终转化为分类向量,在等多个场景落地,大量减少了人工工作,同时提高了模型效果。

Detail Risk 框架示意图

美中不足的是,这类方法大多是监督学习,label 样本不足的阴影始终挥之不去:少量样本无法真正发挥神经网络模型容量大的优势;引入 multi task label 辅助又要仔细权衡各个 task 之间的迁移能力,容易按下葫芦起了瓢。

而在另一方面,我们的业务中积累了堪称海量的未标注数据,如果能利用这些未标注数据训练模型,学习通用的高层特征,而将有限的 label 留给下游场景训练一个简单的分类器,将会极大地提高数据的使用率;另外,这些无监督产生的特征向量和人工设计的特征完全不同,融合后更容易取得效果提升。

二、预训练

相同的问题并非只发生在内部业务中,更加本源性的 NLP 研究从去年开始揭示了一条解决之道:Pretrain (预训练)技术——利用随手可得、但是蕴含知识的代理任务+大量的未标注数据+更深的网络,让模型自动学到有效的高层特征,在下游任务中稍加 finetune 即可取得很好的效果。进入2018年之后,ELMo、GPT、BERT、GPT2、 ERNIE 等预训练模型一遍又一遍地刷新了 NLP 各个基础问题的 SOTA,大有长江后浪推前浪之势。其中 BERT 更是一举刷新11项记录,同时也刷爆了算法工程师的朋友圈。

与训练原理示意图

在 CV 领域,使用 imagenet 预训练的大型网络可以追溯到深度学习的寒武纪时代——2014年;在 NLP 领域,使用 word2vec 或者 glove 预训练的词向量也是常规做法。但是,预训练一个像 Bert 这样大型的、能够显著提高下游任务效果的、还不使用 label样本的模型,却直到最近才爆发。作者认为是4个前置条件的达成解锁了这个科技。

  • 代理任务的积累:代理任务并非随便选择,从简单的 Cbow 和 SkipGram,最终到 Masked-LM、NSP,代理任务越来越难,也越来越能抓住高层抽象知识,这是 Pretrain 的关键。
  • 深层网络:越是深层的、大容量的网络,越能抽取高层的特征、存储更丰富的知识。ResNet、各种 Norm 技术、乃至 SBBB(ShortCut、BottleNeck、Branches、BatchNorm)这类构造模式的出现让深层网络的搭建和训练变得简单。
  • Attention:把 Attention 单独拎出来提并不过分。可以说它为神经网络提供了专门的 memory,以及各种基于 memory access 的功能:对齐、组合、远程依赖、全局视野等,极大丰富了模型的表示能力。这一点在我们关心的序列数据上尤为明显。
  • CNN 流崛起:相比 RNN,CNN 原本并非为序列数据设计,但是它天生易并行,对工业应用友好;易堆叠,适合做深层模型;欠缺的全局视野留给 Attention 去完成。本质上,Transformer 也属于 CNN 流:宽度为1的卷积核加上 Self-Attention。最近两年来,ConvS2S,ByteNet,WaveNet,SliceNet,Transfomer 等各种 CNN 流的工业级框架,正在逐步占领曾经属于 RNN 的天下。

预训练模型 Bert 所依赖的科技树

三、问题分析

目前,内部一些 NLP 产品已经率先用上了 BERT,但是在 NLP 之外的领域目前还未见获益。究其原因主要有:

1. 数据形式不同。风控、推荐等场景里的数据不是文本,而是行为序列。这不仅导致了谷歌提供的预训练参数不可用,更要求我们的模型去适配以下的数据特点:在每个时刻T 都有着多个输入字段、字段之间模态不同、序列长度巨大,没有天然存在的句子分隔,等等。

2. 训练开销巨大。这些专为 NLP 问题设计的模型,走的都是重型武器的路子:单层1600万参数的 Transformer,先来个十几二十层,整体参数2亿起;显存杀手 Self-Attention,在输入序列长度超过1000时单层就会导致 OOM(Out-Of-Memory);即便显存烧得起,收敛速度也很慢,8台最新的 GPU,训练时间也要以月计。为了解决自然语言中复杂的 parsing 和 composing 问题这样做是值得的,但是对行为序列数据来说,显得有些浪费。

因此,要享受预训练的好处,我们还需要另起炉灶,根据数据和业务特点,设计并实现自己的 Pretrain 模型。本文正是基于这种背景,设计并实现了一套行为序列无监督 Pretrain 框架,同时在实际业务落地中验证了其有效性。由于我们的业务场景是风控,因此将其称作 Auto Risk 模型。

四、模型设计

4.1 代理任务

预训练模型不需要任何实际任务的 label,但是需要随手可得的代理任务来驱动训练。代理任务的设计完全决定了模型会挖掘什么样的知识。我们将行为序列数据和文本进行类比,将每个时刻t看成一个词,每个连续序列1:T看成一个文档,那么类似于 BERT,我们也设计了两类代理任务:

两类代理任务

  • 词/事件级别的代理任务 Masked Language Model。我们掩盖输入序列在某个时刻 t 处的值,要求模型在t处输出的词级别向量能预测被掩盖的值。显然这个任务会驱动模型去挖掘序列前后的关联,将行为放到上下文中考察。
  • 句子/序列级别的代理任务 Quick Thought。我们通过采样把每个序列都分割成前后两个子序列,使用孪生网络对两个子序列分别编码为一个向量,再把 batch 内的子序列们两两随机组合,要求模型预测组合后的 pair 是否同源。这个方法最早来自 Skip Gram 的句子级别泛化——Skip Thought,而后将其中运行较慢的Encoder-Decoder 换成速度更快的孪生网络,因此称作 Quick Thought。显然,qt 任务会驱动网络去挖掘序列的标志性特点。

4.2 网络结构

代理任务提供了随手可得的 label,具体模型结构的核心则是 Encoder 网络。根据笔者在第二、三章的分析,像 BERT、GPT 那样直接使用重型武器 Transformer 是非常低效的。我们提出了一个更加高效的基于卷积和注意力的 Encoder 结构:

  • Embedding 层,用于把输入字段向量化,例如事件类型、时间、金额、付款渠道、商品名等不同字段,统统 embedding 表示,然后通过 Add 或者 Concat 融合;其中文本字段是 List 形式,不仅要 Embedding,还要通过卷积或者 Average 等方式汇总成单个向量。
  • Convolution 层,负责抓取局部上下文,我们假设这是行为序列的主要特征(在风控场景中),要做得准确、高效;
  • Attention 层,负责抓取全局上下文,我们假设这是行为序列的次要特征(在风控场景中),重要的是提供额外的视野和能力;
  • 一个 Convolution 层和一个 Attention 层组成一个 Block,使用 ResNet 的形式叠加多个这样的 Block 形成一个 Encoder,就如同叠加多个 Transformer 形成一个 BERT 一样,能够帮我们实现信息的抽象、整合。

Auto Risk 模型结构示意图

■ 4.2.1 Convolution 层改进

Convolution 用于序列时,需要叠加多层以增大视野,这就带来了两个副作用:1.梯度弥散,优化变难,2.参数和计算量巨增。为了解决这两个问题,我们结合两类特殊的卷积以替代一般卷积:Gated Conv 和 Depthwise Separable Conv。首先使用与 LSTM 类似的门机制来抑制梯度弥散问题,可以叠更多的层数;再将一次卷积分解成depthwise 和 pointwise 两步,使得参数量和计算量都从减少到,以特征维度 D=256,卷积核宽度 K=5为例,参数和计算量从32万降到6万,仅为原来的20%;若采用 K=31这样的大卷积核,甚至仅为原来的3.6%。改进后的卷积层显著提高了模型的收敛速度和最终效果。

卷积改进

■ 4.2.2 Attention 层改进

Attention 带来了优秀的视野和能力,但代价是的显存占用,因为它需要在序列内做两两对比。实践中,在序列长度超过1000时,一层 Self-Attention 就会造成显存溢出 OOM,而1000在行为序列问题中还并不算很长。出于现实考量,我们研究了 Fixed Size Attention 或者 Block Attention 替换一般的 Self-Attention,以微小的性能降低为代价,分别将显存占用率优化到 O(2NK) 和,最终实现在单 GPU 上,对长度4000的序列,能够叠加3层改进后的 Attention,顺利覆盖业务需求。

注意力改进

要训练一个这样的大型网络,还有很多 trick 要用到,本篇不再赘述,后续由系列文章分享。

4.3 训练

经过以上一系列优化,我们最终仅用一张显卡实现:

  • 在长度4000的序列上训练3层 Encoder 叠加的网络,而基于 Transformer 的 Bert 模型最多只能在1000以内的序列上训练一层网络。
  • 2~3倍于 Transformer 的 batch 训练速度(序列越长越显著)和更少的收敛步数,一天之内就可以完成千万级别数据的训练。

下面这张图对比了使用不同 Encoder 结构的训练过程,可以发现:

  • 使用卷积+注意力 Encoder 比仅使用卷积 Encoder 或注意力 Encoder 都要好;
  • 卷积对 Loss 的贡献更大,发挥主要作用,注意力发挥次要作用;
  • 叠加多层 Block 效果更好。

五、应用效果

5.1 业务增益

首先,我们评估 Auto Risk 模型对业务的增益。我们使用的风控行为序列包括登录、改密、交易等重点风控行为。我们从全体用户中随机采样了部分作为训练集,训练了一个三层、hidden=128的网络,然后对其他用户,推断其向量。最后将这些向量加入到特征池子中,比较 AUC 效果提升。参与比较的有:

人工特征 SOTA:人工特征的 state-of-the-art,如资产能力、信贷信用等,这些都是在消费金融、信贷、先享后付等场景久经考验的特征。

+ AutoRisk pretrain:在人工特征 SOTA 的基础上,加上原始的 Auto Risk 向量。

+ AutoRisk finetune:在人工特征 SOTA 的基础上,加上场景 finetune 之后的 Auto Risk 向量。

可见,加入 Auto Risk 向量之后,AUC 取得3~6个点的显著提升,说明无监督的 Auto Risk 能够从行为序列中提取到有用的特征;在具体场景中 finetune 一下网络参数会比不做 finetune 更好,这一点与 Bert 等也是相同的。为了简化对比,这张图只展示了使用风控事件作为序列数据的效果。

5.2 多场景效果

由于 pretrain 模型的训练过程没有用到任何具体的场景 label,因此学到的知识比较通用。我们尝试了不同场景,包括一些看似无关的预测性别和年龄的问题,既不加任何人工特征,也不做 finetune,只用最简单的 LR 分类器,分别做 train-test,结果比较惊喜,有的甚至 AUC 达到0.9。一个潜在的业务价值是,也许可以用超低的代价,实现对各个业务的通用补充特征。

为何仅用 LR 就可以取得这样的效果?可以这样理解:Auto Risk 将行为序列的信息比较完整地保留到一个性质较好的 Embedding 空间中,对不同的任务可以找到各自适合的线性分类界面。下图展示了消费金融套现场景的测试集样本和分类平面,由于使用了降维算法(Umap)将128维的向量降到3维,分类性能损失了大约6个点的 AUC,但是依然可以清晰地看到:

1.套现和非套现商户具有明显的分类平面;

2.空间具有明显的流形结构,具体每个簇代表什么含义我们还没有去分析,但是可以肯定的是簇中的点具有相似的行为模式。

5.3 小样本学习

Pretrain 带来的另一个优势是小样本福音。深度学习模型因为参数众多,一般在 label样本较少时效果不佳,而 Pretrain 模型已经通过无监督代理任务学会了大部分知识,因此少量label样本就可以取得更好的结果,更适合冷启动或者 label 昂贵的业务。我们在先享后付场景 B 上对两类不同的行为序列数据分别进行了实验,结果都表明 Auto Risk 会比从零开始训练一个监督学习的神经网络要好的多;在行为日志数据上,甚至都不用 finetune,仅用 Auto Risk+LR,就比监督学习更好。训练集的 label 样本数量已经达到4万(正负样本各2万),监督学习还没有能够追上 Auto Risk+finetune。

5.4 序列 Analogy

Analogy,即单词类比,是 Word Embedding 的一个有趣特性。在 Embedding 空间里,国王(King)-男人(Man)=王后(Queen)-女人(Women),中国(China)-北京(Beijing)=法国(France)-巴黎(Paris),类似的等式从侧面证明了 Embedding 空间确实抓住了高层语义。那么,我们的 Auto Risk 空间中的序列有没有这种特性呢?我们同样进行了一个 A-B=C-D的实验,对100万个样本构成的集合,选定 A、B 和 D,通过与A-B+D 向量的余弦相似度召回 C。为了看得更清楚,我们将不同的字段分开展示,但训练过程还是多字段一起的。

事件类型:A(淘宝花呗付款) - B(淘宝余额付款) = C(站外花呗付款) - D(站外余额付款)。A-B 得到的淘宝付款方式的差异向量,加到站外付款用户 D 上,同样会把他的付款方式从余额变成花呗,说明模型学到的 Embedding 空间中,有一些方向是专门记录付款方式的。

A=[创建交易-淘宝实物担保,花呗付款-淘宝实物担保,创建交易-淘宝实物担保,花呗付款-淘宝实物担保,创建交易-淘宝实物担保,花呗付款-淘宝实物担保,创建交易-淘宝实物担保,花呗付款-淘宝实物担保,创建交易-淘宝实物担保]
B=[创建交易-淘宝实物担保,余额付款-淘宝实物担保,创建交易-淘宝实物担保,余额付款-淘宝实物担保,创建交易-淘宝实物担保,余额付款-淘宝实物担保,创建交易-淘宝实物担保,余额付款-淘宝实物担保,创建交易-淘宝实物担保]
C=[花呗付款-站外即时到账,花呗付款-站外即时到账,花呗付款-站外即时到账,pc端-创建交易,login_登录_app_其他_,花呗付款-站外即时到账,pc端-创建交易]
D=[app端-登录,余额付款-站外即时到账,余额付款-站外即时到账,余额付款-站外即时到账,余额付款-站外即时到账,余额付款-站外即时到账]

金额:A(大金额用户) - B(小金额用户) = C(大金额用户) - D(小金额用户)。召回的 C 也刚好和A一样是8000和10000,看来模型对数字分档的记忆力还是不错的。

A=[\\N,\\N,10000.0,10000.0,10000.0,8000.0,8000.0,8000.0,\\N,8000.0,\\N,\\N,8000.0,\\N,8000.0]
B=[\\N,\\N,10.0,10.0,10.0,10.0,10.0,10.0,\\N,10.0,\\N,\\N,10.0]
C=[\\N,\\N,\\N,8000.0,\\N,\\N,8000.0,\\N,\\N,\\N,\\N,\\N,\\N,10000.0,\\N,10000.0]
D=[\\N,1.0,\\N,1.0,\\N,1.0,1.0,\\N,1.0,\\N,1.0,1.0,\\N,1.0,\\N,\\N]

商品名称:A(打车高频用户) - B(充币高频用户) = C(打车高频用户) - D(充币高频用户)。注意商品名与其他字段不同,需要经过一个 CNN 或 Average 的子网络处理成向量,还能有这样的特性,而且召回了一些与"滴滴快车"相似但不同的"汽车票"、"乘车时间"等,说明网络对文本描述具有一定的泛化能力。

A=["滴滴快车-周师傅","滴滴快车-周师傅",...,"滴滴快车-邵师傅","滴滴快车-邵师傅",...]
B=["腾讯Q币100元qq","腾讯Q币100元qq",...,"腾讯Q币100元qq","腾讯Q币100元qq",...]
C=["滴滴快车-冯师傅","滴滴快车-冯师傅","汽车票**汽车总站(南区","","汽车票**汽车总站(南区)","","联通话费10元快充","","","滴滴快车-亓师傅","滴滴快车-亓师傅","","","0000****-车牌【00*****】乘车时间:2019-04-1914:53:02"]
D=["腾讯1000QQ币1","腾讯QQ币/Q币卡/",...,"腾讯QQ币/Q币卡/","腾讯QQ币/Q币卡/",...]

六、总结

我们提出了一种行为序列深度学习算法 Auto Risk,不需要具体 label 训练,而是基于类似于 Bert 的代理任务预训练思想,从大量的未标注数据中,挖掘上下文关联和标志性特点,生成有用的高层特征,解决了 label 样本不足而 unlabel 样本又难以利用的问题。我们特别针对数据和业务特点设计模型结构,以方便快速训练部署。该方法在我们的实际业务中落地,取得了明显的效果提升;由于训练过程不需要 label,模型结果对其他场景的泛化能力较强;另外,对小样本场景提升明显;序列 Analogy 的实验侧面印证了 Auto Risk 向量空间能够捕捉高层语义。后续,我们将持续这部分工作,扩展到更多类型的数据源和应用场景,并检验其他的代理任务,包括历史积累的多场景 label 作为代理任务等。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 控件 - TextView

1、TextView https://www.bilibili.com/video/BV13y4y1E7pF?p3 1.1、layout_width、layout_height match_parent:表示让当前控件的大小和父布局的大小一样,也就是由父布局来决定当前控件的大小 wrap_content:表示让当前的控件大小能够刚好…

为什么选择Cassandra

cassandra概况 为什么选择Cassandra?cassandra到底有那些令人印象深刻的特点呢?不防我们先来看下cassandra目前的大体概况。 理论扎实,师出名门 cassandra不仅吸收了dynamo论文中的如何做分布式,如何做副本复制,故障…

加速开放混合云技术开发,满足客户新需求,红帽打出这套组合拳!

云计算发展有几十年的历史了,随着科技的进步和发展,云技术慢慢渗透到各行各业,企业上云也不再是新鲜事,据《2020-2026年中国云计算行业市场分析预测及战略咨询研究报告》数据显示:2018年,以IaaS、PaaS和Saa…

系统性能提升利刃 | 缓存技术使用的实践与思考

导读 按照现在流行的互联网分层架构模型,最简单的架构当属Web响应层DB存储层的架构。从最开始的单机混合部署Web和DB,到后来将二者拆分到不同物理机以避免共享机器硬件带来的性能瓶颈,再随着流量的增长,Web应用变为集群部署模式&…

Android 控件 - Button

1、Button 1.1、新建 mybutton 模块 在原有项目基础上新建 mybutton项目 1.2、Button基础 在源码中Button继承TextView,所以TextView有的功能Button基本都有,重复功能不在赘述 1.2.1 设置button背景颜色 当使用background不起作用时&#xff0c…

通过SQL即可让监控分析更简单更高效

1.前言 阿里时序时空数据库TSDB最新推出TSQL,支持标准SQL的语法和函数。用户使用熟悉的SQL,不仅仅查询更简单易用,用户还可以利用SQL强大的功能,实现更加复杂的计算分析。 2. 为什么需要用SQL做时序查询? 2.1 SQL拥…

深度好文 | 战“疫”上云正当时:打开云计算的正确姿势

作者 | 马超责编 | Carol封图 | CSDN 付费下载于视觉中国4月29日,谷歌的母公司Alphabet正式发布了2020年第一季度财报,报告显示,Alphabet比去年同期的363.39亿美元增长13%,不计入汇率变动的影响为同比增长15%;在业绩公…

Windows批处理文件(.bat文件和.cmd文件)简单使用

cmd文件和bat文件的区别,从文件描述中的区别是,cmd文件叫做:Windows命令脚本,bat文件叫:批处理文件,两者都可以使用任意一款文本编辑器进行创建、编辑和修改,只是在cmd中支持的命令要多于bat。 …

AnalyticDB for MySQL:PB级云数仓核心技术和场景解析

2019阿里云峰会上海开发者大会于7月24日盛大开幕,本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货,共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能高级技术专家南仙的精彩演讲&#xff…

UML科普文,一篇文章掌握14种UML图

来源 | 如逆水行舟责编 | Carol封图 | CSDN 付费下载于视觉中国什么是UML?UML是Unified Model Language的缩写,中文是统一建模语言,是由一整套图表组成的标准化建模语言。为什么要用UML?通过使用UML使得在软件开发之前&#xff0c…

企业级数据库新型研发模式——数据管理DMS实践

2019阿里云峰会上海开发者大会于7月24日盛大开幕,本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货,共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能技术专家王天振 (为知)的精彩演讲&…

linux-centos7环境搭建

1、下载centos7 官网地址: http://isoredirect.centos.org/centos/7/isos/x86_64/ 阿里云: http://mirrors.aliyun.com/centos/ 以下针对各个版本的ISO镜像文件,进行一一说明: CentOS-7-x86_64-DVD-1708.iso 标准安装版&#x…

揭秘!机器人和你对话时在想什么?

阿里妹导读:为什么聊天机器人越来越普及?聊天机器人不仅可以节省时间,提升效率,还能一天24小时提供服务,更是可以减少误差。聊天机器人背后的问题原理是什么?效率如何提升?就是今天我们要了解的…

阿里云与A站在一起后,悄悄干了件大事

八月盛夏,“AcFun弹幕视频网站”(简称“A站”)的视频服务器全面迁移上阿里云(此处应有掌声)! A站去年与阿里云达成此项合作。在迁移过程中,阿里云提供专业技术解决方案团队,为A站建立…

科大讯飞营收破百亿,员工涨薪27%,羡慕这个AI“老大哥”​了!

科大讯飞,中国AI公司“老大哥”,交出2019年成绩单。营收达到100.79亿,首次破百亿;净利润同比增长51.12%,达到8.19亿,日均盈利224万元,创下历史最佳业绩。与此同时,5大厂2020年应届生…

Knative Serving 之路由管理和 Ingress

Knative 默认会为每一个 Service 生成一个域名,并且 Istio Gateway 要根据域名判断当前的请求应该转发给哪个 Knative Service。Knative 默认使用的主域名是 example.com,这个域名是不能作为线上服务的。本文我首先介绍一下如何修改 默认主域名&#xff…

linux-centos7 关机命令、系统目录结构介绍

1、关机命令 关机指令 shutdown; sync # 将数据由内存同步到硬盘中,一般关机前需要同步一下,防止数据丢失shutdown # 关机指令,会在一定时间后关机,我试的是一分钟后关机shutdown -h 10 # 十分钟后关机 shutdown -h 10 # 十分…

SprinBoot2.X 集成 Flowable6.6 工作流引擎

上一篇:SpringBoot2.x Flowable 6.4.2 开源项目 码云开源地址:https://gitee.com/lwj/flow GitHub开源地址:https://github.com/ecnice/flow flowable学习 可以入群:633168411 说明:此项目是我师傅为了帮助更多小伙伴们入门工作流…

OceanBase高可用实践

背景 高可用是构建分布式系统的基石。一方面,出于成本考虑, 分布式系统往往采取比较廉价的硬件,其可靠性相对于小型机、专有硬件有很大的不足, 而分布式系统的规模一般比较大,假如硬件的可靠性只有三个9(99.9%)&#…

咦,拆分个字符串都这么讲究?

来源 | 沉默王二封图 | CSDN 付费下载于视觉中国提到拆分字符串,我猜你十有八九会撂下一句狠话,“这有什么难的,直接上 String 类的 split() 方法不就拉到了!”假如你真的这么觉得,那可要注意了,事情远没这…