clickhouse适用场景:ClickHouse 在实时场景的应用和优化

此次分享分为三部分内容,第一部分通过讲解推荐和广告业务的两个典型案例,穿插介绍字节内部相应的改进。第二部分会介绍典型案例中未覆盖到的改进和经验。第三部分会提出目前的不足和未来的改进计划。

(文末附 ClickHouse 沙龙第四场:《ClickHouse 在 A/B 实验和模型训练的使用》报名方式)

沙龙视频

ClickHouse 在实时场景的应用和优化

讲师:郭映中 字节跳动 ClickHouse 研发工程师

文字沉淀

早期实践

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

外部事务

在介绍实时场景之前,我先简单讲一下早期的离线数据是如何支持的:

在第一场分享中,技术负责人陈星介绍了 ClickHouse 在字节跳动内部最早支持的两个业务场景,用户行为分析平台和敏捷 BI 平台。这两个平台的数据主要由分析师或者数仓同学产出,以 T+1 的离线指标为主。考虑到 ClickHouse 并不支持事务,为了保障数据的一致性,我们在 ClickHouse 系统外实现了一套外部事务:

数仓同学一般会在 HDFS/Hive 准备好原始数据;数据就绪后,会执行一个基于 Spark 的 ETL 服务,将数据切成 N 份再存回 HDFS(必要的话也会做一些数据的预处理);再发起 INSERT Query 给 ClickHouse 集群的每一个 shard,将对应的数据文件从 HDFS 中直接导入到 MergeTree 表中,需要注意的是,这里没有把数据写入分布式表(i.e. Distributed table)中;每个节点上的 MergeTree 表写入成功之后,会由外部事务校验整个集群的数据是否写入成功:如果部分节点导入失败,外部的导入服务会将部分写入的数据回滚并重新执行导入任务,直到数据完全导入成功,才允许上层的分析平台查询数据。也就是说,当 ClickHouse 中仅有不完整的数据时,外部的查询服务 不会查询当天的数据。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

除了离线的场景,也有业务方希望执行 INSERT Query 将数据即时地导入 ClickHouse 中,从而能查询到实时的数据。然而,我们曾经出现过由于业务同学高频写入数据,导致文件系统压力过大最后无法正常查询的线上问题。

这里我解释一下直接写入数据的风险:

直接写入的风险

用户写入 ClickHouse 一般有两种选择:分布式表(i.e. Distributed),MergeTree 表:

写入分布式表:

数据写入分布式表时,它会将数据先放入本地磁盘的缓冲区,再异步分发给所有节点上的 MergeTree 表。如果数据在同步给 MergeTree 里面之前这个节点宕机了,数据就可能会丢失;此时如果在失败后再重试,数据就可能会写重。因而,直接将数据写入用分布式表时,不太好保证数据准确性的和一致性。

当然这个分布式表还有其他问题,一般来说一个 ClickHouse 集群会配置多个 shard,每个 shard 都会建立 MergeTree 表和对应的分布式表。如果直接把数据写入分布式表,数据就可能会分发给每个 shard。假设有 N 个节点,每个节点每秒收到一个 INSERT Query,分发 N 次之后,一共就是每秒生成 NxN 个 part 目录。集群 shard 数越多,分发产生的小文件也会越多,最后会导致你写入到 MergeTree 的 Part 的数会特别多,最后会拖垮整个文件的系统。

写入 MergeTree 表:

直接写入 MergeTree 表可以解决数据分发的问题,但是依然抗不住高频写入,如果业务方写入频次控制不好,仍然有可能导致 ClickHouse 后台合并的速度跟不上写入的速度,最后会使得文件系统压力过大。

所以一段时间内,我们禁止用户用 INSERT Query 把数据直接写入到 ClickHouse。

典型案例-推荐系统

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

业务需求

随着 ClickHouse 支持的业务范围扩大,我们也决定支持一些实时的业务,第一个典型案例是推荐系统的实时数据指标:在字节跳动内部 AB 实验 应用非常广泛,特别用来验证推荐算法和功能优化的效果。

