使用ClickHouse UDF与OpenAI模型集成

图片

本文字数:14683;估计阅读时间:37 分钟

作者:Dale McDiarmid

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

图片

Meetup活动

ClickHouse Shenzhen User Group第1届 Meetup 火热报名中,详见文末海报!

介绍

在ClickHouse中,用户可以直接在其SQL中调用AI模型。这可以在插入数据时丰富数据的形式,或者在查询时补充特定的结果。虽然许多用户习惯于训练自己的领域特定模型,但对于较小的团队或用例,这通常是不切实际的。在这些情况下,预构建的“即插即用”模型或服务通常就足够,并且可以在付出最小努力的情况下获得良好的结果。

在本文中,我们演示了:

  • 如何使用ClickHouse用户定义的函数(UDF)轻松集成第三方API,这些API提供“AI as a Service”

  • 如何在ClickHouse中,直接调用这些“即插即用”模型完成特定任务,如情感分析,并针对这些结果进行聚合,以计算有关给定主题的正面和负面帖子数量等指标

鉴于OpenAI最近的知名度和备受关注的ChatGPT服务,我们以OpenAI为例。然而,这种方法的简单性意味着可以轻松地适应其他AI服务。

用户定义的函数(UDF)

ClickHouse中的UDF(用户定义的函数)有几种形式。在最近的一篇文章中,我们分享了:如何使用ClickHouse SQL定义的函数查询Hugging Face中托管的外部数据集。虽然诸如此类的SQL定义的函数对于概括常见的SQL任务非常有用,但有时用户需要熟悉的编程语言的全部功能。为此,ClickHouse支持可执行的UDF。这为开发人员提供了调用任何外部可执行程序或脚本来处理数据的灵活性。在我们下面的简单示例中,我们将使用这个功能来调用简单的Bash和Python脚本,这些脚本将查询OpenAI API。我们将展示API响应如何自动丰富由ClickHouse插入或查询的数据。

图片

使用OpenAI

大多数用户通过流行的ChatGPT服务熟悉OpenAI,该服务已经改变了工作行为和日常任务。OpenAI为企业提供了访问ChatGPT模型的REST API,以在现有服务和自动化流程中使用。这些服务提供从聊天和嵌入生成到图像生成和语音转文本的所有方式。我们的示例专注于聊天完成,这可以用于更通用的任务,如实体提取和情感标记。

注意:访问OpenAI服务的所有请求都需要一个令牌 - 在下面的示例中作为环境变量OPENAI_API_KEY传递。用户可以注册试用版,并获得足够的免费积分来执行这里的示例。

除了能够充当聊天机器人外,OpenAI的完成(completion)服务还支持其他任务,如情感分析和结构提取。对于这些任务,开发人员必须通过系统角色提供相关说明,以描述期望的行为。执行情感分析的示例REST API请求可能如下所示。在这里,我们要求服务对论坛帖子进行分类。请注意,我们需要提供明确的说明,以仅返回指定情感的单个令牌:

curl https://api.openai.com/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer $OPENAI_API_KEY" \-d '{"model": "gpt-3.5-turbo","messages": [{"role": "system","content": "You are an AI language model trained to analyze and detect the sentiment of forum comments."},{"role": "user","content": "Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."}],"temperature": 0,"max_tokens": 256
}'{"id": "chatcmpl-7vOWWkKWGN7McODMXJzQB6zzDcx0r","object": "chat.completion","created": 1693913320,"model": "gpt-3.5-turbo-0613","choices": [{"index": 0,"message": {"role": "assistant","content": "NEGATIVE"},"finish_reason": "stop"}],"usage": {"prompt_tokens": 147,"completion_tokens": 2,"total_tokens": 149}
}

请注意,这里我们使用更具成本效益的gpt-3.5-turbo模型,而不是最新的gpt-4模型。前者对于示例目的已足够。我们将其性能水平的评估留给读者。

相同的服务也可以用于提取结构。假设我们希望从上述文本中提取所提到的技术,作为字符串值的列表。我们需要稍微修改一下说明:

curl https://api.openai.com/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer $OPENAI_API_KEY" \-d '{"model": "gpt-3.5-turbo","messages": [{"role": "system","content": "You are an AI language model trained to extract entities from forum comments"},{"role": "user","content": "From the following text extract the many technologies mentioned as a comma seperated list: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."}],"temperature": 0,"max_tokens": 20
}'{"id": "chatcmpl-7vOdLnrZWeax3RxjeUNelCTdGvr8q","object": "chat.completion","created": 1693913743,"model": "gpt-3.5-turbo-0613","choices": [{"index": 0,"message": {"role": "assistant","content": "BigQuery, Databricks, Spark, ClickHouse"},"finish_reason": "stop"}],"usage": {"prompt_tokens": 122,"completion_tokens": 11,"total_tokens": 133}
}

关于上述请求参数的一些建议:

  • 我们将temperature设置为0,以从响应中删除任何随机性。对于这些用例,我们不需要创造性的文本,只需要确定性的文本分析。

  • 在两种情况下,我们设置max_tokens以确定响应的长度。一个token大约是3/4个词。因此,我们调整了我们的请求。

数据集

对于我们的示例数据集,我们使用了Hacker News的帖子。这个数据集在我们的公共play环境中可用,包含从2006年到2023年8月的流行Hacker News论坛上的所有帖子和评论,约有3700万行。表模式如下所示。

我们对titletext列感兴趣。我们将探索这个数据集的任务留给读者,如果希望将这个数据集的最新版本加载到你自己的ClickHouse实例中,可以按照这里的说明操作。或者,我们提供了一个在S3上的Parquet文件,可以使用如下所示的s3函数加载:

CREATE TABLE hackernews
(`id` UInt32,`deleted` UInt8,`type` Enum8('story' = 1, 'comment' = 2, 'poll' = 3, 'pollopt' = 4, 'job' = 5),`by` LowCardinality(String),`time` DateTime,`text` String,`dead` UInt8,`parent` UInt32,`poll` UInt32,`kids` Array(UInt32),`url` String,`score` Int32,`title` String,`parts` Array(UInt32),`descendants` Int32
)
ENGINE = MergeTree
ORDER BY idINSERT INTO hackernews SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/hackernews/2023-08-18.parquet')

添加情感分析

对于我们的示例,假设我们希望为存储在ClickHouse中的Hacker News数据添加情感分析。为此,我们需要通过ClickHouse UDF调用之前的OpenAI REST API。这个请求的简单性意味着:即使是一个简单的bash脚本可能也足够,如下所示(下面需要jq)。稍后,我们将演示如何直接在Python中执行此操作。

#!/bin/bashwhile read read_data; dosentiment=$(curl -s https://api.openai.com/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer <insert>" \-d "{\"model\": \"gpt-3.5-turbo\",\"messages\": [{\"role\": \"system\",\"content\": \"You are an AI language model trained to analyze and detect the sentiment of forum comments.\"},{\"role\": \"user\",\"content\": \"Analyze the following Hacker News comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: ${read_data}\"}],\"temperature\": 0,\"max_tokens\": 2,\"temperature\": 0
}" | jq -r '.choices[0].message.content')printf "$sentiment";
done

这个脚本应该保存在ClickHouse的user_scripts目录中,命名为sentiment.sh,并设置为可执行。还应该在一个文件openai_functions.xml中添加以下条目,并保存到ClickHouse配置目录(通常是/etc/clickhouse-server/)。

<functions><function><name>sentiment</name><type>executable</type><format>TabSeparated</format><return_type>String</return_type><argument><type>String</type></argument><command>sentiment.sh</command><command_read_timeout>10000</command_read_timeout><command_write_timeout>10000</command_write_timeout><max_command_execution_time>10000</max_command_execution_time></function>
</functions>

这个配置使得UDF可用于ClickHouse。除了在这里修改超时以允许OpenAI请求的延迟之外,我们提供了一个函数名sentiment,并指定了输入和返回类型。

有了上述配置,用户可以通过简单的函数调用请求文本片段的情感,例如:

SELECT sentiment('Learn about the key differences between ClickHouse Cloud and Snowflake and how ClickHouse Cloud outperforms Snowflake across the critical dimensions for real-time analytics: query latency and and cost.') AS sentiment┌─sentiment─┐
│ POSITIVE  │
└───────────┘1 row in set. Elapsed: 0.433 sec.

