Byzer 是一门面向 Data 和 AI 的新一代编程语言,它支持多种文件类型,例如本地文件系统,HDFS,对象存储:Amazon blob、S3等。

这些对象存储通过 Byzer 内置的 CustomFS 插件,加上官方提供的 SDK,便可以轻松访问。我们也支持在引擎侧通过配置的方式把对象存储作为默认的文件系统。

Byzer-lang 默认文件系统

Byzer 是有文件系统的概念的,Byzer 的文件系统是 File System、Deltalake(数据湖)、Hive等数据源的聚合。其中的 File System、Deltalake 存储是由底层配置的文件存储系统所决定的,而其他的目录则是来自不同的数据源不同的数据存储。

我们看一下 Byzer Notebook,在右侧边的数据目录,可以看到 Hive/Deltalake/FileSystem。FileSystem 为个人目录,用户上传、加载、存储的数据都在该目录下,该目录为用户私有不支持公开其他用户访问。Deltalake 为 Byzer 的工作空间,支持公开访问。

FileSystem 默认就是按租户隔离的,而 DetltaLake 的库表则是所有用户都可以看到和使用的。

Byzer-lang Interpreter 团队在设计的时候,就考虑了多租户。那如果要实现多租户,有两种实现模式:

  1. 和 Linux/HDFS 文件系统的用户系统保持一致
  2. 独立的用户系统

如果采用第一种方案,会导致绑定在特定文件系统上,元数据难以同步。所以我们采用了第二种方案。

具体做法是,在和Byzer-lang Interpreter 的通讯的时候,Notebook 可以传递一个目录前缀,比如/data/byzer/homes, 此时用户对文件系统的读写都会挂载在该目录下。对于如下语句:

save overwrite table1 as csv.`/tmp/table1`;

对应的实际目录会是 /data/byzer/homes/<用户名>/tmp/table1。 这样,用户都是在自己的目录操作,不同的用户不会互相影响。

我们知道,在 Byzer Notebook 你可以进行上传文件的动作,Byzer Notebook 会将文件通过 Byzer-lang Interpreter 上传到 Byzer-lang 的默认文件系统上,因为只有在其默认的文件系统上,Byzer-lang 才能进行操作,同时在 Notebook 里你可以在文件系统里查看你上传的文件。这等价于你使用如下命令进行文件的查看:

!fs -ls /;

如何将 s3/oss/azure blob 配置成默认的文件系统

开始体验之前,请参考 安装文档 部署 Byzer-lang;您也可以在 byzer.org 体验这个功能。

默认文件系统配置我们主要会以 core-site.xml 文件配置为例,尽管你也可以在启动命令中进行配置。 对于分布式版本的 Byzer, 您仅需将 core-site.xml 文件放在 $SPARK_HOME/conf 目录下, 如果是桌面版本,命令行版本,那么可以将其用如下命令达成 jar包后放到 Byzer-lang 的安装目录 libs 子目录下。

jar cvf conf.jar core-site.xml

libs 子目录长这个样子:

Amazon S3

为了读写 Amazon S3,我们在官方下载站提供了适配 Byzer 的 SDK JAR 包,您需要根据使用的 Byzer 对应 hadoop 版本选择不同的 JAR:

  • 适配 hadoop 2.7 的 aws-s3_2.7-1.0-SNAPSHOT(link失效,待补充)
  • 适配 hadoop 3.2 的 aws-s3_3.2-1.0-SNAPSHOT(link失效,待补充)

您也可以访问我们用于生成shard jar 的 github 项目byzer-objectstore-dep,手动进行构建。

获取到 JAR 包后,请将 Jar 移至 $BYZER_HOME/libs子目录,并重启 Byzer-lang。

开通 AWS 账号

现阶段您可以在 AWS官网 免费注册 AWS 账号,免费体验海外区域产品和服务。注册后默认赠送海外区域账户免费套餐,其中包括 5G 的免费 S3 存储空间,方便我们体验。