最初,公司内部专门的 AB 实验平台已经提供了 T+1 的离线实验指标,而推荐系统的算法工程师们希望能更快地观察算法模型、或者某个功能的上线效果,因此需要一份能够实时反馈的数据作为补充。他们大致有如下需求:

  1. 研发同学有 debug 的需求,他们不仅需要看聚合指标,某些时间还需要查询明细数据。
  2. 推荐系统产生的数据,维度和指标多达几百列,而且未来可能还会增加。
  3. 每一条数据都命中了若干个实验,使用 Array 存储,需要高效地按实验 ID 过滤数据。
  4. 需要支持一些机器学习和统计相关的指标计算(比如 AUC)。
clickhouse适用场景:ClickHouse 在实时场景的应用和优化

当时公司也有维护其他的分析型引擎,比如 Druid 和 ES。ES 不适合大批量数据的查询,Druid 则不满足明细数据查询的需求。而 ClickHouse 则刚好适合这个场景。

  1. 对于明细数据这个需求:ClickHouse > Druid。
  2. 对于维度、指标多的问题,可能经常变动,我们可以用 Map 列的功能,很方便支持动态变更的维度和指标。
  3. 按实验 ID 过滤的需求,则可以用 Bloom filter 索引。
  4. AUC 之前则已经实现过。

这些需求我们当时刚好都能满足。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

方案设计和比较

常规方案:

比较常规的思路,是用 Flink 消费 Kafka,然后通过 JDBC 写入 ClickHouse。

优点: 各个组件职责划分清楚、潜在扩展性强

缺点: 需要额外资源、写入频次不好控制、难以处理节点故障、维护成本较高

关键是后面两点:由于缺少事务的支持,实时导入数据时难以处理节点故障;ClickHouse 组技术栈以 C++为主,维护 Flink 潜在的成本比较高。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

Kafka Engine 方案:

第二个方案,则是使用 ClickHouse 内置的 Kafka Engine。我们可以在 ClickHouse 服务内部建一张引擎类型为 Kafka 的表,该表会内置一个消费线程,它会直接请求 Kafka 服务,直接将 Kafka partition 的数据拉过来,然后解析并完成数据构建。对于一个 ClickHouse 集群而言,可以在每个节点上都建一张 Kafka 表,在每个节点内部启动一个消费者,这些消费者会分配到若干个 Kafka Partition,然后将数据直接消费到对应。

这样的架构相对于使用了 Flink 的方案来说更简单一些,由于少了一次数据传输,整体而言开销会相对小一些,对我们来说也算是补齐了 ClickHouse 的一部分功能(比如 Druid 也支持直接消费 Kafka topic)缺点就是未来可扩展性会更差一些,也略微增加了引擎维护负担。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

Kafka engine 原理

这里简单介绍一下如何使用 kafka 引擎,为了能让 ClickHouse 消费 Kafka 数据,我们需要三张表:首先需要一张存数据的表也就是 MergeTree;然后需要一张 Kafka 表,它负责描述 Topic、消费数据和解析数据;最后需要一个物化视图去把两张表关联起来,它也描述了数据的流向,某些时候我们可以里面内置一个 SELECT 语句去完成一些 ETL 的工作。只有当三张表凑齐的时候我们才会真正启动一个消费任务。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

这是一个简单的例子:最后呈现的效果,就是通过表和 SQL 的形式,描述了一个 kafka -> ClickHouse 的任务。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

最终效果

由于外部写入并不可控、技术栈上的原因,我们最终采用了 Kafka Engine 的方案,也就是 ClickHouse 内置消费者去消费 Kafka。整体的架构如图:

  1. 数据由推荐系统直接产生,写入 Kafka。这里推荐系统做了相应配合,修改 Kafka Topic 的消息格式适配 ClickHouse 表的 schema。
  2. 敏捷 BI 平台也适配了一下实时的场景,可以支持交互式的查询分析。
  3. 如果实时数据有问题,也可以从 Hive 把数据导入至 ClickHouse 中,不过这种情况不多。除此之外,业务方还会将 1%抽样的离线数据导入过来做一些简单验证,1%抽样的数据一般会保存更久的时间。
clickhouse适用场景:ClickHouse 在实时场景的应用和优化