虽然上面的例子可以让我们开始,但可能需要一个更健壮的解决方案,具有错误处理的功能。为此,我们可能希望将上述内容转换为Python。下面的Python脚本添加了基本的错误处理和带有回退的重试。后者是为了特别解决OpenAI速率限制的挑战 - 请参阅处理延迟和速率限制以获取更多详细信息。

请注意,需要openai和tenacity库来处理API请求和速率限制。

#!/usr/bin/python3
import sys
import openai
from tenacity import (retry,stop_after_attempt,wait_random_exponential,
)openai.api_key = "<INSERT>"
request_timeout = 3@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(20))
def completion_with_backoff(**kwargs):return openai.ChatCompletion.create(**kwargs)def extract_sentiment(text):if text == "":return "NEUTRAL"messages = [{"role": "system","content": "You are an AI language model trained to analyze and detect the sentiment of hackernews forum comments."},{"role": "user","content": f"Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. "f"Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: {text}"}]try:response = completion_with_backoff(model="gpt-3.5-turbo", messages=messages, max_tokens=30, temperature=0, request_timeout=request_timeout)return response.choices[0].message.contentexcept:return "ERROR"for size in sys.stdin:# collect a batch for performancefor row in range(0, int(size)):print(extract_sentiment(sys.stdin.readline().strip()))sys.stdout.flush()

服务的基于聊天的性质使得在单个请求中评估多个文本片段的情感变得具有挑战性。为了使这些示例保持简单,我们每行进行一次请求。一个更优化的解决方案可能会对请求进行批处理,并要求端点评估一组文本。

上述假设:从ClickHouse传递的任何输入,都包括一个行数的前缀。这用于确定后续输入要迭代的次数。这可以使Python脚本内的操作进行批处理以获得更高的性能。

除了定义唯一名称sentiment_p之外,上述函数的配置还有一些额外的设置。我们将type设置为可执行池,以提高吞吐性能。这将启动命令N次(下面是10次),允许多个并发的调用。设置send_chunk_header确保在任何输入之前有一个表示要处理的行数的数字标题。我们增加了超时设置,以防传递大块的行。

<functions><function><name>sentiment_p</name><type>executable_pool</type><pool_size>10</pool_size><send_chunk_header>true</send_chunk_header><format>TabSeparated</format><return_type>String</return_type><argument><type>String</type></argument><command>sentiment.py</command><command_read_timeout>10000000</command_read_timeout><command_write_timeout>10000000</command_write_timeout><max_command_execution_time>1000000</max_command_execution_time></function>
</functions>

我们可以将上述任何一个函数应用于列的一组行。在下面的示例中,我们请求包含单词ClickHouse的10行的标题和文本的情感。

SELECT text, sentiment_p(text) AS sentiment
FROM hackernews WHERE text LIKE '%ClickHouse%' OR title LIKE '%ClickHouse%'
ORDER BY time DESC
LIMIT 2
FORMAT Vertical
Row 1:
──────
text:    Yeah ClickHouse is definitely the way to go here. Its ability to serve queries with low latency and high concurrency is in an entirely different league from Snowflake, Redshift, BigQuery, etc.
sentiment: POSITIVERow 2:
──────
text:    There are other databases today that do real time analytics (ClickHouse, Apache Druid, StarRocks along with Apache Pinot).  I&#x27;d look at the ClickHouse Benchmark to see who are the competitors in that space and their relative performance.
sentiment: POSITIVE2 rows in set. Elapsed: 2.763 sec. Processed 37.17 million rows, 13.30 GB (13.46 million rows/s., 4.82 GB/s.)

只有在最终结果被整理后,UDF才会执行 - 这意味着只需要两个请求。这种方法是理想的,因为对OpenAI的请求的延迟通常比ClickHouse评估查询的时间要长得多。

进一步地,我们可以通过简单的聚合来计算ClickHouse的正面和负面帖子的数量。这会产生更多的开销,因为我们需要对OpenAI API进行1600多次调用。这反映在最终的计时中。

SELECTcount(),sentiment
FROM hackernews
WHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')
GROUP BY sentiment_p(text) AS sentiment
FORMAT PrettyCompactMonoBlock┌─count()─┬─sentiment─┐
│   192 │ NEGATIVE  │
│   628 │ NEUTRAL   │
│   857 │ POSITIVE  │
└─────────┴───────────┘3 rows in set. Elapsed: 203.695 sec. Processed 37.17 million rows, 13.28 GB (182.48 thousand rows/s., 65.21 MB/s.)