注册过程中需要绑定信用卡号,如果您没有VISA,可以直接使用银联卡进行绑定,建议如果使用的是银联卡,请选择人民币进行结算。

如何获取 Access key 和 Secret key

  1. 转到 Amazon Web Services 控制台并 单击您的帐户名称(位于控制台的右上角)。然后,在展开的下拉列表中,选择 Security Credentials

  1. 单击 继续使用安全凭证 按钮。

  1. 展开 访问密钥(访问密钥 ID 和秘密访问密钥) 选项。您将看到活动和已删除访问密钥的列表。注意: 您无法检索现有的密钥。您只能在创建后立即看到密钥一次。因此,为了获得密钥,您需要创建一个新密钥。

  1. 要生成新的访问密钥,请单击 创建新访问密钥 按钮。

  1. 单击 显示访问密钥 使其显示在屏幕上。请注意,您可以将其作为文件下载到您的计算机上,并在需要时打开它。要下载它,只需单击“ 下载密钥文件” 按钮。

注意! 如果您在按下“关闭”或“取消”之前没有记下密钥或将密钥文件下载,您以后将无法查询密钥。然后您必须删除您创建的密钥并开始创建新密钥。

文件系统配置

我们需要修改 hadoop 的 core-site.xml 配置文件,用于云存储连接器通过该配置访问 S3,fs.defaultFS 的配置如下:

  <configuration><property><name>fs.AbstractFileSystem.s3a.impl</name><value>org.apache.hadoop.fs.s3a.S3A</value></property><property><name>fs.s3a.impl</name><value>org.apache.hadoop.fs.s3a.S3AFileSystem</value></property><property><name>fs.AbstractFileSystem.s3a.impl</name><value>org.apache.hadoop.fs.s3a.S3A</value></property><property><name>fs.defaultFS</name><value>s3a://test</value></property><property><name>fs.defaultFS.lightning</name><value>s3a://test</value></property><property><name>fs.s3a.fast.upload</name><value>true</value></property><property><name>fs.s3a.region</name><value>us-west-2</value></property><property><name>fs.s3a.block.size</name><value>67108864</value></property><property><name>fs.s3a.connection.maximum</name><value>200</value></property></configuration>

使用配置属性进行身份验证

要使用 S3 配置身份验证,请在配置文件core-site.xml中显式声明凭据,例如:

<property><name>fs.s3a.access.key</name><value>ACCESS-KEY</value></property><property><name>fs.s3a.secret.key</name><value>SECRET-KEY</value></property>

如果使用 AWS 会话凭证进行身份验证,密钥必须是会话的密钥,并且fs.s3a.session.token选项设置为您的会话令牌。

<property><name>fs.s3a.session.token</name><value>SESSION-TOKEN</value></property>

这种三元组的配置方式,是通过 AssumeRole 定期刷新的临时凭证,有关获取这些凭证的详细信息,请参见此处:

https:// docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html

也可以为特定存储桶添加此配置。有关更多信息,请参阅 使用 Per-bucket 凭据进行身份验证。

使用 spark 属性进行身份验证

除了上述的在 core-site.xml 进行配置,您可以在 byzer 启动配置中配置 S3 配置身份验证,例如:

--spark.hadoop.fs.s3a.aws.credentials.provider <aws-credentials-provider-class>--spark.hadoop.fs.s3a.endpoint <aws-endpoint>--spark.hadoop.fs.s3a.server-side-encryption-algorithm SSE-KMS

Per-bucket 配置

您可以使用语法配置每个存储桶的属性spark.hadoop.fs.s3a.bucket.<bucket-name>.<configuration-key>。这使您可以设置具有不同凭据、端点等的存储桶。

例如,除了全局 S3 设置之外,您还可以使用以下键单独配置每个存储桶,比如用于夜间数据的存储桶s3a://nightly/使用身份密钥,因此其特定于存储桶的配置为:

<property><name>fs.s3a.bucket.nightly.access.key</name><value>AKAACCES-SKEY-2</value></property><property><name>fs.s3a.bucket.nightly.secret.key</name><value>SESSION-SECRET-KEY</value></property>

Azure Blob

我们在官方下载站提供了适配 Byzer 的 SDK JAR 包,您需要根据使用的 Byzer 对应 hadoop 版本选择不同的 JAR:

  • 适配 hadoop 2.7 的 azure-blob_2.7-1.0-SNAPSHOT
  • 适配 hadoop 3.2 的 azure-blob_3.2-1.0-SNAPSHOT

您也可以访问我们用于生成 shard jar 的 github 项目 byzer-objectstore-dep,手动进行构建。

获取到 JAR 包后,请将 Jar 移至 $BYZER_HOME/libs子目录,并重启 Byzer-lang。

文件系统配置

通过如下格式配置 wasb 路径,任何 Hadoop 组件都可以使用以下格式的 URL 引用该 Azure Blob 存储帐户中的文件:

wasb[s]://<containername>@<accountname>.blob.core.windows.net/<path>

我们这里将 fs.defaultFS 配置为使用wasb或wasbs URL。这会导致所有路径(例如 /testDir/testFile)自动解析为该文件系统。示例:

<property><name>fs.defaultFS</name><value>wasb://CONTAINER_NAME@ACCOUNT_NAME.blob.core.windows.net</value><final>true</final></property><property><name>fs.AbstractFileSystem.wasb.impl</name><value>org.apache.hadoop.fs.azure.Wasb</value><final>true</final></property><property><name>spark.hadoop.fs.wasb.impl</name><value>org.apache.hadoop.fs.azure.NativeAzureFileSystem</value><final>true</final></property>

使用 Azure Blob 存储需要配置凭据,配置属性名称的格式为fs.azure.account.key.<account name>.blob.core.windows.net,值是访问密钥。 访问密钥是保护对存储帐户的访问的机密。不要与不受信任的一方共享访问密钥(或 core-site.xml 文件)。

配置示例:

<property><name>fs.azure.account.key.youraccount.blob.core.windows.net</name><value>YOUR ACCESS KEY</value></property>

Aliyun-OSS

我们在官方下载站提供了适配 Byzer 的 SDK JAR 包

  • 适配 hadoop 3.2 的 azure-blob_3.2-1.0-SNAPSHOT

您也可以访问我们用于生成 shard jar 的 github 项目 byzer-objectstore-dep,手动进行构建。

获取到 JAR 包后,请将 Jar 移至 $BYZER_HOME/libs子目录,并重启 Byzer-lang。

文件系统配置

我们需要修改 hadoop 的**core-site.xml**配置文件,用于云存储连接器通过该配置访问 OSS,fs.defaultFS 的配置如下:

  <configuration><property><name>fs.oss.impl</name><value>org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem</value></property><property><name>fs.defaultFS</name><value>oss://test</value></property>    <property><name>fs.oss.endpoint</name><value>oss-cn-hangzhou.aliyuncs.com</value></property>  </configuration>

使用配置属性进行身份验证

要使用 S3 配置身份验证,请在配置文件core-site.xml中显式声明凭据,例如:

<property><name>fs.oss.accessKeyId</name><value>ACCESS-KEY</value></property><property><name>fs.oss.accessKeySecret</name><value>SECRET-KEY</value></property>

该配置文件在桌面或者命令行版本里,需要通过

jar cvf conf.jar core-site.xml

将配置文件打成 Jar 包,然后丢到 libs 目录里去。如果是分布式 Server 版本,则直接将 core-site.xml`` 文件丢到 $SPARK_HOME/conf 目录下即可。

如果使用 Byzer 命令行进行运行,脚本的路径要写全路径。比如 ./bin/byzer run file:///Users/allwefantasy/Softwares/byzer-lang-darwin-amd64-3.0-2.2.1/test.by 。 否则默认

脚本路径会被作为对象存储路径来使用。