我们在支持推荐系统的实时数据时遇到过不少问题,其中最大的问题随着推荐系统产生的数据量越来越大,单个节点的消费能力也要求越来越大:

改进一:异步构建索引

第一做的改进是将辅助索引的构建异步化了:在社区实现中,构建一个 Part 分为三步:(1)解析输入数据生成内存中数据结构的 Block;(2)然后切分 Block,并按照表的 schema 构建 columns 数据文件;(3) 最后扫描根据 skip index schema 去构建 skip index 文件。三个步骤完成之后才会算 Part 文件构建完毕。

目前字节内部的 ClickHouse 并没有使用社区版本的 skip index,不过也有类似的辅助索引(e.g. Bloom Filter Index, Bitmap Index)。构建 part 的前两步和社区一致,我们构建完 columns 数据之后用户即可正常查询,不过此时的 part 不能启用索引。此时,再将刚构建好数据的 part 放入到一个异步索引构建队列中,由后台线程构建索引文件。这个改进虽然整体的性能开销没有变化,但是由于隐藏了索引构建的时间开销,整体的写入吞吐量大概能提升 20%

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

改进二:支持多线程消费

第二个改进是在 Kafka 表内部支持了多线程的消费:

目前实现的 Kafka 表,内部默认只会有一个消费者,这样会比较浪费资源并且性能达不到性能要求。一开始我们可以通过增大消费者的个数来增大消费能力,但社区的实现一开始是由一个线程去管理多个的消费者,多个的消费者各自解析输入数据并生成的 Input Stream 之后,会由一个 Union Stream 将多个 Input Stream 组合起来。这里的 Union Stream 会有潜在的性能瓶颈,多个消费者消费到的数据最后仅能由一个输出线程完成数据构建,所以这里没能完全利用上多线程和磁盘的潜力。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

一开始的解决方法,是建了多张 Kafka Table 和 Materialized View 写入同一张表,这样就有点近似于多个 INSERT Query 写入了同一个 MergeTree 表。当然这样运维起来会比较麻烦,最后我们决定通过改造 Kafka Engine 在其内部支持多个消费线程,简单来说就是每一个线程它持有一个消费者,然后每一个消费者负责各自的数据解析、数据写入,这样的话就相当于一张表内部同时执行多个的 INSERT Query,最后的性能也接近于线性的提升。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

改进三:增强容错处理

对于一个配置了主备节点的集群,我们一般来说只会写入一个主备其中一个节点。

为什么呢?因为一旦节点故障,会带来一系列不好处理的问题。(1)首先当出现故障节点的时候,一般会替换一个新的节点上来,新替换的节点为了恢复数据,同步会占用非常大的网络和磁盘 IO,这种情况,如果原来主备有两个消费者就剩一个,此时消费性能会下降很大(超过一倍),这对于我们来说是不太能接受的。(2)早先 ClickHouse Kafka engine 对 Kafka partition 的动态分配支持不算好,很有可能触发重复消费,同时也无法支持数据分片。因此我们默认使用静态分配,而静态分配不太方便主备节点同时消费。(3)最重要的一点,ClickHouse 通过分布式表查询 ReplicatedMergeTree 时,会基于 log delay 来计算 Query 到底要路由到哪个节点。一旦在主备同时摄入数据的情况下替换了某个节点,往往会导致查询结果不准。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

这里简单解释一下查询不准的场景。一开始我们有两副本,Replica #1 某时刻出现故障,于是替换了一个新的节点上来,新节点会开始同步数据,白框部分是已经同步过的,虚线黄框是正在恢复的数据,新写入的白色框部分就是新写入的数据。如果此时两个机器的数据同步压力比较大或查询压力比较大,就会出现 Replica #1 新写入的数据没有及时同步到 Replica #2 ,也就是这个绿框部分,大量历史数据也没有及时同步到对应的黄框部分,这个情况下两个副本都是缺少数据的。因此无论是查 Replica #1 还是 Replica #2 得到的数据都是不准的。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