处理延迟和速率限制

OpenAI API的实用性受到两个因素的限制:延迟和它施加的速率限制。请注意,这些变量将取决于所选择的“即插即用”模型。在我们的示例中,我们使用OpenAI。还有许多其他选择,每个选择都有其自己的权衡。

延迟将影响查询的最小响应时间。虽然OpenAI允许多个并发查询以确保这不会影响吞吐量,但速率限制将更具限制性。因此,我们建议用户仅将这些API用于自发分析,其中函数仅在结果的小子集上使用(例如我们之前的2行示例),或者在插入时丰富数据。在展示后者的示例之前,让我们探讨一下延迟和速率限制的限制。

我们可以通过修改我们的情感curl请求来使用一个简单的格式文件来评估响应的延迟:

curl -w "@curl-format.txt" -o /dev/null -s  https://api.openai.com/v1/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer $OPENAI_API_KEY" \-d '{"model": "gpt-3.5-turbo","messages": [{"role": "system","content": "You are an AI language model trained to analyze and detect the sentiment of forum comments."},{"role": "user","content": "Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."}],"temperature": 0,"max_tokens": 256,"temperature": 0
}'time_namelookup:  0.081196s
time_connect:  0.084907s
time_appconnect:  0.095853s
time_pretransfer:  0.095937s
time_redirect:  0.000000s
time_starttransfer:  0.095942s
----------
time_total:  0.650401s

这里的总延迟为0.65秒,限制了我们的查询响应时间,但由于我们有一个命令池(上面是10),ClickHouse的并行执行管道可以利用它。然而,这种并行化又受到OpenAPI速率限制的限制。

OpenAI受到每分钟请求数和每分钟令牌数的限制。对于我们的gpt-3.5-turbo模型,这是每分钟90,000个令牌(TPM)和每分钟3,500个请求(RPM)。速率限制因模型和帐户类型而异 - 进一步的细节请参阅此处。

为了解决这个问题,我们在我们的UDF中添加了基本的速率限制。API返回头中包含速率限制信息(即下一分钟剩余的令牌数和请求数)。虽然我们可以开发一个使用这些信息的速率限制函数,但OpenAI建议使用几个专为通过指数回退解决此问题而设计的库。这样做的好处是我们不需要跟踪跨多个线程的请求和令牌使用情况。

我们对聚合查询的上述计时(203.695秒)表明,我们可能没有充分利用我们的10个UDF命令池,或者正在受到速率限制的限制。假设平均延迟为0.65 *,完全并行化,我们预计我们的总执行时间在这里更接近100秒(1600/10 * 0.65 = 104秒)。

*我们假设Open AI API可以保持这种延迟,而不受变量内容长度等因素的影响(一些评论可能比其他评论更长)。

这种性能(100秒)之所以没有实现,是因为查询受到OpenAI API的速率限制的限制 - 具体来说是令牌限制。每个Hacker News评论平均约为330个单词,如下所示,或约80个令牌(每个令牌约4个字符)。但这并不包括我们的提示和系统文本,其中还增加了额外的60个令牌。我们的与ClickHouse相关的子集的平均令牌长度也较高,为136。

SELECTround(avg(length(text))) AS num_chars,round(num_chars * 0.25) AS num_tokens
FROM hackernews┌─num_chars─┬─num_tokens─┐
│     333 │       83 │
└───────────┴────────────┘1 row in set. Elapsed: 1.656 sec. Processed 37.17 million rows, 12.72 GB (22.44 million rows/s., 7.68 GB/s.)SELECTround(avg(length(text))) AS num_chars,round(num_chars * 0.25) AS num_tokens
FROM hackernews
WHERE (title LIKE '%ClickHouse%') OR (text LIKE '%ClickHouse%')┌─num_chars─┬─num_tokens─┐
│     546 │      136 │
└───────────┴────────────┘1 row in set. Elapsed: 1.933 sec. Processed 37.17 million rows, 13.28 GB (19.23 million rows/s., 6.87 GB/s.)
Peak memory usage: 73.49 MiB.