为什么已经有了默认文件系统,还要做一个文件系统插件?

回答这个问题,Byzer的开发者们认真思考过很久,才提出了这个解决方案。

William补充: 默认文件系统,易于使用,使用者无需关注文件系统,并且有隔离机制,并且通常它和引擎会有更好的亲和性(比如同一个云产商的对象存储和计算资源)。但缺点是需要运维人员提前配置。 但实际上,跨对象存储的数据传输和处理会是刚需,因为用户有组织架构的问题或者为了不被 lock 的问题,或者保证多活的问题需要通过跨云来解决。Byzer 希望为此将对象存储也抽取成一个独立数据源来看待,通过该数据源,用户可以访问和存储任意主流对象存储,并且是在 Byzer 语言层面解决,而不需要系统管理员事先配置。这个时候就引入了文件系统插件。 回到 JuiceFS , JuiceFS 可以对接各种对象存储,但是缺点是无法对对象存储里已有的数据进行管理,同时现在也不具备动态添加文件系统的能力,需要提前配置好,所以他无法解决我们实际场景中的问题。

在 Byzer 设计之初,我们就有考虑对象存储可以通过简单配置的方式,作为 Byzer 的默认文件系统。这得益于 hadoop 附带的云存储连接器让我们轻松实现这一能力。后来,我们发现了一个高性能文件系统juicefs,我们把这款产品以可配置的方式,集成到 Byzer 中。依赖于 juicefs,Byzer 可以无缝的对接几乎所有对象存储。

是不是 juicefs 就可以覆盖我们对象存储的全部场景了呢?答案是否定的,原因有几个,一个是在大数据和AI的场景中,越来越多企业不满足于一种文件系统的使用,比如长期运行的业务系统数据越来越多,运行速度越来越慢,集群扩容对线上业务影响极大,扩缩容变得越来越艰难,很多企业采用了多套文件系统,冷热分离的存储方式。如果是多个云存储之间进行数据搬迁,我们可以使用 juicefs sync,如果多个云存储有不同的业务数据,需要同时访问,就很难去做。还有一个原因是如果引擎没有配置 juicefs,引擎需要提供一种方式可以访问除默认文件系统之外的其他文件系统。

另外我们再考虑一个问题,如果使用spark 标准的 API 去读 S3 等云存储,S3 相关配置是放到 sparkContext 级别的,没办法在 spark session 级别。这意味着权限方面会有问题,比如设置了 S3 的 bucket,如果一个用户地址写对了,由于这个参数直接设置到 spark conf 中,那么理论上其他用户也能读,如果有权限系统,我们可以做两件事情:

  1. 不是每个人都可以使用 customFS 数据源。
  2. 对 customFS 里的路径需要先授权再使用。

比如你要使用 s3a://bucket01/a.txt 你需要现在权限系统获得授权。授权后就可以使用了。另外一个用户去访问,会被权限拒绝。通过数据源插件,我们可以很方便的在编译时,在权限管理系统中进行权限校验。

那么如果不需要接入统一的权限管理系统呢,有没有更便捷的方式?hadoop 附带的云存储连接器在 3.X 以后的版本中,支持了 Per-bucket 的模式,我们在配置对象存储时,可以配置多个桶,依靠这种方式,我们可以在云存储服务中配置不同权限策略的Access Key和Secret Key,达到密钥的方式隔离权限的目的。

想清楚了上面的几个问题,我们实现了 CustomFS 数据源插件,用于灵活访问多种对象存储。

下面 Amazon S3、OSS 和 Azure Blob 的读写为例介绍其使用方式。

如何使用 FS 数据源插件,随意访问一个 bucket

Amazon S3

前提条件

在使用S3之前,需要准备好SDK并设置到 spark中,如何将 s3/oss/azure blob 配置成默认的文件系统章节已经介绍这里不再赘述。

使用CustomFS读取S3