对于替换节点导致查询不准问题,我们先尝试解决只有一个节点消费的问题。为了避免两个节点消费这个数据,改进版的 Kafka engine 参考了 ReplicatedMergeTree 基于 ZooKeeper 的选主逻辑。对于每一对副本的一对消费者,(如上图 A1 A2),它们会尝试在 ZooKeeper 上完成选主逻辑,只有选举称为主节点的消费者才能消费,另一个节点则会处于一个待机状态。一旦 Replica #1 宕机,(如上图 B1 B2 ),B1 已经宕机连不上 ZooKeeper 了,那 B2 会执行选主逻辑拿到 Leader 的角色,从而接替 B1 去消费数据。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

当有了前面的单节点消费机制,就可以解决查询的问题了。假设 Replica #1 是一个刚换上来的节点,它需要同步黄框部分的数据,这时候消费者会与 ReplicatedMergeTree 做一个联动,它会检测其对应的 ReplicatedMergeTree 表数据是否完整,如果数据不完整则代表不能正常服务,此时消费者会主动出让 Leader,让副本节点上的消费者也就是 Replica #2 上的 C2 去消费数据。

也就是说,我们新写入的数据并不会写入到缺少数据的节点,对于查询而言,由于查询路由机制的原因也不会把 Query 路由到缺少数据的节点上,所以一直能查询到最新的数据。这个机制设计其实和分布式表的查询写入是类似的,但由于分布表性能和稳定原因不好在线上使用,所以我们用这个方式解决了数据完整性的问题。

小结一下上面说的主备只有一个节点消费的问题

配置两副本情况下的 Kafka engine,主备仅有一个节点消费,另一个节点待机。

  1. 如果有故障节点,则自动切换到正常节点消费;
  2. 如果有新替换的节点无法正常服务,也切换到另一个节点;
  3. 如果不同机房,则由离 Kafka 更近的节点消费,减少带宽消耗;
  4. 否则,由类似 ReplicatedMergeTree 的 ZooKeeper Leader 决定。

典型案例-广告投放实时数据

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

业务背景

第二个典型案例是关于广告的投放数据,一般是运营同学需要查看广告投放的实时效果。由于业务的特点,当天产生的数据往往会涉及到多天的数据。这套系统原来基于 Druid + Superset 实现的,Druid 在这个场景会有一些难点:

难点一:产生的实时数据由于涉及到较多的时间分区,对于 Druid 来说可能会产生很多 segment,如果写入今天之前的数据它需要执行一些MR的任务去把数据合并在一起,然后才能查历史的数据,这个情况下可能会导致今天之前的数据查询并不及时。

难点二:业务数据的维度也非常多,这种场景下使用 Druid 预聚合的效率并不高。

对比 Druid 和 ClickHouse 的特点和性能后,我们决定将该系统迁移到 ClickHouse + 自研敏捷 BI。最后由于维度比较多,并没有采用预聚合的方式,而是直接消费明细数据。

因为业务产生的数据由 (1) 大量的当天数据和 (2) 少量的历史数据 组成。历史数据一般涉及在 3 个月内,3 个月外的可以过滤掉,但是即便是 3 个月内的数据,在按天分区的情况下,也会因为单批次生成的 parts 太多导致写入性能有一定下降。所以我们一开始是把消费的 block_size 调的非常大,当然这样也有缺点,虽然整个数据吞吐量会变大,但是由于数据落盘之前是没法查到数据的,会导致整体延时更大。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

改进一:Buffer Engine 增强

单次写入生成过多 parts 的问题其实也有方案解决。社区提供了 Buffer Engine,可以在内存中缓存新写入的数据,从而缓解 parts 高频生成的问题。不过社区文档也介绍了,Buffer Engine 的缺点是不太能配合 ReplicatedMergeTree 一起工作。如果数据写入到了一对副本(如上图),那么 Buffer #1 和 Buffer #2 缓存的数据其实是不一样的,两个 Buffer 仅缓存了各自节点上新写入的数据。对于某个查询而言,如果查询路由到 Replica #1,那查询到的数据是 MergeTree 部分的数据加上 Buffer #1,这部分的数据其实是和 Replica #2 的 MergeTree 加上 Buffer2 的数据并不等价,即便 MergeTree 的数据是相同的。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

针对社区版 Buffer Table 存在的问题,我们也做了相应改进。