虽然每个评论都需要一个请求,导致总共1600个请求(低于每分钟3500的限制),但我们总共有900k个字符或229k个令牌。考虑到我们的提示文本,这增加到了329k个令牌(每个请求额外增加60个)。这远远超过了每分钟90k的限制。尽管如此,如果这项工作被完美地安排,我们预计这个请求将在我们经历的200秒内完成(329/90〜3.65分钟〜200秒)。

尽管更好的速率限制实现(例如基于通用单元速率算法的实现)可能会更有效地利用Open AI API资源,但请求的延迟最终将受到令牌限制的约束。我们只能使用前N个令牌,其中N的选择基于一个限制,该限制将确保完全利用每分钟3500次的完整请求限制,即90000/3500〜25个令牌。然而,在我们的示例中,这不太可能足以确定情感上述技术。 

在插入时进行提取

鉴于速率限制和延迟,使用API进行查询的更可取的方法是在数据插入时分配情感列。借助其命令池,Python函数更适合进行此类型的批处理处理。下面,在通过INSERT INTO加载行时提取情感。在这个例子中,我们将所有与ClickHouse相关的行插入一个专用表中,为每个计算一个情感列。这种处理方式非常理想,因为新行插入时,Hacker News数据集每分钟接收约8-10行新数据。一旦分配了列,我们就可以在情感列上享受ClickHouse查询速度,而无需进行API请求。

INSERT INTO hackernews_v2 SELECT*,sentiment_p(text) AS sentiment
FROM hackernews
WHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')0 rows in set. Elapsed: 185.452 sec. Processed 37.17 million rows, 13.54 GB (200.44 thousand rows/s., 73.00 MB/s.)SELECT count(), sentiment
FROM hackernews_v2
GROUP BY sentiment┌─count()─┬─sentiment─┐
│   193 │ NEGATIVE  │
│   850 │ POSITIVE  │
│   634 │ NEUTRAL   │
└─────────┴───────────┘3 rows in set. Elapsed: 0.003 sec. Processed 1.68 thousand rows, 1.68 KB (531.10 thousand rows/s., 531.10 KB/s.)
Peak memory usage: 72.90 KiB.

提取结构

为了完整起见,让我们也将之前的OpenAI请求转换为提取我们的帖子中的技术。以下是bash Python脚本:

#!/usr/bin/python3
import sys
import openai
from tenacity import (retry,stop_after_attempt,wait_random_exponential,
)openai.api_key = "<INSERT>"
request_timeout = 3@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(20))
def completion_with_backoff(**kwargs):return openai.ChatCompletion.create(**kwargs)def extract_topics(text):if text == "":return ""messages = [{"role": "system","content": "You are an AI language model trained to extract entities from Hacker News forum comments."},{"role": "user","content": f"From the following text extract the technologies mentioned as a comma separated list with no spaces. Return an empty string if there are no technologies: {text}"}]try:response = completion_with_backoff(model="gpt-3.5-turbo", messages=messages, max_tokens=30, temperature=0,request_timeout=request_timeout)return response.choices[0].message.content.strip()except Exception as e:return f"ERROR - {e}"for size in sys.stdin:# collect a batch for performancefor row in range(0, int(size)):print(",".join([tech.strip() for tech in extract_topics(sys.stdin.readline().strip()).split(",")]))sys.stdout.flush()

配置此函数时,使用与情感UDF相同的参数,只是将名称更改为extract_techs,我们可以在Hacker News上使用ClickHouse识别提到的顶级技术。

WITH results AS (SELECT extract_techs(text) as techsFROM hackernewsWHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')
)
SELECTarrayJoin(splitByChar(',', techs)) AS tech,count() AS c
FROM results
GROUP BY tech
HAVING tech NOT ILIKE '%ClickHouse%' AND tech != ''
ORDER BY c DESC
LIMIT 5┌─tech────────┬───c─┐
│ Postgres  │  78 │
│ PostgreSQL  │  65 │
│ SQL       │  63 │
│ TimescaleDB │  54 │
│ MySQL     │  51 │
└─────────────┴─────┘5 rows in set. Elapsed: 211.358 sec. Processed 37.17 million rows, 13.28 GB (175.87 thousand rows/s., 62.85 MB/s.)
Peak memory usage: 931.95 MiB.