-- FS后面的路径是 S3 object 的地址。 byzertestbucket1 是 bucket。load FS.`s3a://byzertestbucket1/a.csv` where -- S3 区域。这里是东北亚3区`fs.s3a.endpoint`="s3.ap-northeast-3.amazonaws.com"-- HDFS 访问 S3 的实现类 and `fs.s3a.impl`="org.apache.hadoop.fs.s3a.S3AFileSystem"and `fs.s3a.access.key`="your access key"and `fs.s3a.secret.key`="your secret key"and `fs.s3a.buffer.dir`="/tmp/oss"and implClass="csv"as output;

脚本中包含 S3 路径,AWS 区域 ( fs.s3a.endpoint ),用户鉴权信息和文件格式 (access key、secret key) 。

S3 路径格式为:

s3a://<bucket_name>/<object_name>

使用Per-bucket写入数据到S3

通过 **Per-bucket** 我们可以配置单独的bucket信息,Byzer 代码示例如下:

set rawData=''' {"jack":1,"jack2":2}{"jack":2,"jack2":3}''';load jsonStr.`rawData` as table1;save overwrite table1 as FS.`s3a://byzertestbucket2/test.csv` where `fs.s3a.endpoint`="s3.ap-northeast-3.amazonaws.com"-- 这里我们使用fs.s3a.bucket.<bucket name>.access.key的方式单独配置一个bucket的信息and `fs.s3a.bucket.byzertestbucket2.access.key`=""your access key"and `fs.s3a.bucket.byzertestbucket2.secret.key`="your secret key"-- HDFS 访问 S3 的实现类 and `fs.s3a.impl`="org.apache.hadoop.fs.s3a.S3AFileSystem"and `fs.s3a.buffer.dir`="/tmp/oss"-- 表示s3 对象是csvand implClass="csv";

如何在aws上设置不同的权限

打开IAM 控制面板

点击 policies,创建一个自定义的策略

在编辑器中选择S3

操作这一项中,我们只选择Get 和 List

为了保证有足够的访问权限,我们把资源都勾选,唯独bucket选择我们要测试的只读bucket,要限制bucket只读,我们需要添加一个ARN

在ARN表单中,填入我们的bucket name

点击下一步,下一步,创建策略,一个bucket只读的策略就创建成功了。

我们创建好了一个策略s3_bucket_read

接下来我们再来创建几个用户,给这些用户加上这些策略。我们点击用户选择添加用户

我们创建一个叫readonly的用户

接下来,我们直接附加刚刚创建好的策略

点3次下一步后,系统会告诉我们创建成功了,并提供了密钥的下载按钮,这里我们一定要下载下来,不然就再也没有办法获取到该用户的秘钥了。

让我们来试用一下配置了策略的秘钥吧!

set rawData=''' {"jack":1,"jack2":2}{"jack":2,"jack2":3}''';load jsonStr.`rawData` as table1;save overwrite table1 as FS.`s3a://byzertestbucket2/test.csv` where -- S3 区域。这里是东北亚3区`fs.s3a.endpoint`="s3.ap-northeast-3.amazonaws.com"-- 使用只读权限的aksk做写操作,提示Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied;and `fs.s3a.bucket.byzertestbucket2.access.key`="xx"and `fs.s3a.bucket.byzertestbucket2.secret.key`="xx"-- HDFS 访问 S3 的实现类 and `fs.s3a.impl`="org.apache.hadoop.fs.s3a.S3AFileSystem"and `fs.s3a.buffer.dir`="/tmp/oss"-- 表示s3 对象是csvand implClass="csv";

我们尝试只有读权限的秘钥做写操作,得到了如下的报错信息:

Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied;

可以发现,权限配置生效了。

Azure Blob

我们在官方下载站提供了适配 Byzer 的 SDK JAR 包,您需要根据使用的 Byzer 对应 hadoop 版本选择不同的 JAR:

  • 适配 hadoop 2.7 的 azure-blob_2.7-1.0-SNAPSHOT
  • 适配 hadoop 3.2 的 azure-blob_3.2-1.0-SNAPSHOT