(1) 我们选择将 Kafka/Buffer/MergeTree 三张表结合起来,提供的接口更加易用;

(2) 把 Buffer 内置到 Kafka engine 内部, 作为 Kafka engine 的选项可以开启/关闭;

(3) 最重要的是支持了 ReplicatedMergeTree 情况下的查询;

(4) Buffer table 内部类似 pipeline 模式处理多个 Block。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

这里解释一下我们如何解决查询一致性的问题。前面提到,目前一对副本仅有一个节点在消费,所以一对副本的两个 Buffer 表,只有一个节点有数据。比如 Consumer #1 在消费时,Buffer #1 就是有缓存数据,而 Buffer #2 则是空的。

对于任何发送到 Replica #1 的查询,数据肯定是完整的;而对于发送到 Replica #2 的查询则会额外构建一个特殊的查询逻辑,从另一个副本的 Buffer #1 读取数据。这样发送到 Replica #2 的查询,获取到数据就是绿框部分也就是 Replica #2 的 MergeTree 再加上 Replica #1 的 Buffer,它的执行效果是等价于发送到 Replica #1 的查询。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

改进二:消费稳定性增强

由于业务数据的分区比较分散,某个批次的写入往往生成多个 parts。以上图为例,如果某个批次消费到 6 条数据,假设可以分为 3 个 part(比如涉及到昨天、今天、大前天三天数据),第一条和第四条写入到第一个 part,第二第五条数据写入到第二个 part,这时候服务宕机了,没有及时写入第三第六条数据。

由于 ClickHouse 没有事务的支持,所以重启服务后再消费时,要么会丢失数据 {3, 6},要么会重复消费 {1, 4, 2, 5}。对于这个问题我们参考了 Druid 的 KIS 方案自己管理 Kafka Offset, 实现单批次消费/写入的原子语义:实现上选择将 Offset 和 Parts 数据绑定在一起,增强了消费的稳定性。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

每次消费时,会默认创建一个事务,由事务负责把 Part 数据和 Offset 一同写入磁盘中:如果消费的途中写入 part #1 part #2 失败了,事务回滚的时候会把 Offset 和 part #1 part #2 一并回滚,然后从 Part #1 的位置重新消费并重试提交 offset 1-3。

实践&经验

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

接入平台

很早的时候为了推广 ClickHouse 消费 Kafka 的方案,我们做了一个接入平台,这个平台可以创建、审核、管理 Kafka -> ClickHouse 的消费任务。前面介绍到了创建一个消费任务需要三张表,直接建表的学习成本比较高,所以这个平台提供这样一个简单易用的页面来完成接入任务。

这里解释一下框起来的两个部分:

首先是查询粒度,如果大家有听第一场分享就大概知道,我们目前对物化视图做了一些改进,假如查询粒度选了 5 分钟或 10 分钟,那消费数据时数据会像 Druid 一样提前对数据预聚合。而查询的时候也会做一些查询改写,用来达到类似 Druid 的效果,目的是为了覆盖公司内部一些用 Druid 的场景。

为简化用户的使用成本,用户也不用挨个填写 Table 的 Schema,而是从 Kafka 的数据里直接推断出 schema。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

推断的 schema 是这个样子,用户可以填写一些简单的表达式来做一些聚合 & 转换的工作。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

我们也在其他的平台集成了 Kafka -> ClickHouse 的功能:比如说敏捷 BI 平台,它可以直接支持将 Kafka Topic 作为数据集。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

诊断能力增强

前面提到,Kafka engine 方案有一个弊端是增加了引擎端的运维负担。在推广过程中,运维压力也越来越重,我们开发了相应的工具来辅助诊断和运维。我们参考社区 system 表实现了用来辅助诊断 Kafka 消费的表,比如 system.kafka_log 和 system.kafka_tables。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

system.kafka_log 表:每当有消费的事件发生的时,会写入一条诊断日志,比如从 Kafka partition 拉取数据对应了POLL事件;而写入数据则会对应 WRITE 时间;一旦有异常产生,也会产生专门记录异常的 EXCEPTION 事件。按时间和各类事件聚合之后,可以统计一段时间内的消费量和写入量,也可以通过异常信息去定位和诊断线上问题。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