结论

本文展示了如何使用UDF将ClickHouse直接集成到模型提供商,以丰富和添加结构到现有数据中。虽然我们在示例中使用了OpenAI,但类似的“即插即用”模型服务应该同样容易集成。

Meetup 活动报名通知

好消息:ClickHouse Shenzhen User Group第1届 Meetup 已经开放报名了,将于2024年1月6日在深圳南山区海天二路33号腾讯滨海大厦举行,扫码免费报名

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

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

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

相关文章

使用Spring Boot和Vue.js构建一个简单的CRUD应用

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 在本教程中&#xff0c;您将使用Vue.js作为客户端并将Spring Boot作为资源服务器来构…

linux安装 icc编译器,安装 Intel Compiler (ifort icc icpc)

在下载目录下解压heqinheqin-dell:~/Downloads$ tar zxvf parallel_studio_xe_2017_update7.tgz进入解压后的文件夹heqinheqin-dell:~/Downloads$ cd parallel_studio_xe_2017_update7/为了记录过程而不用截图&#xff0c;我选择用命令行安装&#xff0c;当然你也可以用install…

linux 安装mongodb 64,在CentOS 6.x 64bit上安装MongoDB 3.2社区版

基本安装步骤参考: https://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/1) 创建repo源文件:sudo vim /etc/yum.repos.d/mongodb-org-3.2.repo内容如下:[mongodb-org-3.2]nameMongoDB Repositorybaseurlhttps://repo.mongodb.org/yum/redhat/$releasever/mon…

[免费网络研讨会] Java 11的第一印象

一年多以前&#xff0c;我们正焦急地等待新的模块化Java 9的到来。大约在同一时间&#xff0c;引入了一个新的发布周期&#xff0c;该周期将每6个月发布一次新版本&#xff0c;并提供长期支持&#xff08;LTS&#xff09;。每3年发行一次&#xff08;或每6个版本发行一次&#…

linux可以http安装么,Linux 5下 http的安装

Web网站服务(一)http.conf中的全局配置ServerRoot&#xff1a;用于设置httpd服务的根目录&#xff0c;该目录中包括运行Web站点必须的目录和文件。默认根目录为&#xff1a;/usr/local/apache2Listen&#xff1a;用于设置Apache服务器监听的网络端口号&#xff0c;默认为80User…

APIGEE – API网关简介

在本文中&#xff0c;我想简要介绍一下APIGEE。 APIGEE主要提供现成的以下功能作为api网关。 协议转换 与任何协议进行转换&#xff0c;包括SOAP&#xff0c;REST&#xff0c;XML二进制或自定义 交通管理 开箱即用的灵活&#xff0c;分布式配额管理&#xff0c;速率限制和峰…

内存泄漏分析_调查内存泄漏第2部分–分析问题

内存泄漏分析这个小型系列的第一个博客介绍了如何创建一个非常泄漏的示例应用程序&#xff0c;以便我们可以研究解决服务器应用程序上基于堆的问题的技术。 它展示了Producer-Consumer模式的一个大问题&#xff0c;即消费者代码必须能够至少与生产者一样快&#xff08;甚至不是…

将Java Flight Recorder与OpenJDK 11结合使用

Java Flight Recorder&#xff08;JFR&#xff09;曾经是Oracle JDK的商业附加组件。 由于它是与Java Mission Control一起最近开源的&#xff0c;因此使用OpenJDK 11的每个人现在都可以使用此出色的工具免费对Java应用程序进行故障排除。 JFR以前是专有解决方案&#xff0c;对…

c语言开发工具程序代码是什么文件,【C语言】开发工具--GCC使用入门

来自&#xff1a; 51CTO GCC使用入门通常所说的GCC是GUN Compiler Collection的简称&#xff0c;除了编译程序之外&#xff0c;它还含其他相关工具&#xff0c;所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进制代码。GCC是Linux平台下最常用的编…

无服务器安全性:将其置于自动驾驶仪上

Ack &#xff1a;本文是从个人经验以及从无服务器安全性的其他多个来源学到的东西的混合。 我无法在这里列出或确认所有这些信息&#xff1b; 但是&#xff0c;应该特别感谢The Register &#xff0c; Hacker Noon &#xff0c; PureSec以及Serverless Status和Serverless&…