您也可以访问我们用于生成 shard jar 的 github 项目 byzer-objectstore-dep,手动进行构建。

获取到 JAR 包后,请将 Jar 至 $SPARK_HOME/jars 或 Byzer-lang 安装目录的 libs 子目录,并重启 Byzer-lang。

此外,您需要 Azure Blob container 和 account key 替换下文的变量,再执行。

set rawData=''' {"jack":1,"jack2":2}{"jack":2,"jack2":3}''';load jsonStr.`rawData` as table1;SAVE overwrite table1 as FS.`wasb://<container>@<account>.blob.core.chinacloudapi.cn/tmp/json_names_1` where `spark.hadoop.fs.azure.account.key.account.blob.core.chinacloudapi.cn`="<account_key>"and `spark.hadoop.fs.AbstractFileSystem.wasb.impl`="org.apache.hadoop.fs.azure.Wasb"and `spark.hadoop.fs.wasb.impl`="org.apache.hadoop.fs.azure.NativeAzureFileSystem"and implClass="parquet";load FS.`wasb://<container>@<account>.blob.core.chinacloudapi.cn/tmp/json_names` where `spark.hadoop.fs.azure.account.key.<account>.blob.core.chinacloudapi.cn`="<account_key>"and `spark.hadoop.fs.AbstractFileSystem.wasb.impl`="org.apache.hadoop.fs.azure.Wasb"and `spark.hadoop.fs.wasb.impl`="org.apache.hadoop.fs.azure.NativeAzureFileSystem"and implClass="parquet"as table2;

执行结果如下:

上面的脚本提供了 Azure Blob 路径,格式如下。假如你使用 Azure Global,请将 core.chinacloudapi.cn 替换为 core.windows.net 。

wasb://<container>@<account>.blob.core.chinacloudapi.cn/<path>/<file_name>

Where 子句 包括三类信息: Azure 鉴权信息, Azure 文件系统参数和文件格式。Azure 鉴权信息格式为

"fs.azure.account.key.<account>.blob.core.chinacloudapi.cn`="key_secret"

fs.AbstractFileSystem.wasb.impl 和 fs.wasb.impl fs.wasb 声明了 wasb 类型的URI 处理入口类为 NativeAzureFileSystem。NativeAzureFileSystem 兼容 HDFS API ,若你感兴趣,以上配置以core-site.xml 部署到 $HADOOP_CONF_DIR,部署 hadoop-azure 3.2.0 shade jar,就能使用 hdfs dfs 命令愉快地操作 Azure Blob的数据了。

下面表格说明了各个参数:

无法复制加载中的内容

Aliyun-OSS

我们在官方下载站提供了适配 Byzer 的 SDK JAR 包

  • 适配 hadoop 3.2 的 aliyun-oss_3.2-1.0-SNAPSHOT(链接失效待补充)

您也可以访问我们用于生成 shard jar 的 github 项目 byzer-objectstore-dep,手动进行构建。

获取到 JAR 包后,请将 Jar 移至 $BYZER_HOME/``libs子目录,并重启 Byzer-lang。

使用CustomFS读取 Aliyun-OSS

load FS.`oss://mlsql-release-repo/test.csv` where`fs.oss.endpoint`="oss-cn-hangzhou.aliyuncs.com"and `fs.oss.accessKeyId`="xxxxxx"and `fs.oss.accessKeySecret`="xxxxxx"and `fs.oss.impl`="org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem"and `fs.oss.buffer.dir`="/tmp/oss"and implClass="csv" as output;