<一个使用案例>

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

<前面 Query 的查询结果>

如上图,我们可以通过 exception 得知业务方的数据和表的 schema 匹配不上,因而触发了解析异常。同时,也可以到错误消息的 topic、partition、offset。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

当然业务方一般不会直接用到这个功能,而是通过运维平台查询消费是否有异常。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

这个是 Kafka Tables,这里提供了关于 Kafka engine 的基本信息。最常用的是 assigned partition,可以快速定位某个具体节点消费了哪些 Kafka partition。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

SQL 增强

我们也扩展了一些常用的 query,比如 SYSTEM START/STOP 和 RESTART,可以比较快速地关闭、重启消费;比如 ALTER Query 的扩展支持,在不用重建表的情况下变更表的 schema。

未来展望和计划

小结

简单来说在字节内部的应用场景主要分为四类:AB 实验、业务实时数据、服务的后台日志数据、机器的监控数据。Kafka Engine 的改进主要以稳定性改进为主,同时也做了部分性能上的改进。为了方便业务接入,我们也提供了配套的平台和接口,除了自己运维的平台,也和字节内部其他服务做了集成。运维层面则增加了 system table 和 system query 等一系列工具来辅助诊断,简化操作。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

目前字节内部仍然没有 MySQL 同步到 ClickHouse 的场景。之前虽然有开发一个简单的方案,但是因为写入和消费不够稳定,并没有在线上使用。因为 MySQL 同步 ClickHouse 时一旦数据出错,那么 ClickHouse 很难再和 MySQL 保持一致了,需要一些额外手段去修复。我们目前有重新设计一套更完整的方案,未来能够支持 TP 数据库的同步,以及支持直接 UPDATE/DELETE Query 直接更新 ClickHouse 的数据。

clickhouse适用场景:ClickHouse 在实时场景的应用和优化

未来展望

未来我们计划持续投入人力来完善 ClickHouse 写入的功能。

(1)第一步是实现在 ClickHouse 上分布式事务,以此解决 Kafka engine 消费以及 INSERT Query 不稳定的问题。

(2)之后会尝试实现读写分离,将消费数据的节点与查询节点隔离;再基于读写分离做消费节点的动态伸缩。

(3)分开的消费/写入节点做为专门的写入层,后续会引入 WAL 和 Buffer 解决高频写入的问题。如果有必要的话,也会在写入层实现类似分布式表分发数据的功能。

一旦上面的功能实现成熟,会考虑重新开放业务直接使用 INSERT Query 写入数据。