c语言构造报文,构造一个缓冲区溢出的C语言的例子

满意答案wk05122013.06.01采纳率&#xff1a;45% 等级&#xff1a;12已帮助&#xff1a;15719人#include #include #include void function(char *str){char buffer[16];strcpy(buffer, str);}void evilfunc(){printf("Am I Evil?\n");}int main(int argc, char*…

mongodb插入速度每秒_MongoDB事实:商品硬件上每秒插入80000次以上

mongodb插入速度每秒在尝试一些时间序列集合时&#xff0c;我需要一个大型数据集来检查我们的聚合查询在增加数据负载的情况下不会成为瓶颈。 我们解决了5000万份文档&#xff0c;因为超出此数目我们仍然会考虑分片。 每次事件如下所示&#xff1a; {"_id" : Objec…

parallels for linux,在 Parallels Desktop 上安装 Remix OS PC

前言个人觉得呢&#xff0c;像 Remix OS 和 Phoenix OS 这样的国产安卓桌面操作系统还是很划时代的。赋予了安卓平台多任务操作的能力&#xff0c;这可以给二合一设备的体验带来一定的变化&#xff0c;但是不像 Surface 一样后面有巨硬给撑腰可以做大做强起来&#xff0c;但是这…

模拟用户输入并检查输出的简单方法

最近&#xff0c;我的一些学生向我询问了赫尔辛基大学MOOC提供的单元测试的机制&#xff0c;我检查了它们的实现&#xff0c;并认为这对于初学者了解实际发生的情况是有帮助的&#xff0c;因此在此发表了这篇小文章。 我们将以“机场”项目为例&#xff0c;这是OOP2第一周的最…

android bench内存测试,华为p10内存测试软件(androbench) v5.0.1 免费版

华为p10内存测试软件(androbench)其实是androbench这款内存测试软件&#xff0c;可以用于测试你的华为p10&#xff0c;是一款不错的华为p10内存测试软件&#xff0c;可以测试你的手机闪存性能&#xff0c;其他的手机也可以免费测试哦。华为p10内存测试软件介绍AndroBench是衡量…

android对话框字体大小,Android Dialog 设置字体大小的具体方法

先看下面图片&#xff1a;这是我在做登录页面的时候&#xff0c;调用系统的progressdialog 进行等待&#xff0c;可是看起来很不协调&#xff0c;左边的等待图片过大&#xff0c;右边文字过小&#xff0c;看起来老别扭&#xff0c;虽然功能上不存在什么问题&#xff0c;但是我有…

android custom toast,Android自定义Toast

核心代码&#xff1a;package com.huatec.myapplication;import android.content.Context;import android.graphics.Bitmap;import android.support.annotation.ColorInt;import android.support.annotation.DrawableRes;import android.view.Gravity;import android.view.Layo…

华为android打开usb调试模式,华为 PE-CL00 开启USB调试模式

我们要将华为 PE-CL00与电脑进行连接&#xff0c;就必须要打开华为 PE-CL00系统的调试模式&#xff0c;不同的系统版本打开调试模式的方法有所不同&#xff0c;在这里我们就谈谈华为 PE-CL00各种系统版本打开USB调试模式的方法。1、针对Android 2.1-2.2版本的系统&#xff1a;我…

API网关和AWS Lambda进行身份验证

当Foreach最初涉足微服务领域时&#xff0c;我们并没有真正构建微服务。 我们以为我们做到了&#xff0c;但是我们所有的服务中总存在一些逻辑。 当然&#xff0c;每个服务实际上应该只专注于自己的任务&#xff0c;而不应该专注于属于另一个微服务的事物。 我们这方面最明显的…

魅蓝x android 7,魅蓝x2什么时候发布 魅蓝x2发布时间最新消息

日前&#xff0c;魅蓝品牌掌门人李楠或kkk便在微博上放出“bluegate(蓝色大门)”这样一个句子&#xff0c;似乎暗示魅蓝品牌或在近期会有动作&#xff0c;并且由于该条微博的尾巴显示为“下款魅蓝Android”&#xff0c;所以在不少网友看来&#xff0c;或许预示着魅蓝将有新机即…