一篇文章了解Byzer的文件系统相关推荐

  1. 一篇文章搞懂php文件系统基本操作

    作为一门服务端的编程语言,php自然是对服务器的文件系统提供了操作支持,一个完整的网站项目,经常会用到文件系统的方法,本文对文件系统进行详细的介绍. 两个简单的读取/写入函数 file_get_con ...

  2. 一篇文章熟悉ubuntu desktop指南

    文章目录 引言 前言 1.熟悉你的GNOME界面 1.1.GNOME指导 1.2.Log out,power off or switch users 1.3.应用程序和窗口 2.熟悉linux的基础 ...

  3. python 的库如何开发_一篇文章入门Python生态系统

    译者按:原文写于2011年末,虽然文中关于Python 3的一些说法可以说已经不成立了,但是作为一篇面向从其他语言转型到Python的程序员来说,本文对Python的生态系统还是做了较为全面的介绍.文 ...

  4. 一篇文章搞懂filebeat(ELK)

    一篇文章搞懂filebeat(ELK) https://www.cnblogs.com/zsql/p/13137833.html 目录 一.filebeat是什么 1.1.filebeat和beats ...

  5. 一篇文章了解JsBridge之IOS篇

    之前发布在掘金Android栏目下的文章"一篇文章了解Js Bridge"受到了较多的反馈,本文在该文章的基础上,添加了一些针对IOS平台下的一些问题的讨论. 什么是JSBridg ...

  6. 一篇文章入门Python生态系统

    开发者从PHP.Ruby或其他语言转到Python时,最常碰到的第一个障碍,就是缺乏对Python生态系统的全面了解.开发者经常希望能有一个教程或是资源,向他们介绍如何以大致标准的方式完成大部分的任务 ...

  7. 一篇文章看明白 Android PackageManagerService 工作流程

    Android - PackageMangerService 分析 相关系列 一篇文章看明白 Android 系统启动时都干了什么 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制 ...

  8. 真的,Kafka 入门一篇文章就够了

    初识 Kafka 什么是 Kafka Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区.多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订 ...

  9. 转载:一篇文章看明白 Android 系统启动时都干了什么

    最近在看<深入理解Android内核设计思想>,老实说,作为教材,这本书实在写的不好.本来内核的东西就比应用层繁杂,需要有个条绳子牵着,有个框子框着才不好跟丢.这个书老是在章节开头抛出一些 ...

最新文章

  1. light oj 1011Marriage Ceremonies
  2. java 不退出_Java项目不挂断运行,即当账户退出或终端关闭时,程序仍然运行,并附上执行脚本...
  3. zip压缩和unzip解压缩命令详解
  4. 详细易懂的二叉树遍历(先中后)
  5. 深度学习常见概念解析
  6. 太牛了,原来古人是这样铸造钱币的。。。
  7. 剑指offer_06
  8. Struts2源码阅读(五)_FilterDispatcher核心控制器
  9. C#利用NI VAS采集图片
  10. 如何把服务器系统克隆出来,一次Win2003服务器下的完全克隆 -电脑资料
  11. BZOJ3172lg3966 TJOI单词(广义后缀自动机)
  12. 从template到DOM(Vue.js源码角度看内部运行机制)
  13. 对花不准(错版、套版不准、错花)的原因
  14. java语言乘号_java的编码样式、运算符运算对象
  15. bzoj4006 [JLOI2015]管道连接
  16. poj 1276 Cash Machine(多重背包)
  17. drupal与html转换,HTML转Drupal主题的方法
  18. git 删除添加的远程地址
  19. studio 3t MongoDB for MAC 201903+Cracking
  20. c++ 快排优化(三数取中法)

热门文章

  1. 经典规划PDDL-积木世界
  2. SQL常见函数及题目整理
  3. 我国信用卡代偿业务的特点与问题
  4. 博洛尼亚大学计算机科学,2021QS世界大学学科排名重磅发布!意大利大学详细上榜排名,不容错过!...
  5. java 静态工厂方法代替构造器的好处
  6. 高数【求导】--猴博士爱讲课
  7. 杜彪:天猫数据如何运营、变现? 利用阿里云聚石塔在双11的成功案例
  8. DEAP 情绪数据集介绍
  9. isnumber()函数注意事项
  10. 【云栖大会】高德技术副总裁田密:智能定位带来的时代新机会