精华内容
下载资源
问答
  • 在任何环境下都能适应
    千次阅读 多人点赞
    2021-05-22 08:52:44

    导读

    在迁移学习中, 当源域和目标的数据分布不同 ,但两个任务相同时,这种特殊的迁移学习叫做域适应 (Domain Adaptation,DA )。因为其任务相同,域适应属于一种直推式迁移学习。在计算机视觉中,域适应是一个常见要求,因为带有标注的数据集很容易取得,但是获得的数据集和我们最终应用的数据集来源的域往往是不同的。那么解决这类问题的思路是什么呢?请看 AI 前线翻译的这篇文章,希望能有所启迪。

    前言

    过去十年来,计算机视觉领域如盛壮之时的骐骥,一日而驰千里。这一进展主要归功于卷积神经网络不可否认的有效性。如果使用高质量、带注释的训练数据进行训练,卷积神经网络(Convolutional Neural Networks,CNN)可以进行非常精确的预测。例如,在分类设置中,你通常会使用一种标准的网络架构(如 ResNet、VGG 等),并使用你的数据集对其进行训练。这可能会得到非常好的性能。

    另一方面,如果你没有为特定问题提供手动注释的大型数据集,卷积神经网络还允许利用已经通过迁移学习训练一个类似问题的网络的其他数据集。在这种情况下,你可以使用一个在大型数据集上预训练的网络,并使用你自己的带注释的小型数据集对其一些上层进行调优。

    这两种方法,都假定你的训练数据(无论大小)都代表了基本分布。但是,如果测试时的输入与训练数据有显著差异,那么模型的性能可能不会很好。举个例子,假设你是一名自动驾驶汽车工程师,你想要分割汽车摄像头拍摄的图像,以便了解前方的情况(如建筑物、树木、其他汽车、行人、交通信号灯等)。NYC 数据集有很好的人工生成的注释,你可以使用这些注释来训练一个大型网络。你在曼哈顿的街道上测试你的自动驾驶汽车,一切似乎都很顺利。然后你在巴黎街道测试同样的系统,突然情况变得非常糟糕。这辆汽车再也无法探测到交通信号灯,它看到的汽车也非常不一样(因为巴黎的出租车没有黄色的),街道也不再那么笔直了。

    你的模型在这些场景中表现不佳的原因是问题域发生了变化。在这种特殊情况下,输入数据的域发生了变化,而任务域(标签)保持不变。在其他情况下,你可能希望使用来自相同域的数据(针对相同的基本分布绘制)来完成新任务。同样,输入域和任务域可以同时发生变化。在这些情况下,域适应 就会来拯救你。域适应是机器学习的一个子学科,它处理的 场景是,在不同(但相关)的目标分布的背景下,使用在源分布上训练的模型。通常,域适应使用一个或多个源域中的标记数据来解决目标域中的新任务。因此,源域和目标域之间的关联程度通常决定了适应的成功程度。

    域适应有多种方法。在“浅层(不是深度)”域适应中,通常使用两种方法:重新加权源样本,在重新加权样本上进行训练,并尝试 学习共享空间来匹配 源和目标数据集的 分布。虽然这些技术也可以应用于深度学习,深度神经网络 学习的深度特征,通常会产生更多的可转移表示(一般来说,在较底层中具有高度可转移的特征,而在较高层中可转移性就急剧下降了,请参阅 Donahue 等人的论文 DeCAF: A Deep Convolutional Activation Featurefor Generic Visual Recognition(《DecAF:通用视觉识别的深度卷积激活特征》))。在 深度域适应 中,我们尝试使用深度神经网络的这一特性。

    域适应类别

    以下的总结主要是基于 Wang 等人的这篇综述论文:Deep Visual Domain Adaptation: A Survey(《深度视觉域适应研究综述》),以及 Wilson 等人的这篇评论文章:Unsupervised Deep Domain Adaptation(《无监督深度域适应》)。在这项工作中,作者区分不同类型的域适应,取决于任务的复杂性、可用的标记 / 未标记数据的数量以及输入特征空间的差异。它们特别定义了域适应问题,即任务空间相同,区别仅在与输入域的散度(divergence)。根据这个定义,域适应可以是同构(homogeneous)的(输入特征空间相同,但数据分布不同),也可以是异构(heterogeneous)的(特征空间及其维度可能不同)。

    域适应也可以在一个步骤(一步域适应(one-step domain adaptation))中发生,或者通过多个步骤发生,遍历过程中的一个或多个域(多步域适应(multi-step domain adaptation))。在本文中,我们将只讨论一步域适应,因为这是最常见的域适应类型。

    根据你从目标域获得的数据,域适应可以进一步分类为 监督(supervised)域适应(你确实标记了来自目标域的数据,尽管这些数据的数量,对于训练整个模型来说还是太小了)、半监督(semi-supervised)域适应(你既有已标记的数据,也有未标记的数据)、无监督(unsupervised)域适应(你没有来自目标域的任何标记数据)。

    任务相关性

    我们如何确定在源域中训练的模型是否可以适应我们的目标域呢?事实证明,这个问题并不容易回答,任务相关性仍然是个活跃的研究课题。如果两个任务都使用相同的特征进行决策,我们就可以将它们定义为相似的任务。另一种可能性是,如果两个任务的参数向量(即分类边界)很接近,则将它们定义为相似的(参见 Xue 等人的论文 Multi-Task Learning for Classification with Dirichlet Process Priors(《基于 Dirichlet 过程先验的分类多任务学习》))。另一方面,Ben-David 等人提出,如果两个任务的数据都可以通过一组变换 F 从固定的概率分布中生成,则这两个任务是 F 相关的(参见 Exploiting Task Relatedness for Multiple Task Learning(《利用任务相关性进行多任务学习》))。

    尽管有这些理论上的考虑,但在实践中,可能有必要尝试在自己的数据集上进行域适应,看看是否可以通过使用源任务的模型为目标任务获得一些好处。通常,任务相关性可以通过简单的推理来确定,例如来自不同视角或不同光照条件的图像,或者在医学领域中来自不同设备的图像等。

    一步域适应技术及其应用

    一步域适应有三种基本技术:

    • 基于散度的域适应
    • 基于对抗的域适应,使用生成模型(生成对抗网络,GAN)或域混淆损失函数
    • 基于重建的域适应,使用堆叠式自编码器(stacked autoencoders,SAE)或生成对抗网络。

    基于散度的域适应

    基于散度的域适应,通过 最小化源和目标数据分布之间的散度准则来实现,从而实现 域不变的特征表示。如果我们找到这样一种特征表示,分类器将能够在这两个域上执行得同样好。当然,这是假设存在这样一种表示,而这种表示又假设任务以某种方式相关。

    最常用的四种散度度量是:最大均值差异(Maximum Mean Discrepancy,MMD)、相关对齐(Correlation Alignment,CORAL)、对比域差异(Contrastive Domain Discrepancy,CCD)和 Wasserstein 度量。

    MMD 是一种假设检验,将两个样本映射到一个再生核希尔伯特空间(Reproducing Kernel Hilbert Space,RKHS),然后通过比较特征的均值来检验这两个样本是否属于同一分布。如果均值不同,则分布也可能不同。这通常是通过使用核嵌入技巧并使用高斯核比较样本实现的。这里的直觉是,如果两个分布相同,来自每个分布的样本你之间的平均下你公司性应该等于来自两个分布的混合样本之间的平均相似性。在域适应中使用 MMD 的一个例子,可参见 Rozantsev 等人的论文 Beyond Sharing Weights for Deep Domain Adaptation(《除共享权重外的深度域适应》)。在这篇论文中,双流架构(two-stream architecture)使用的权重是不共享的,但通过使用分类、正规化和域差异(MMD)损失的组合导致相似的特征表示,如下图所示。

    在这里插入图片描述

    因此,设置可以是监督的、半监督的、甚至是无监督的(在目标域中没有分类损失函数)。

    CORAL 类似于 MMD,但它试图调整源分布和目标分布的二阶统计(相关性),而不是使用线性变换的均值。在 Sun 等人撰写的论文 Deep CORAL: Correlation Alignment for DeepDomain Adaptation(《Deep CORAL:深度域适应的相关对齐》)中,通过使用源和目标协方差矩阵之间的 Frobenius 范数构造可微分的 CORAL 损失函数,在深度学习的环境中使用 CORAL。

    CCD 也是基于 MMD 的,但也通过查看条件分布来利用标签分布。这就确保了联合域特征仍然保留 w.r.t 标签的预测性。最小化 CCD 可最大限度地减少类内差异,同时使类间差异最大化。这需要源域标签和目标域标签。为摆脱这种约束,Kang 等人撰写的论文 Contrastive Adaptation Network for Unsupervised Domain Adaptation(无监督域适应的对比适应网络)提出,在一个联合优化目标标签和特征表示的迭代过程中,使用聚类来估计损失的目标标签。在此基础上,通过聚类找到目标标签,从而使 CCD 最小化以适应这些特征。

    最后,源域和目标域中的特征和标签分布可以通过考虑最优传输问题及其对应的距离(即 Wasserstein 距离)来对齐。这是在 Damodaran 等人的论文 DeepJDOT: Deep Joint Distribution OptimalTransport for Unsupervised Domain Adaptation (《DeepJDOT:用于无监督域适应的深度联合分布优化传输》)中提出的。作者提出通过优化传输来使联合深度特征表示与标签之间的差异最小化。

    基于对抗的域适应

    这种技术是尝试通过对抗训练来实现域适应。

    一种方法是使用 生成对抗网络 来生成与源域相关的合成目标数据(例如通过保留标签)。然后将这些合成数据用来训练目标模型。

    CoGAN 模型 尝试通过对源分布和目标分布使用两个生成器 / 判别器对来实现这一点。对生成器和判别器的权重进行共享,来学习域不变的特征空间。通过这种方式,可以生成标记的目标哦数据,这些数据可以进一步用于诸如分类等任务中。

    在这里插入图片描述
    在另一个装置中,在 Yoo 等人的论文 Pixel-Level Domain Transfer(《像素级域迁移》)中,作者提出,尝试通过使用两个判别器来学习 源 / 目标转换器网络:一个用于确保目标数据是真实的,另一个用于保持源域和目标域之间的相关性。因此,生成器以源数据为条件。这种方法只需要目标域中未标记的数据。

    除了当前任务的分类损失函数之外,如果使用所谓的域混淆损失函数,我们还可以完全摆脱生成器,一次性完成域适应。域混淆损失类似于生成对抗网络中的判别器,因为它试图匹配源域和目标域的分布,以“混淆”高级分类层。也许这种网络最著名的例子是 Ganin 等人提出的 域对抗神经网络(Domain-Adversarial Neural Network,DANN)。该网络由两个损失函数组成,即分类损失函数和域混淆损失函数。它包含一个 梯度反转层(gradient reversal layer)来匹配特征分布。通过最小化源样本的分类损失函数和所有样本的域混淆损失函数(同时最大化特征提取的域混淆损失函数),这就确保了对分类器而言,这些样本是无法区分的。

    在这里插入图片描述

    基于重建的域适应

    这种方法使用一个 辅助重建任务 为每个月创建共享表示。例如,深度重建分类网络( Deep Reconstruction Classification Network,DRCN)试图同时解决这两个任务:
    (i) 源数据的分类
    (ii) 未标记目标数据的重建

    这确保了网络不仅能够学习正确识别目标数据,而且还能够保存目标数据的信息。在这篇论文 Deep Reconstruction-Classification Networksfor Unsupervised Domain Adaptation(《用于无监督域适应的深度重建分类网络》)中,作者还提到重建管道学习将源图像转换为类似于目标数据集的图像,这表明两者都学习了一个共同的表示方式。
    在这里插入图片描述
    另一种可能性是使用所谓的 循环 GAN。循环 GAN 的灵感来自于机器翻译中的双重学习概念。这个概念是同时训练两个相反的语言翻译器(A-B,B-A)。循环中的反馈信号由相应的语言模型和共同的 BLEU 分数组成。使用 im2im 框架也可以对图像进行同样的处理。在这篇论文 Unpaired Image-to-Image Translationusing Cycle-Consistent Adversarial Networks(《使用循环一致对抗网络的不成对图像到图像的转换》)中,作者提出了在不使用任何成对图像样本的情况下,如何学习从一个图像域到另一个图像域的映射。这是通过同时训练分别在两个域中生成图像的两个 GAN 来实现的。为了确保一致性,引入了 循环一致性损失函数(cycle consistency loss)。这确保了从一个域转换到另一个域,然后再转换回来,得到的图像域输入的图像大致相同。因此,两个成对的网络的完全损失函数是两个判别器的 GAN 损失函数和循环一致性损失函数的总和。

    最后,通过将它们的输入调整为来自另一个域的图像上,生成对抗网络还可以用于编码器 - 解码器设置中。在 Isola 等人的论文 Image-to-Image Translation with Conditional Adversarial Networks(《基于条件对抗网络的图像到图像转换》)中,作者提出,条件生成对抗网络(conditional GAN)是通过调节输入上的判别器和生成器的输出,来将图像从一个域转换到另一个域。这可以通过使用简单的编码器 - 解码器架构来实现,也可以通过使用带有跳跃连接(skip-connections)的 U-Net 架构来实现。

    在这里插入图片描述

    结论

    深度域适应允许我们将源任务上的特定深度神经网络锁学的只是迁移到新的相关目标任务上。这种方法已经成功地应用于图像分类、风格转换等任务。从某种意义上说,就特定的计算机视觉任务所需的训练数据量而言,深度域适应使我们更接近人类水平的表现。因此,我认为这一领域的进展对整个计算机视觉领域至关重要,我希望它最终能引导我们在视觉任务中能够进行有效而简单的知识重用。

    更多相关内容
  • 阿里面试失败后,一气之我图解了Java中18把锁

    万次阅读 多人点赞 2021-06-17 23:21:47
    举个生活中的例子,假设厕所只有一个坑位了,悲观锁上厕所会第一时间把门反锁上,这样其他人上厕所只能门外等候,这种状态就是「阻塞」了。 回到代码世界中,一个共享数据加了悲观锁,那线程每次想操作这个数据前...

     号外号外!《死磕 Java 并发编程》系列连载中,大家可以关注一波:

    「死磕 Java 并发编程04」说说Java Atomic 原子类的实现原理

    「死磕 Java 并发编程03」阿里二面,面试官:说说 Java CAS 原理?

    「死磕 Java 并发编程02」面试官:说说什么是 Java 内存模型(JMM)?

    「死磕 Java 并发编程01」10张图告诉你Java并发多线程那些破事

     

    目录

    乐观锁和悲观锁

    独占锁和共享锁

    互斥锁和读写锁

    公平锁和非公平锁

    可重入锁

    自旋锁

    分段锁

    锁升级(无锁|偏向锁|轻量级锁|重量级锁)

    锁优化技术(锁粗化、锁消除)

    一张图总结:


     

    乐观锁和悲观锁

    悲观锁

    悲观锁对应于生活中悲观的人,悲观的人总是想着事情往坏的方向发展。

    举个生活中的例子,假设厕所只有一个坑位了,悲观锁上厕所会第一时间把门反锁上,这样其他人上厕所只能在门外等候,这种状态就是「阻塞」了。

    回到代码世界中,一个共享数据加了悲观锁,那线程每次想操作这个数据前都会假设其他线程也可能会操作这个数据,所以每次操作前都会上锁,这样其他线程想操作这个数据拿不到锁只能阻塞了。

    20210606232504-2021-06-06-23-25-04

    在 Java 语言中 synchronizedReentrantLock等就是典型的悲观锁,还有一些使用了 synchronized 关键字的容器类如 HashTable 等也是悲观锁的应用。

    乐观锁

    乐观锁 对应于生活中乐观的人,乐观的人总是想着事情往好的方向发展。

    举个生活中的例子,假设厕所只有一个坑位了,乐观锁认为:这荒郊野外的,又没有什么人,不会有人抢我坑位的,每次关门上锁多浪费时间,还是不加锁好了。你看乐观锁就是天生乐观!

    回到代码世界中,乐观锁操作数据时不会上锁,在更新的时候会判断一下在此期间是否有其他线程去更新这个数据。

    20210606232434-2021-06-06-23-24-35

    乐观锁可以使用版本号机制CAS算法实现。在 Java 语言中 java.util.concurrent.atomic包下的原子类就是使用CAS 乐观锁实现的。

    两种锁的使用场景

    悲观锁和乐观锁没有孰优孰劣,有其各自适应的场景。

    乐观锁适用于写比较少(冲突比较小)的场景,因为不用上锁、释放锁,省去了锁的开销,从而提升了吞吐量。

    如果是写多读少的场景,即冲突比较严重,线程间竞争激励,使用乐观锁就是导致线程不断进行重试,这样可能还降低了性能,这种场景下使用悲观锁就比较合适。

    独占锁和共享锁

    独占锁

    独占锁是指锁一次只能被一个线程所持有。如果一个线程对数据加上排他锁后,那么其他线程不能再对该数据加任何类型的锁。获得独占锁的线程即能读数据又能修改数据。

    20210606232544-2021-06-06-23-25-45

    JDK中的synchronizedjava.util.concurrent(JUC)包中Lock的实现类就是独占锁。

    共享锁

    共享锁是指锁可被多个线程所持有。如果一个线程对数据加上共享锁后,那么其他线程只能对数据再加共享锁,不能加独占锁。获得共享锁的线程只能读数据,不能修改数据。

    20210606232612-2021-06-06-23-26-13

    在 JDK 中 ReentrantReadWriteLock 就是一种共享锁。

    互斥锁和读写锁

    互斥锁

    互斥锁是独占锁的一种常规实现,是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。

    20210606232634-2021-06-06-23-26-35

    互斥锁一次只能一个线程拥有互斥锁,其他线程只有等待。

    读写锁

    读写锁是共享锁的一种具体实现。读写锁管理一组锁,一个是只读的锁,一个是写锁。

    读锁可以在没有写锁的时候被多个线程同时持有,而写锁是独占的。写锁的优先级要高于读锁,一个获得了读锁的线程必须能看到前一个释放的写锁所更新的内容。

    读写锁相比于互斥锁并发程度更高,每次只有一个写线程,但是同时可以有多个线程并发读。

    20210606232658-2021-06-06-23-26-59

    在 JDK 中定义了一个读写锁的接口:ReadWriteLock

    public interface ReadWriteLock {
        /**
         * 获取读锁
         */
        Lock readLock();
    
        /**
         * 获取写锁
         */
        Lock writeLock();
    }
    

    ReentrantReadWriteLock 实现了ReadWriteLock接口,具体实现这里不展开,后续会深入源码解析。

    公平锁和非公平锁

    公平锁

    公平锁是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买,后来的人在队尾排着,这是公平的。

    20210606232716-2021-06-06-23-27-17

    在 java 中可以通过构造函数初始化公平锁

    /**
    * 创建一个可重入锁,true 表示公平锁,false 表示非公平锁。默认非公平锁
    */
    Lock lock = new ReentrantLock(true);
    

    非公平锁

    非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发环境下,有可能造成优先级翻转,或者饥饿的状态(某个线程一直得不到锁)。

    20210606232737-2021-06-06-23-27-38

    在 java 中 synchronized 关键字是非公平锁,ReentrantLock默认也是非公平锁。

    /**
    * 创建一个可重入锁,true 表示公平锁,false 表示非公平锁。默认非公平锁
    */
    Lock lock = new ReentrantLock(false);
    

    可重入锁

    可重入锁又称之为递归锁,是指同一个线程在外层方法获取了锁,在进入内层方法会自动获取锁。

    20210606232755-2021-06-06-23-27-56

    对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁。对于Synchronized而言,也是一个可重入锁。

    敲黑板:可重入锁的一个好处是可一定程度避免死锁。

    以 synchronized 为例,看一下下面的代码:

    public synchronized void mehtodA() throws Exception{
     // Do some magic tings
     mehtodB();
    }
    
    public synchronized void mehtodB() throws Exception{
     // Do some magic tings
    }
    

    上面的代码中 methodA 调用 methodB,如果一个线程调用methodA 已经获取了锁再去调用 methodB 就不需要再次获取锁了,这就是可重入锁的特性。如果不是可重入锁的话,mehtodB 可能不会被当前线程执行,可能造成死锁。

    自旋锁

    自旋锁是指线程在没有获得锁时不是被直接挂起,而是执行一个忙循环,这个忙循环就是所谓的自旋。

    20210606232809-2021-06-06-23-28-09

    自旋锁的目的是为了减少线程被挂起的几率,因为线程的挂起和唤醒也都是耗资源的操作。

    如果锁被另一个线程占用的时间比较长,即使自旋了之后当前线程还是会被挂起,忙循环就会变成浪费系统资源的操作,反而降低了整体性能。因此自旋锁是不适应锁占用时间长的并发情况的。

    在 Java 中,AtomicInteger 类有自旋的操作,我们看一下代码:

    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!compareAndSwapInt(o, offset, v, v + delta));
        return v;
    }
    

    CAS 操作如果失败就会一直循环获取当前 value 值然后重试。

    另外自适应自旋锁也需要了解一下。

    在JDK1.6又引入了自适应自旋,这个就比较智能了,自旋时间不再固定,由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定。如果虚拟机认为这次自旋也很有可能再次成功那就会次序较多的时间,如果自旋很少成功,那以后可能就直接省略掉自旋过程,避免浪费处理器资源。

    分段锁

    分段锁 是一种锁的设计,并不是具体的一种锁。

    分段锁设计目的是将锁的粒度进一步细化,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

    20210606232830-2021-06-06-23-28-31

    在 Java 语言中 CurrentHashMap 底层就用了分段锁,使用Segment,就可以进行并发使用了。

    锁升级(无锁|偏向锁|轻量级锁|重量级锁)

    JDK1.6 为了提升性能减少获得锁和释放锁所带来的消耗,引入了4种锁的状态:无锁偏向锁轻量级锁重量级锁,它会随着多线程的竞争情况逐渐升级,但不能降级。

    无锁

    无锁状态其实就是上面讲的乐观锁,这里不再赘述。

    偏向锁

    Java偏向锁(Biased Locking)是指它会偏向于第一个访问锁的线程,如果在运行过程中,只有一个线程访问加锁的资源,不存在多线程竞争的情况,那么线程是不需要重复获取锁的,这种情况下,就会给线程加一个偏向锁。

    偏向锁的实现是通过控制对象Mark Word的标志位来实现的,如果当前是可偏向状态,需要进一步判断对象头存储的线程 ID 是否与当前线程 ID 一致,如果一致直接进入。

    轻量级锁

    当线程竞争变得比较激烈时,偏向锁就会升级为轻量级锁,轻量级锁认为虽然竞争是存在的,但是理想情况下竞争的程度很低,通过自旋方式等待上一个线程释放锁。

    重量级锁

    如果线程并发进一步加剧,线程的自旋超过了一定次数,或者一个线程持有锁,一个线程在自旋,又来了第三个线程访问时(反正就是竞争继续加大了),轻量级锁就会膨胀为重量级锁,重量级锁会使除了此时拥有锁的线程以外的线程都阻塞。

    升级到重量级锁其实就是互斥锁了,一个线程拿到锁,其余线程都会处于阻塞等待状态。

    在 Java 中,synchronized 关键字内部实现原理就是锁升级的过程:无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁。这一过程在后续讲解 synchronized 关键字的原理时会详细介绍。

    锁优化技术(锁粗化、锁消除)

    锁粗化

    锁粗化就是将多个同步块的数量减少,并将单个同步块的作用范围扩大,本质上就是将多次上锁、解锁的请求合并为一次同步请求。

    举个例子,一个循环体中有一个代码同步块,每次循环都会执行加锁解锁操作。

    private static final Object LOCK = new Object();
    
    for(int i = 0;i < 100; i++) {
        synchronized(LOCK){
            // do some magic things
        }
    }
    

    经过锁粗化后就变成下面这个样子了:

     synchronized(LOCK){
         for(int i = 0;i < 100; i++) {
            // do some magic things
        }
    }
    

    锁消除

    锁消除是指虚拟机编译器在运行时检测到了共享数据没有竞争的锁,从而将这些锁进行消除。

    举个例子让大家更好理解。

    public String test(String s1, String s2){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(s1);
        stringBuffer.append(s2);
        return stringBuffer.toString();
    }
    

    上面代码中有一个 test 方法,主要作用是将字符串 s1 和字符串 s2 串联起来。

    test 方法中三个变量s1, s2, stringBuffer, 它们都是局部变量,局部变量是在栈上的,栈是线程私有的,所以就算有多个线程访问 test 方法也是线程安全的。

    我们都知道 StringBuffer 是线程安全的类,append 方法是同步方法,但是 test 方法本来就是线程安全的,为了提升效率,虚拟机帮我们消除了这些同步锁,这个过程就被称为锁消除

    StringBuffer.class
    
    // append 是同步方法
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    

    一张图总结:

    Java 并发编程的知识非常多,同时也是 Java 面试的高频考点,面试官必问的,需要学习 Java 并发编程其他知识的小伙伴可以去下载『阿里师兄总结的Java知识笔记 总共 283 页,超级详细』。

    前面讲了 Java 语言中各种各种的锁,最后再通过六个问题统一总结一下:

    Java中那些眼花缭乱的锁-2021-06-16-23-19-40

    大家学会了吗?收藏等于白嫖,点赞才是真爱,雷小帅感谢大家~~~

     

    作者:雷小帅

    推荐一个Github 开源项目,『Java八股文』Java面试套路,Java进阶学习,打破内卷拿大厂Offer,升职加薪!

    作者简介:

    ☕读过几年书:华中科技大学硕士毕业;
    😂浪过几个大厂:华为、网易、百度……
    😘一直坚信技术能改变世界,愿保持初心,加油技术人!

    微信搜索公众号【爱笑的架构师】,关注这个对技术有追求且有趣的打工人。

    展开全文
  • GCC编译器简明教程(LinuxC语言开发环境的搭建)

    万次阅读 多人点赞 2018-09-13 21:49:59
    GCC编译器简明教程(LinuxC语言开发环境的搭建) 市面上常见的Linux是发行版本,典型的Linux发行版包含了Linux内核、桌面环境(例如GNOME、KDE、Unity等)和各种常用的必备工具(例如Shell、GCC、VIM、Firefox...

    GCC编译器简明教程(Linux下C语言开发环境的搭建)

    市面上常见的Linux都是发行版本,典型的Linux发行版包含了Linux内核、桌面环境(例如GNOMEKDEUnity等)和各种常用的必备工具(例如ShellGCCVIMFirefox等),国内使用较多的是CentOSUbuntu(乌班图)、DebianRedhat等。

    Linux主要应用于各种服务器(例如网站服务器、数据库服务器、DNS服务器、邮件服务器、路由器、负载均衡集群等),而不是我们常见的个人电脑。Linux是服务器操作系统的绝对霸主,占据了80%以上的份额,在未来的服务器领域,Linux是大势所趋。这其中,又以CentOSUbuntu为主,CentOS占有压倒性的优势。服务器操作系统80%以上的市场份额被Linux占据,而Linux 80%以上的份额又被CentOS占据。本教程以CentOS为例来讲述如何编译C程序。

    服务器上的Linux是不安装图形界面的,只能在控制台模式下使用,以尽量节省服务器资源。而我们在学习过程中使用的Linux是带图形界面的,以满足初学者的需求,降低学习成本。

    Linux下我们仍然可以使用带界面的、傻瓜式的IDE,例如CodeLiteCLion(收费)、Code::BlocksNetbeansEclipse CDT等。微软的Visual Studio也支持Linux了,在Windows下用惯了Visual Studio的用户也可以毫无障碍地迁移到Linux平台。

    但是作为初学者,我建议大家在命令行模式下编译C语言程序,这样能够了解生成一个可执行程序的详细步骤,以及编译命令的各种设置选项,为以后的LinuxC/C++ 开发打好坚实的基础。

    Gedit 编辑器

    Linux下,很多程序员都推崇使用VimEmacs等命令行模式的编辑器,它们功能强大,逼格够高,不管有没有桌面环境都能使用,是LinuxC/C++程序员必备的神器。但是VimEmacs并不容易上手,使用者需要记忆很多命令和快捷键,熟练才能生巧,所以需要一段时间的学习和适应,这会增加初学者的学习成本,所以这里不推荐大家使用。

    CentOS下有一款自带的图形界面编辑器,叫做GeditGedit是一款简单实用的文本编辑器,界面优雅,支持语法高亮,比Vim容易上手,它和Windows下的编辑器没有什么两样。本教程将Gedit作为C语言代码的编辑器。

    如果你使用的是其它的Linux发行版,可能没有默认安装Gedit,这个时候就得自己安装,具体步骤为:

    $ sudo apt-add-repository ppa:ubuntu-on-rails/ppa   #添加ubuntu的软件源

    $ sudo apt-get update   #更新软件列表

    $ sudo apt-get install gedit-gmate   #安装

    首先,在我们自己的用户目录下新建一个名为demo的文件夹。这个文件夹专门用来存放与C语言相关的文件,例如源文件、目标文件、可执行文件等,它专供我们学习使用。

    用户目录有时候也叫home文件夹或者主文件夹,它的路径是/home/username,其中 username 就是我们登录Linux时使用的用户名。Linux 会在 home 目录下为每一个登录的用户创建一个文件夹,专门用来存放该用户使用到的配置文件、文本文档、图片、可执行程序等,以和其他用户区分开来。

    接下来需要创建一个空白的 main.c 源文件。main.c 其实就是一个纯文本文件,并没有任何特殊格式,但是Linux不像 Windows,可以在右键菜单中新建文本文档,Linux 必须使用命令来创建,如下所示:

    $ cd demo  #进入 demo 目录,这是源文件所在的目录

    $ touch main.c  #使用 touch 命令创建一个名为 main.c 的空文件

    $ gedit main.c  #使用 gedit 命令编辑 main.c

    这样就完成了源文件的创建,并能够使用Gedit编辑源文件了。

    Gedit 中输入下面的C语言代码:

    #include <stdio.h>

    int main()

    {

        puts("C语言中文网");

        return 0;

    }

    输入完成后的效果如下图所示:

    http://c.biancheng.net/cpp/uploads/allimg/171008/1-1G00Q10053154.jpg

    Ctrl+S保存文件,就完成了源代码的编辑工作。此时需要关闭Gedit的窗口,$ gedit main.c命令才算执行结束,才能在控制台继续输入其它命令。

    下图演示了在控制台上的实际效果:

    http://c.biancheng.net/cpp/uploads/allimg/171009/1-1G00910510UJ.jpg

    注意,在CentOS下,使用touch命令创建完main.c后,进入demo目录,在右键菜单中也可以使用Gedit 打开main.c,如下图所示:

    http://c.biancheng.net/cpp/uploads/allimg/171008/1-1G00Q104301H.jpg

    GCC 编译器

    Linux下使用最广泛的 C/C++ 编译器是 GCC,大多数的Linux发行版本都默认安装,不管是开发人员还是初学者,一般都将 GCC 作为Linux下首选的编译工具。本教程也毫不犹豫地使用 GCC 来编译C语言程序。GCC 仅仅是一个编译器,没有界面,必须在命令行模式下使用。通过gcc命令就可以将源文件编译成可执行文件。

    1) 生成可执行程序

    最简单的生成可执行文件的写法为:

    $ cd demo  #进入源文件所在的目录

    $ gcc main.c  # gcc 命令后面紧跟源文件名

    打开 demo 目录,会看到多了一个名为 a.out 的文件,这就是最终生成的可执行文件,如下图所示:

    http://c.biancheng.net/cpp/uploads/allimg/171008/1-1G00Q64J2C5.jpg

    这样就一次性完成了编译和链接的全部过程,非常方便。

    注意:不像 WindowsLinux 不以文件后缀来区分可执行文件,Linux 下的可执行文件后缀理论上可以是任意的,这里的.out只是用来表明它是 GCC 的输出文件。不管源文件的名字是什么,GCC 生成的可执行文件的默认名字始终是a.out

    如果不想使用默认的文件名,那么可以通过-o选项来自定义文件名,例如:

    $ gcc main.c -o main.out

    这样生成的可执行程序的名字就是main.out

    因为Linux下可执行文件的后缀仅仅是一种形式上的,所以可执行文件也可以不带后缀,例如:

    $ gcc main.c -o main

    这样生成的可执行程序的名字就是main

    通过-o选项也可以将可执行文件输出到其他目录,并不一定非得在当前目录下,例如:

    $ gcc main.c -o ./out/main.out

    或者

    $ gcc main.c -o out/main.out

    表示将可执行文件输出到当前目录下的out目录,并命名为main.out./表示当前目录,如果不写,默认也是当前目录。

    注意:out 目录必须存在,如果不存在,gcc 命令不会自动创建,而是抛出一个错误。

    2) 运行可执行程序

    上面我们生成了可执行程序,那么该如何运行它呢?很简单,在控制台中输入程序的名字就可以,如下所示:

    $ ./a.out

    ./表示当前目录,整条命令的意思是运行当前目录下的 a.out 程序。如果不写./Linux 会到系统路径下查找 a.out,而系统路径下显然不存在这个程序,所以会运行失败。

    所谓系统路径,就是环境变量指定的路径,我们可以通过修改环境变量添加自己的路径,或者删除某个路径。很多时候,一条Linux命令对应一个可执行程序,如果执行命令时没有指明路径,那么就会到系统路径下查找对应的程序。

    输入完上面的命令,按下回车键,程序就开始执行了,它会将输出结果直接显示在控制台上,如下所示:

    $ cd demo

    $ gcc main.c

    $ ./a.out

    C语言中文网

    $

    下图演示了在控制台上的实际效果:

    http://c.biancheng.net/cpp/uploads/allimg/171009/1-1G00910095aA.jpg

    如果程序在其它目录下,运行程序时还要带上目录的名字,例如:

    $ ./out/main.out

    或者

    $ out/main.out

    这个时候加不加./都一样,Linux 能够识别出out是一个目录,而不是一个命令,它默认会在当前路径下查找该目录,而不是去系统路径下查找,所以不加./也不会出错。

    注意,如果程序没有执行权限,可以使用sudo命令来增加权限,例如:

    $ sudo chmod 777 a.out

    完整的演示

    为了让读者有一个更加全面的认识,我们不妨将上面两部分的内容连接起来,完整的演示一下从编辑源文件到运行可执行程序的全过程:

    $ cd demo  #进入源文件所在目录

    $ touch main.c  #新建空白的源文件

    $ gedit main.c  #编辑源文件

    $ gcc main.c  #生成可执行程序

    $ ./a.out  #运行可执行程序

    C语言中文网

    $   #继续等待输入其它命令

    下图是在控制台上的实际效果:

    http://c.biancheng.net/cpp/uploads/allimg/171009/1-1G009111F9448.jpg

    分步骤编译

    上面讲解的是通过gcc命令一次性完成编译和链接的整个过程,这样最方便,大家在学习C语言的过程中一般都这么做。实际上,gcc命令也可以将编译和链接分开,每次只完成一项任务。

    1) 编译(Compile

    将源文件编译成目标文件需要使用-c选项,例如:

    gcc -c main.c

    就将 main.c 编译为 main.o。打开 demo 目录,就会看到 main.o

    http://c.biancheng.net/cpp/uploads/allimg/171009/1-1G009130633I6.jpg

    对于微软编译器(内嵌在 Visual C++ 或者 Visual Studio 中),目标文件的后缀为.obj;对于 GCC 编译器,目标文件的后缀为.o

    一个源文件会生成一个目标文件,多个源文件会生成多个目标文件,源文件数目和目标文件数目是一样的。通常情况下,默认的目标文件名字和源文件名字是一样的。

    如果希望自定义目标文件的名字,那么可以使用-o选项,例如:

    gcc -c main.c -o a.o

    这样生成的目标文件的名字就是 a.o

    2) 链接(Link

    gcc命令后面紧跟目标文件的名字,就可以将目标文件链接成为可执行文件,例如:

    gcc main.o

    就将 main.o 链接为 a.out。打开 demo 目录,就会看到 a.out

    gcc命令后面紧跟源文件名字或者目标文件名字都是可以的,gcc命令能够自动识别到底是源文件还是目标文件:如果是源文件,那么要经过编译和链接两个步骤才能生成可执行文件;如果是目标文件,只需要链接就可以了。

    使用-o选项仍然能够自定义可执行文件的名字,例如:

    gcc main.o -o main.out

    这样生成的可执行文件的名字就是 main.out

    下面是一个完整的演示:

    $ cd demo

    $ gcc -c main.c

    $ gcc main.o

    $ ./a.out

    C语言中文网

    在控制台上的真实效果为:

    http://c.biancheng.net/cpp/uploads/allimg/171009/1-1G009131435196.jpg

    展开全文
  • 此背景,云原生数据库成为大势所趋,不管是老牌的数据库厂商,还是大型云计算企业都在向这一趋势靠拢。 全球知名咨询公司Gartner指出,云将主导数据库市场的未来,到2022年,75%的数据库将被部署或迁移至云平台...

    前言

    数据库一直是应用开发中非常重要的一部分。从MySQL到亚马逊的RDS(关系型数据库服务,Relational Database Service),业界有很多数据库系统供开发者存储、查询和管理数据。随着海量计算的持续发展,给传统数据库带来了不少挑战,而云原生数据库却可以应对这些挑战。

    亚马逊云科技提供了100余种产品免费套餐。其中,计算资源Amazon EC2首年12个月免费,750小时/月;存储资源 Amazon S3 首年12个月免费,5GB标准存储容量;数据库资源 Amazon RDS 首年12个月免费,750小时;Amazon Dynamo DB 25GB存储容量 永久免费。——戳这里

    传统数据库产品为何难以适应这个时代

    什么是传统数据库

    传统数据库是依照某种数据模型组织起来并存放二级存储器中的数据集合。这种数据集合具有如下特点:尽可能不重复,以最优方式为某个特定组织的多种应用服务,其数据结构独立于使用它的应用程序,对数据的增、删、改、查由统一软件进行管理和控制。

    传统数据库的缺点

    在云计算诞生之前的很长时间里,传统自建数据库可以说是所有开发者的唯一选择。 然而随着用户的数量增长以及业务复杂度的提升,传统自建数据库的缺点越发明显。
    以下只是列举出传统自建数据库的一些常见的缺点,传统的数据库技术和商业发展模式已经不能适应这个时代了。

    • 系统安全性:需要对抗DDoS攻击,传统自建数据库需要自行实现,且实现成本较高,同时也需自行修复数据库安全漏洞。
    • 硬件成本:为了能部署数据库,开发者需要购买费用高昂的数据库服务器。一次性的硬件成本很高。而且考虑到硬件损耗,后期还会有维修和更换硬件的成本。
    • 运维成本:需要花费大量的人力物力来维护硬件、维护操作系统、维护数据库软件。
    • 可扩展性:传统自建数据库采用物理硬盘作为存储空间,受单盘容量的限制,并不支持弹性升级,要增减节点,也比较难实现,如果某个数据库超过了这个存储的限制,需要运维和开发的人员一起进行数据归档来降低数据库容量。
    • 可靠性:单机实例,没有数据灾备。需要额外成本建立异地的数据灾备。不管是主从架构、还是负载均衡还是自动容灾方面,传统自建数据库都需要自行实现。

    传统数据库面临的挑战

    一方面是传统数据库不能满足互联网企业新需求。互联网企业因业务快速扩展,需实时处理海量数据,并发访问量非常大。传统数据库基于专用服务器和高端存储构成共享存储环境,设备造价昂贵,且性能和扩展性极其有限,无法满足互联网行业对数据库高并发、实时在线需求。

    另一方面是传统数据库不能适应云计算技术新需求。云计算公司依托技术积累,发起由IOE架构向基于廉价PC服务器技术的变革,降低IT服务支出,倡导以软件为中心的架构演变,降低数据库维护升级的风险。传统数据库环境是集中在一个地点的高稳定、高可靠、高可用高端企业级设备,制约云计算企业未来业务发展,增加长期运营成本。

    最后则是传统数据库在实际使用中遇到的瓶颈:

    1. 无法应对每秒上万次的读写请求,硬盘IO此时也将变为性能瓶颈
    2. 表中存储记录数量有限,横向可扩展能力有限,纵向数据可承受能力也是有限的,面对海量数据,势必涉及到分库分表,难以维护。大数据查询SQL效率极低,数据量到达一定程度时,查询时间会呈指数级别增长
    3. 难以横向扩展,无法简单地通过增加硬件、服务节点来提高系统性能
    4. 对于需要24小时不间断提供服务的网站来说,数据库升级、扩展将是一件十分麻烦的事,往往需要停机维护,数据迁移,为了避免服务间断,如果网站使用服务器集群,则根据集群策略,需要相应的考虑主从一致性、集群扩展性等一系列问题

    云原生数据库到底是什么?

    什么是云原生

    云原生(Cloud Native)是一种构建和运行应用程序的方法,是一套技术体系和方法论。Cloud Native是一个组合词,Cloud+Native。Cloud是适应范围为云平台,Native表示应用程序从设计之初即考虑到云的环境,原生为云而设计,在云上以最佳姿势运行,充分利用和发挥云平台的弹性+分布式优势。

    在这里插入图片描述

    云原生的特点

    说起云原生的定义,最早要从2013年说起,期间在不断定义完善。可以看出“云原生”的定义,也是随着时代和技术的发展,不断演化。容器技术、微服务、可持续交付、DevOps,这四点构成云原生的四要素特点。

    在这里插入图片描述

    • 容器化: 微服务的最佳载体,Docker起到应用隔离作用,为微服务及其所需的所有配置、依赖关系和环境变量移动到全新、无差别的运行环境,移植性强。
    • DevOps: 强调高效地协调开发与运维的合作。通过自动化发布管道、CI 工具快速将应用部署到生产环境中。
    • 持续交付: 在敏捷开发中,针对客户的需求变化,发布非常频繁,那么就需要用到持续交付。当存在多个版本同时提供服务的情况,需要支持灰度发布/金丝雀发布等。
    • 微服务: 一个微服务基本是一个能独立发布的应用服务,应用间通过RESTful API 通信,可以被独立部署、更新、扩容和重启。

    什么是云原生数据库

    云原生数据库,是一种通过云平台构建、部署和分发的数据库服务。它以 PaaS 的形式进行分发,也经常被叫做 DBaaS。相比于传统数据库,云原生数据库提供了更好的访问性和可伸缩性。

    在这里插入图片描述

    云原生数据库的特点

    • 自动容错: 云原生数据库自动容错机制包括宕机自动迁移,故障自动隔离,负载均衡,自动限流降级等。
    • 弹性伸缩: 可以根据 CPU load,memory 使用率等做到自动伸缩,秒级扩容。能够根据业务CPU Load、 Memory 负载时自动伸缩,做到秒级扩缩容能力,灵活的动态分配或释放资源,结合弹性计费策略,可以大幅度降低用户的使用成本。
    • 弹性计费: 支持按量(如流量、存储量、调用次数、调用时长、核数、内存资源占用量等)制定多种定价策略,使用户可根据业务情况灵活匹配出最优计量模式,节约用户成本。
    • 易于管理: 能够做到从自助运维到自动运维的转变,具备自动化异常分析诊断能力,在运维操作中实现白屏化、智能化、规模化、少人化。
    • 安全隔离: 云数据库采用共享池化技术来提高计算、存储、网络等资源的利用率,此外还需要考虑多租户安全稳定的隔离性,避免信息泄露或遭受攻击。
    • 极致体验: 用户对于数据库的申请、创建、监控、报警、故障定位都以最简单的方式完成,给用户以极致便捷的体验。

    相比传统数据库,云原生数据优势又是什么?

    选择云原生数据库有以下几个优点:
    易处置性简单来讲,易处置性是指数据库在无需事先通知的情况下,即时处理崩溃或启动进程的能力。尽管现在有先进的技术,但是像磁盘故障、网络隔离故障,以及虚拟机异常等,仍然不可避免。

    对于传统数据库,这些故障尤其有害,因为用单个机器运行整个数据库,即便一个很小的问题都可能影响所有功能。而云原生数据库的设计具有显著的易处置性,即允许虚拟机在即时通知下立即重启或重新调度。实际上,易处置性已从单个虚拟机扩展到了整个数据中心。随着我们的环境持续朝着更加稳定的方向发展,云原生数据库将发展到对此类故障无感知的状态。

    增强的安全性 DBaaS运行在受高度监控和安全的环境里,受到反恶意软件、反病毒软件和防火墙的保护。除了全天候的监控和定期的软件升级以外,云环境还提供了额外的安全性。相反,传统数据库容易遭受数据丢失和被不受限制的访问。基于服务提供商通过即时快照副本提供的数据能力,用户可以达成“RPO=0,RTO<60秒”的目标。

    可扩展性能够在运行时进行按需扩展的能力是任何企业成长的先决条件。因为这种能力让企业可以专注于追求商业目标,而不用担心存储空间大小的限制。
    传统数据库将所有文件和资源都存储在同一主机中,而云原生数据库则不同,它不仅允许你以不同的方式存储,而且不受存储问题的影响。

    更好的可访问性传统数据库最重要的限制之一,是它只能通过连接数据库系统本身进行访问。而云原生数据库提供对数据库全天候的访问,以便你随时进行任何修改,而你只需要一个可以访问internet的计算机。这样一来,就消除了可能发生的潜在的延迟,同时也为多个开发人员之间的协作开辟了途径。

    显著的成本节约建立一个数据中心是一项独立而完备的工程,需要大量的硬件投资,还需要能可靠管理和维护数据中心的训练有素的运维人员。此外,持续的运维会给你的财务带来相当大的压力。而使用云原生的DBaaS平台,你可以以较低的前期成本,获得一个可扩展的数据库,这可以让你腾出双手,实现更优化的资源分配。

    云原生数据库实力派Amazon Aurora

    云原生数据库鼻祖——亚马逊云科技

    说到云原生数据库,就不得不提的还是亚马逊云科技了,作为云计算市场的开创者,亚马逊云科技引领了整个云计算市场的发展,同时云计算也成就了亚马逊云科技。

    在这里插入图片描述
    Gartner最近发布了2021年数据库管理系统(DBMS)市场研究报告(以下简称报告)。根据报告,2021年数据库市场收入接近800亿美元,增幅达到22.3%。这是数据库市场连续5年保持高速增长。报告另一组令人关注的数据是,2021年托管云服务(dbPaaS)的收入增至392亿美元,占整体收入的49%以上。云对数据库市场的颠覆已经展露无遗。

    在这里插入图片描述
    2021年DBMS市场份额前五名中,亚马逊云科技(AWS)的表现值得关注,其2021年增长率达42.3%,几乎是市场增长的两倍。在连续三年增长的增长下,AWS已跃居第二,占比23.9%,与第一名微软仅差0.1%。第三名甲骨文占20.6%,第四名谷歌,第五名IBM。

    在这里插入图片描述
    在非关系数据库领域,AWS以64亿美元获得了43%的份额占比,在该细分领域以主导优势占据首位。这个增长背后是大数据、物联网、机器学习的兴起,非关系型数据的处理需求迅速增长。Gartner数据显示,2021年非关系型数据库的市场收入达到148亿美元,占总体数据库市场的19%。2017年时,这一比例仅为8%。

    在这里插入图片描述
    截至目前,亚马逊云科技目前提供十多种专门构建的数据库服务,支持关系、键值、文档、内存、图、时间序列、宽列和分类账八大数据类型。

    在这里插入图片描述
    为什么亚马逊云科技要提供这么多的数据库产品?在笔者看来,正如亚马逊首席技术官兼副总裁 Dr. Werner Vogels 所言,“开发者希望他们的应用程序能够很好地被构建和有效扩展,为此,他们需要能够在同一应用程序中使用多个数据库和数据模型。很少有一个数据库能够满足多个不同应用场景的需要,一刀切的数据库时代已经过去,开发人员正在使用大量的专用数据库来构建高度分布式的应用程序。

    附亚马逊数据库免费试用链接及上手教程:
    https://aws.amazon.com/cn/getting-started/databases/get-started/?nc=sn&loc=4&trk=fab55528-7c2e-4517-b90e-65b760ecfc1c&sc_channel=el
    云原生数据库在线大会:https://www.awsevents.cn/CloudNative/listDetails.html?trk=1227489f-bfd0-430a-85df-750d92bb9d11&sc_channel=el

    云时代Amazon Aurora的发展

    如今,企业面临着指数级递增的海量存储需求,业务也面临更多的热点和突发流量带来的挑战。由于企业需要降本增效,进行更智能的数据决策,传统的商业数据库已经难以满足和响应快速增长的业务诉求。

    云原生数据库不仅减少了数据库参数的重复配置,而且具有快速部署、高扩展性、高可用性、可迁移性和易运维性以及资源隔离等特点。尤其是基于容器化、微服务、Serverless 等理念设计的具备弹性伸缩与全球部署能力的云原生数据库,能随时随地从多前端访问,提供云服务的计算节点,并且可以灵活及时调动资源进行扩缩容,助力企业降本增效,成为行业发展新趋势。

    在此背景下,云原生数据库成为大势所趋,不管是老牌的数据库厂商,还是大型云计算企业都在向这一趋势靠拢。

    全球知名咨询公司Gartner指出,云将主导数据库市场的未来,到2022年,75%的数据库将被部署或迁移至云平台,只有25%的数据库会在本地运行。云化无疑代表了未来,企业如何在云原生架构下使用数据库,就成为必须要思考的问题。

    此时,为适应变化,关系型数据库需要革新和自我进化。而开路者就是连续 11 年被 Gartner 评为“全球云计算领导者”的亚马逊云科技(Amazon Web Services)。

    亚马逊云科技在 2014 年推出关系型数据库Amazon Aurora。它兼容 MySQL 和 PostgreSQL,采用共享存储和读写分离的方式,不仅提升了数据库性能,而且解决了可扩展性问题,让传统互联网公司可以无缝迁移到云上,这让它成为云计算时代的一个代表。

    在这里插入图片描述
    凭借既有传统商业数据库的高性能和可用性,以及具有开源数据库的简单性和成本效益,Amazon Aurora 成为亚马逊云科技历史上用户数量增速最快的云服务,且跻身最受初创公司青睐的八项亚马逊云科技全球服务。

    通过DB-Engines趋势图,我们可以发现Amazon Aurora的增长趋势明显,受欢迎程度之高。

    在这里插入图片描述

    企业选择Amazon Aurora背后的原因

    为什么它能受到诸多企业青睐?这离不开 Amazon Aurora 强大的性能特性和先进的架构设计以及廉价的成本。

    • 兼容MySQL
      Aurora完全兼容使用InnoDB存储引擎的MySQL 5.6,使得使用MySQL编写的大部分代码、应用、驱动等无需改变或者很少改变即可实现迁移到Aurora,反之依然。
    • 高性能
      Amazon通过紧密集成数据库引擎和基于SSD的虚拟化存储层(专为数据库工作负载而开发),其性能和可用性相较于MySQL有大幅提升,从而降低了存储系统的写入次数、尽量避免了锁定并消除了数据库处理线程带来的延迟。在相同硬件条件下,Aurora提供了相对于标准MySQL高达五倍的吞吐量,每分钟能完成600万的插入操作和3000万的查询操作。
    • 高可用性和高耐久性
      Aurora能够在多个可用区上自动复制数据,并持续地把数据备份Amazon S3上,在不影响性能的情况下实现99.999999999%的耐久性。 Aurora提供了高于99.99%的可用性,可在60秒内自动检测大多数数据库故障并恢复正常,而不会出现崩溃恢复或需要重建数据库缓存的情况。Aurora还能够持续监测实例健康状况,如果出现故障,它会自动切换至只读副本而不会丢失数据。
    • 高扩展性
      使用Amazon RDS服务扩展了Aurora的容量,还能够增加15个Aurora 副本,以及自动扩展存储容量而无需任何中断,从而避免停机或性能降低的情况。
    • 高安全性
      Aurora运行在Amazon VPC里,它能够将Aurora限制在自己的虚拟网络里;在数据传输过程中自动加密数据。Amazon RDS为Aurora集成了AWS身份识别和访问管理(IAM)服务,该服务能够非常安全地控制用户对Amazon AWS服务和资源的访问权限。
    • 非常廉价
      Aurora提供了同高端商用数据库同样的功能,但只有高端商用数据库产品成本的十分之一。用户无需前期投入,只需为自己所使用的每个Aurora数据库实例支付每小时的使用费,也没有最低承诺费用或预付费用。
    • 无服务器架构
      Amazon Aurora 架构支持 Serverless 无服务器架构。 它采用计算与存储分离的架构,可以做到存储层的快速扩展,提升数据分析能力。同时,它还采用了独特的日志即数据库理念,省去节点跟存储层数据传输的量,以达到性能提升。

    如果说云时代的到来推动了数据库的变革,那么与 Serverless 的结合,则再次为数据库的发展添了把火。

    亚马逊云科技在 2018 年推出 Amazon Aurora Serverless v1。据悉,它是 Amazon Aurora 的一种按需自动扩展配置版本,它会根据应用程序的需求自动启动、关闭以及扩展或缩减容量,让开发者无需管理任何数据库实例,即可在云中运行数据库。

    如此看来云原生数据库真的很强,接下来我们通过以下几个实例来看看亚马逊云科技的云原生数据库的具体优势,这些优势解决了哪些企业的痛点。

    在这里插入图片描述
    三星使用Amazon Aurora降低成本。随着用户数量激增至11亿以上,这家电子巨头决定将其庞大的数据库从单一的传统联网数据中心 (IDC)解决方案转移出去,因为这一解决方案不仅成本高昂,而且难以扩展,因此难以适应不断增长的流量需求。三星电子将其全球三星账户数据迁移到了一个专为云构建且与MySQL和PostgreSQL兼容的关系数据库一Amazon Aurora中。此后,三星运维成本大幅降低,因为三星得以从本地传统数据库的限制性许可成本中解放出来。
    在这里插入图片描述
    九州通采用 Amazon Aurora,轻松实现数据库的读写分离及按需扩展。使用 Amazon Aurora 数据库服务,单个 Amazon Aurora 集群可以支持多达 15 个只读节点,支持在线自动扩展与收缩。整体数据库性能提升 5 倍,TCO 降低了 50%,实现了跨可用区部署、负载均衡 / 自动故障转移,精细监控 / 按需自动伸缩等。同时,还有效降低主库工作负载压力。此外,在性能和成本上取得高效平衡。借助 Amazon Aurora Auto Scaling 功能,实现只读副本按需伸缩,满足业务需求的同时,节省服务器成本。
    在这里插入图片描述
    虎牙直播在全球化过程中,也选择了 Amazon Aurora。2018 年初,虎牙直播上线海外产品 Nimo TV,年底,月活用户达千万级。产品成功登陆东南亚及拉美地区,2019 年进入西班牙市场。据悉,在数据库后台,虎牙直播使用 DynamoDB 存储用户的动态信息,包括支付、状态、好友关注等信息。相对静态的信息存储在 Amazon Aurora 上,如用户的基础信息。Amazon Aurora 能自动扩容,且因为计算和存储分离,当数据量较大时,能单独升级计算实例,确保性能。同时,异常情况下,通常只需 10 秒左右就能自动实现故障转移,对终端用户没有任何影响。并且,利用其全球数据库功能,可以提升本地用户体验。虎牙直播在亚马逊云科技亚太(新加坡)区域部署数据库,在其他区域建立副本,提高当地用户的使用体验。

    最近,亚马逊云科技宣布无服务器数据库服务Amazon Aurora Serverless v2(Amazon Aurora Serverless 第二个版本)正式可用,新一代Amazon Aurora Serverless可在几分之一秒内自动扩展到数十万个事务,支持最严苛的应用程序。Amazon Aurora Serverless v2可根据应用程序的需求,以细粒度的增量扩展容量,与为峰值负载预置数据库容量的方式相比,可帮助客户节省高达90%的成本。Amazon Aurora Serverless v2同时兼备Amazon Aurora的高可用性、性能和弹性,以及低延迟和快速查询等功能。使用Amazon Aurora Serverless v2无需预付费用,客户只需为使用的数据库容量付费。

    更值得一提的是,Amazon Aurora Serverless v2 支持跨 AZ 的高可用部署和读取扩展,通过持续的监控和尽可能大的利用缓冲池,v2 原地扩展可以做到秒级别。

    目前,Amazon Aurora Serverless v2在兼容MySQL和PostgreSQL的Amazon Aurora上正式可用,现已在美国东部(俄亥俄)、美国东部(弗吉尼亚北部)、美国西部(加利福尼亚北部)、美国西部(俄勒冈)、亚太地区(香港)、亚太地区(孟买)、亚太地区(首尔)、亚太地区(新加坡)、亚太地区(悉尼)、亚太地区(东京)、加拿大(中区)、欧洲(法兰克福)、欧洲(爱尔兰)、欧洲(伦敦)、欧洲(巴黎)、欧洲(斯德哥尔摩)和南美洲(圣保罗)区域推出,并将很快在其它亚马逊云科技区域推出。

    总结

    伴随数字化转型步入“深水区”,企业的业务需求迭代迅速,数据量和并发访问量呈指数级增长,传统关系型数据库遇到捉襟见肘的扩展能力、大数据处理性能低等挑战。数据对于企业的重要性越来越高,企业对于以数据库为核心的专业服务需求也愈发迫切。传统数据库逐渐难以适应现在企业的需求,而亚马逊云原生数据库Aurora的到来解决了企业在数字化时代的使用传统数据库面临的一切问题。

    对于中小企业来说,新冠疫情的冲击反而加速了企业上云的步伐,但在上云的过程中,技术门槛和高额的试错成本,都有可能变成压垮中小企业的稻草。而恰恰亚马逊云原生数据Aurora可以很好地帮助这些中型企业渡过这些难关。

    粉丝福利

    亚马逊云科技专为开发者们打造了多种学习平台:

    1. 入门资源中心:从0到1 轻松上手云服务,内容涵盖:成本管理,上手训练,开发资源。https://aws.amazon.com/cn/getting-started/?nc1=h_ls&trk=32540c74-46f0-46dc-940d-621a1efeedd0&sc_channel=el
    2. 架构中心:亚马逊云科技架构中心提供了云平台参考架构图表、经过审查的架构解决方案、Well-Architected 最佳实践、模式、图标等。https://aws.amazon.com/cn/architecture/?intClick=dev-center-2021_main&trk=3fa608de-d954-4355-a20a-324daa58bbeb&sc_channel=el
    3. 构建者库:了解亚马逊云科技如何构建和运营软件。https://aws.amazon.com/cn/builders-library/?cards-body.sort-by=item.additionalFields.sortDate&cards-body.sort-order=desc&awsf.filter-content-category=*all&awsf.filter-content-type=*all&awsf.filter-content-level=*all&trk=835e6894-d909-4691-aee1-3831428c04bd&sc_channel=el
    4. 用于在亚马逊云科技平台上开发和管理应用程序的工具包:https://aws.amazon.com/cn/tools/?intClick=dev-center-2021_main&trk=972c69e1-55ec-43af-a503-d458708bb645&sc_channel=el

    专属福利

    福利一: 100余种产品免费套餐。其中,计算资源Amazon EC2首年12个月免费,750小时/月;存储资源 Amazon S3 首年12个月免费,5GB标准存储容量。
    https://aws.amazon.com/cn/free/?nc2=h_ql_pr_ft&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all&trk=e0213267-9c8c-4534-bf9b-ecb1c06e4ac6&sc_channel=el

    福利二: 最新优惠大礼包,200 数 据 与 分 析 抵 扣 券 , 200 数据与分析抵扣券,200 200机器学习抵扣券,200$微服务与应用开发抵扣券。https://www.amazonaws.cn/campaign/?sc_channel=el&sc_campaign=credit-acts-ldr&sc_country=cn&sc_geo=chna&sc_category=mult&sc_outcome=field&trkCampaign=request-credit-glb-ldr&trk=f45email&trk=02faebcb-3f61-4bcb-b68e-c63f3ae33c99&sc_channel=el

    福利三: 解决方案CloudFormation一键部署模版库
    https://aws.amazon.com/cn/quickstart/

    展开全文
  • LinuxC语言开发环境的搭建

    千次阅读 2019-09-26 20:38:58
    等命令行模式的编辑器,它们功能强大,逼格够高,不管有没有桌面环境都能使用,是 LinuxC/C++ 程序员必备的神器。但是 Vim 和 Emacs 并不容易上手,使用者需要记忆很多命令和快捷键,熟练才能生巧,所以需要一段时间...
  • 危机自救的第一策略是极速调整认知.人类历史的发展过程中,有无数的变化和未知数不确定性,但唯一不变的就是——人类永远要面对困难和挑战。危机之中,我们每个...
  • 强化学习环境搭建

    千次阅读 2019-04-30 17:16:40
    强化学习环境搭建强化学习简介环境安装Anaconda安装安装DockerDocker介绍Docker安装Open...1.2.智能体的状态执行了一个动作后进入一个状态 1.3.环境会根据智能体的动作给予相应的奖惩 1.4.智能体根据环境给予...
  • 如何搭建软件测试环境

    千次阅读 多人点赞 2021-02-18 21:19:05
    如何搭建软件测试环境
  • Knewton适应性学习

    千次阅读 2018-06-21 10:40:29
    Knewton适应性学习 构造全球最强大的教育推荐... (原文:Ateaching method premised on the idea that the curriculum should adapt to eachuser.) 基础层次上,适应性学习的定义看起来很简单。但是更深入的...
  • 阿里工作的这段时间里,学到了哪些东西

    万次阅读 多人点赞 2019-08-18 21:38:28
    当初我没有参加阿里巴巴的实习,而是选择了直接进行校园招聘,这也是因为当时我对实习的部门不感兴趣,于是校招的时候我就选择了自己感兴趣的部门,也就是现在我所在的蚂蚁金服。 之前就听说过阿里的工作强度,...
  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。 1、 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 “Hellow World”。 ...
  • VC++6.0环境下调试c语言代码的方法和步骤_附图

    万次阅读 多人点赞 2018-08-13 11:55:12
    1.C语言程序四步开发步骤 (1)编辑。可以用任何一种编辑软件将纸上编写好的C语言程序输入计算机,并将C语言源程序文件*.c以纯文本文件形式保存计算机的磁盘上(不设置字体、字号等)。
  • 普适边缘计算环境下的区块链资源分配与共识 资源提供者:具有传感、存储和通信资源的"抽象边缘"设备 应用:使用这些资源可以完成数据交易 安全保证:区块链技术确保交易不可更改和否认 本文特点: 1、利用设计的...
  • RTOS环境下多任务编程要点

    千次阅读 2014-04-05 17:39:53
    RTOS环境下多任务编程要点 一. 分析阶段 1. 需求分析,予以文档描述; 2. 一些初始化问题,探究需求分析中的关键点; 3. 解决时序问题,系统中算法的分析; 4. 决定使用RTOS,依赖于时间响应和任务数量;...
  • 什么是适应

    千次阅读 2018-06-23 04:30:19
    【智慧就是适应,是一种最高级形式的适应。动作是认识的源泉,是主客体相互作用的中介。图式即认知结构。同化是主体将环境中的信息纳入并整合到已有的认知结构的过程。同化表明主体改...
  • 问题 重排序多线程环境下可能会导致数据不安全 顺序一致性 多线程环境下的理论参考模型 为程序提供了极强的内存可见性保证 特性 一个线程中的所有操作必须按照程序的顺序来执行 所有线程只能看到一个单一的操作...
  • 太厉害了,终于有人把TCP/IP 协议讲的明明白白了

    万次阅读 多人点赞 2020-05-07 09:30:15
    OSI 参考模型注重“通信协议必要的功能是什么”,而 TCP/IP 则更强调“计算机上实现协议应该开发哪种程序”。 二、 TCP/IP 基础 1. TCP/IP 的具体含义 从字面意义上讲,有人可能会认为...
  • Zabr是一种开源的一维码和二维码检测工具,该工具检测时适应性很强,如图的示例图片不进行任何图像处理情况下都可以便正确读取条形码或者二维码的信息,适合于工业环境下光照不稳定情况识别条形码和二维码。...
  • 今天突然想玩一玩苹果的Mac OS系统,由于没钱买苹果机,只好通过虚拟机来装一个玩玩,说干就干,开始走起。...由于苹果的操作系统不管是镜像格式,还是引导方法上,与windows和linux系统存在...
  • openEuler网络配置+换源+桌面环境ukui等基本环境部署

    千次阅读 多人点赞 2021-09-29 21:43:09
    这篇文章也许是你最佳的选择,干货满满。 文章目录1.网络配置1.虚拟网络配置器配置2.网络配置文件设置2.使用xshell远程登录3.换源4.安装桌面环境ukui5.安装vmware tools6.问题解决办法
  • Anaconda python windows环境安装及完全排坑教程

    千次阅读 多人点赞 2020-07-15 17:42:07
    有些新同学希望了解数据科学的内容,通过各方渠道了解到了anaconda这只神兽,但安装到使用的过程中,往往面临着一个又一个的大坑,所以我趁着重新安装,尽可能的把之前趟过的雷再踩一遍,并且把处理的过程和最后的...
  • 不得不说,codeproject是个好东西,昨天就一直查这个png按钮怎么用,很多人都在说这个老外写的GdipButton,可惜家里的网登不上,老外的网站不了。后来又找了个pngbutton,发现不能适应我按钮的大小,就又费劲找到...
  • 告诉我这科的理论哪可以实用呀?搞不懂,只能收藏一下包不挂科
  • 20款知名PHP集成环境推荐与优缺点分析、php环境大全推荐(PHP环境搭建包)、PHP环境搭建、PHP集成环境搭建,最好用的20个php环境搭建工具推荐
  • 这是一篇深度好文,我讲我的经验很直白地写出来了,希望大家会喜欢。 一个思维习惯,让你成为架构师 程序员的迷茫不仅仅是面对技术繁杂的无力感,更重要的是因为长期埋没于软件 世界的浩大的分工体系中,无法...
  • ERP系统集成实例 - 适应新常态

    千次阅读 2022-01-28 16:26:22
    眼下,持续的新冠疫情(COVID-19)对全球供应链产生了...ERP可以将各种不同的业务功能和数据源联系一起,形成一个数据共享平台,制造商利用该平台可以精确地管理从原材料、采购到人力资源乃至更多领域的日常运营...
  • Linux与Windows编程的区别,可以总结为以下几点: 1.Linux可以看到源代码,windows不行。 这一点直接导致的结果就是特殊应用的场合可以自行剪裁和定制所需的内核模块,这对于高级系统内核管理优化和驱动程...
  • 您肯定会想:是不是任何一个普通帐户可以变成管理员啊?!但是,难道这不是一个安全漏洞吗? 答案是:可以。不过本人不认为这是安全漏洞,这是系统的用户管理的一种方式而已。 出于安全考虑,能否防止? 答案是...
  • 采用32位单片机STM32F103C8T6为处理核心,数据采集节点端控制一系列的传感器(如DS18B20、DHT11、MQ-135、光敏二极管、雨滴传感器、土壤水分传感器等)来采集环境参数,使用蜂鸣器与STM32F103C8T6连接做为系统的...
  • 分享一篇文章,原文链接:Python IDEs and Code Editors (Guide)。 使用IDLE或者Python Shell来编写Python是非常适合于...使用一款集成开发环境甚至是一款好的专用的代码编辑器会让编程充满乐趣,但是如何选择呢?...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 205,862
精华内容 82,344
关键字:

在任何环境下都能适应