本文链接:https://www.dzdvip.com/37961.html 版权声明:本文内容均来源于互联网。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 395045033@qq.com,一经查实,本站将立刻删除。
(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年8月27日 15:27
下一篇 2022年8月28日 01:30

相关推荐

  • 旧电脑如何装固态硬盘(旧电脑怎么加装固态硬盘)

    一个同事,觉得电脑启动太慢了,想装一个固态硬盘。我开始也没装过,我走过一些弯路, 我开始以为把数据线和电源线连接好就可以了,然后没什么效果。 因为这个不像装新电脑,从一开始装,开始一头雾水。 本来我那个同事电脑有问题, 连接显示器横着放,显示器连接有问题,我开始都懵逼了,是固态硬盘插错了吗,当时很懵逼。 步骤1:你得买个固态硬盘,然后还有一条数据线线。 步骤2:打开机箱,固定固态硬盘, 连接数据线和电源线。   步骤3:找一个U盘系统盘, 然后f12进入bios系统,进入设置启动盘为u盘系统盘。 步骤4:给固态硬盘装上系统,如果要分区的话,也可以分。 步骤5:系统装好之后,把启动盘改为这个固态硬盘。

    2021年9月17日
    29
  • 人死后去哪里了(人死后会去哪里)

    “科学的说法,人死后会去火葬场,然后就是化骨扬灰。迷信的说法,人死后身体死了,但精神不灭。人的灵魂还存在,会通过各种传说去往各种地方。中国人的传说就是会通过牛头马面两勾魂鬼差的接引去往地府,接受传说中的地狱各代阎王的赏恶扬善处罚。外国人的传说跟中国人的不一样,但结果基本相同,为善者上天堂,为恶者下地狱。 死亡是一个人人忌讳的话题,但所有人终将面对,关于死亡之后的事情,没有答案,因为从来都没有人复述这个过程!但在这个世界上,有一些特殊经历的人,比如有过濒死体验的朋友,似乎经历过死亡,又似乎只是接近死亡,也许将会给我们一些启示。 木内鹤彦的经历,让人目瞪口呆 准确地说木内鹤彦并不是一位天文学家,而是一名彗星搜索猎人,不过很多人都在以“天文学家”相称,他出生于1954年,在1960年代观测过池谷·关彗星(C/1965 S1)后开始对天文观测开始感兴趣。 池谷·关彗星 不过事与愿违,木内鹤彦后来从事了飞行技能测试相关的工作,但并不是一名飞行员。1976年,22岁的木内鹤彦因为十二指肠受到脊椎和动脉压迫住院,这是上肠系膜动脉症候群,一度病危,医生将他从生死线上抢救了回来,经历了40分钟的濒死体验! 在这次濒死体验中,木内鹤彦经历了亮光、隧道和花海,还有死去的亲人,看起来这是濒死体验者的常规经历。 此后天文一直都是他的爱好,只要天气合适,他就扛着望远镜上山观测,后来的好身体也拜这些无意中的锻炼所赐,他也在后来的天文同好交流中数次谈起这次经历。在几十年的观测中,也成绩斐然,比如35岁时发现了“木内-中村彗星”((1990年) C/1990 E1),39岁时又发现了备受瞩目的“斯威夫特,塔特尔彗星”(再次发现,没有命名权)。 2009年7月,木内鹤彦带队日食观赏团来到上海观测日食,结果因为胃穿孔经历了一次濒死体验,后来转院到杭州,在手术过程中,冠状静脉破裂大出血,再次经历了濒死体 木内鹤彦总共经历了三次濒死体验,这样的案例比较罕见,而木内鹤彦则称第一次体验他看到了亲人,但到了第二次时他发现可以自由穿梭,进入人的身体,当木内正在抢救时他曾进入爸爸的身体,告诉他没事,而他爸爸事后称听到了儿子的声音。 木内发现只要想着某个人就会来到他的身边,他曾瞬移到母亲身边,刚好他母亲和姐姐聊天,后来告诉他母亲和姐姐这件事,她们惊讶得目瞪口呆。 第三次濒死体验则更神奇,他发现还能穿越到未来和过去,其中…

    2022年8月22日
    38
  • SEO优化:网站里的死链接怎么处理?

    所谓死链,句话是“打不开的链接”,般情况下所产生的死链是因为网页被删除、网站改版(原来旧URL由于站点改版URL发生了新的变化,如果大家不理解的话,可以这样思考,网站改版后正确的URL是改版后的链接,当用户输入原来的URL地址时是错误的链接因此该页面不存在)、数据库错误或者是程序自动生成等原因。

    2021年4月26日
    22
  • 全球最受欢迎的手机APP有哪些?

    既然是全球最受欢迎的应用榜单,我们根据几个具有代表的大市场数据,然后来获取全球的应用受欢迎程度。注意这是实时榜单,不是累积榜单!

    2021年4月15日
    70
  • 抖音打造爆款运营方法

    壹零增长CEO飞扬进行了精彩的内容分享,他分享的主题是《如何借势抖音打造超级爆款》。 我是从2006年开始进入互联网行业,当时和阿北、大丫等一起写博客。我的专业是市场营销。当年做互联网,产品是第一位。因为当时没有产品经理,需要自己去了解相关领域。 从06年到2018年,从互联网到移动互联网,我比较幸运,只管产品和增长。美妆性APP是当时独立APP中的领头羊,行业影响力和营收各方面都不错。 后来我们遇到了一个很大的瓶颈——移动互联网的时代结束了,也可以说是中国的人口红利、移动流量红利已经结束。 在2018年底,我预判互联网已经变成底层的基础设施,未来可能会进入到内容互联网时代。因此,我在2019年创立了美新。 美新最开始主要做抖音的ROI投放,属于星图最早的服务商。当时我不仅是公司的产品经理,也是CEO。基于当时的商业环境,开始做抖音投放业务。 前三年,我们服务了花西子、完美日记等新锐品牌;自然堂、珀莱雅、欧诗漫等本土top品牌。最近一年,则以欧莱雅、戴森、雀巢等国际消费品牌为主。因为这些项目都涉及到消费品的增长,所以我今天会讲一些思维逻辑和方法论的体系,以及当下爆款的产品、爆红的新消费做增长的方法。 一、品牌面临的投放问题与痛点 我们先讲讲投放问题的痛点和重点。现阶段的消费品,实现0到1的突破后,都会面临流量增长的问题。因为只要大家抓住任何一波红利或平台机会,基本都可以完成0到1的增长。 但是在1到10,10到100的过程中,流量成本会越来越贵。便宜的流量已经被买完了,后面的成本自然是水涨船高。随着时间增长,竞争也在不断加剧。因此流量上升必然导致ROI下降。 三年的时间内,不管哪个短视频平台,都会有新的流量红利。不过,抖音的流量红利最大,而且在不同的时间都会有红利机会。 由于我们自认为窗口时间很短,再加上部分局部现象的干扰,品牌往往会发现结果是一个巨大的陷阱。如果CEO把时间放在抓住红利上,对于产品增长,他的认知就是KPI等于ROI。 他会认为投放的这个环节,约等于ROI的目标。但是流量不断变贵,显然ROI会不断下滑,由此慢慢开始变成恶性循环。 不知道大家有没有发现,前两年增长特别好的新锐品牌,今年的ROI都在不断下滑,而且他们核心团队的人员也在不断流失。因为之前的方法今年不管用了,所以他们团队的信心、品牌的信心以及投放效率都发生了变化。团队核心人员可以跳槽到其它公…

    2021年11月28日
    37
  • 济南旅游攻略(济南旅游攻略自由行路线推荐)

    “市区 路线:趵突泉-五龙潭-大明湖-曲水亭街-芙蓉街-泉城广场-黑虎泉-解放阁-宽厚里-千佛山-山东博物馆” 济南,别称泉城,是山东省省会,是山东省政治、经济、文化、科技、教育和金融中心,重要的交通枢纽。地处中国华东地区、山东省中部、华北平原东南部边缘,是中国人民解放军北部战区陆军机关驻地,济南因境内泉水众多,拥有“七十二名泉”,素有“四面荷花三面柳,一城山色半城湖”的美誉,济南八景闻名于世,是拥有“山、泉、湖、河、城”独特风貌的旅游城市,是国家历史文化名城、首批中国优秀旅游城市,史前文化——龙山文化的发祥地之一。 一、主要旅游景点 到了济南,去感受一下济南的美景,如果不是深度游,以下主要旅游景点足够你了解济南了。济南交通便利,景点相对集中,市区内公共交通便利,建议乘坐公共交通工具出行。 山东省济南市主要旅游景点 序号 景点名称 门票 游玩 时间位置1趵突泉403h历下2大明湖景区免费3h历下3千佛山302-3h历下4黑虎泉免费2-3h历下5泉城广场免费1h历下6九如山风景区1205-6h历城7红叶谷805-7h历城8五龙潭公园免费1-2h历下9济南动物园253h天桥10灵岩寺502-3h长清11山东博物馆免费1-2h历下12野生动物世界1605h章丘13九顶塔民俗园1204-5h历城14水帘峡904-4h历城15大明湖海底世界904-5h历城 二、济南美食 到了济南不要辜负了济南的美食。 济南美食 序号 美 食 1 油旋 2 九转大肠 3 糖醋鲤鱼 4 爆炒腰花 5 甜沫 6 打卤面 7 坛子肉 济南的美食相对集中,你可以去美食一条街品尝。 济南美食街 序号 名 称 1 芙蓉街 2 宽厚里美食街 3 大观园小吃街 4 经十一路美食街 5 回民烧烤一条街 6 文化路美食街 7 花园路美食街 8 山大路美食街 9 胜利大街美食街 10 祝舜路美食街

    2022年8月1日
    16