This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris-website.git
The following commit(s) were added to refs/heads/master by this push: new 5891bc1e838 update workload document (#1612) 5891bc1e838 is described below commit 5891bc1e83805697ae75aa78c21e5a3d197b6f04 Author: wangbo <wan...@apache.org> AuthorDate: Wed Dec 25 22:14:52 2024 +0800 update workload document (#1612) ## Versions - [x] dev - [ ] 3.0 - [ ] 2.1 - [ ] 2.0 ## Languages - [x] Chinese - [ ] English ## Docs Checklist - [ ] Checked by AI - [ ] Test Cases Built --- .../best-practice/group-workload-groups.md | 157 ----- .../best-practice/workload-group-best-practice.md | 412 ----------- .../best-practice/group-workload-groups.md | 155 ----- .../best-practice/workload-group-best-practice.md | 437 ------------ .../workload-management/sql-blocking.md | 28 +- .../workload-management/workload-group.md | 750 +++++++++++++++++---- 6 files changed, 634 insertions(+), 1305 deletions(-) diff --git a/docs/admin-manual/workload-management/best-practice/group-workload-groups.md b/docs/admin-manual/workload-management/best-practice/group-workload-groups.md deleted file mode 100644 index 4d63c3c9fb6..00000000000 --- a/docs/admin-manual/workload-management/best-practice/group-workload-groups.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -{ -"title": "Grouping Workload Groups", -"language": "en" -} ---- - -<!-- -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. ---> - -The Workload Group grouping function is commonly used when there are multiple physically isolated BE clusters in a Doris cluster. Workload Groups can be grouped, and different groups of Workload Groups can be bound to different BE clusters. - -## Recommended usage - -If there are currently two isolated BE sub-clusters in the cluster, named rg1 and rg2, and these two groups are completely physically isolated, with no shared data or computation, the recommended configuration approach is as follows: - -1. Reduce the resource allocation for the normal group as much as possible, serving as a fallback query group. For example, if a query does not carry any Workload Group information, it will automatically use this default group to avoid query failures. - -2. Create corresponding Workload Groups for these two sub-clusters and bind them to the respective sub-clusters. For instance, create the first Workload Group named wg1 for the rg1 cluster, which includes Workload Group a and Workload Group b. Create the second Workload Group named wg2 for the rg2 cluster, which includes Workload Group c and Workload Group d. - -The final effect will be as follows: - - - -The operating process is as follows: - -Step 1: Bind the data replicas to the BE nodes, which essentially completes the division of the rg1 and rg2 sub-clusters, achieving isolation of the data replicas. If the cluster has already completed the division into sub-clusters, this step can be skipped, and you can proceed directly to Step 2. -1. Bind the data replicas to the rg1 and rg2 clusters. -``` --- When creating tables for the rg1 cluster, it is necessary to specify that the replicas are distributed to rg1. -create table table1 -(k1 int, k2 int) -distributed by hash(k1) buckets 1 -properties( - "replication_allocation"="tag.location.rg1:3" -) - --- When creating tables for the rg2 cluster, it is necessary to specify that the replicas are distributed to rg2. -create table table2 -(k1 int, k2 int) -distributed by hash(k1) buckets 1 -properties( - "replication_allocation"="tag.location.rg2:3" -) -``` - -2. Bind the BE nodes to the rg1 and rg2 clusters. -``` --- Bind be1 and be2 to the rg1 cluster. -alter system modify backend "be1:9050" set ("tag.location" = "rg1"); -alter system modify backend "be2:9050" set ("tag.location" = "rg1"); - --- Bind be3 and be3 to the rg2 cluster. -alter system modify backend "be3:9050" set ("tag.location" = "rg2"); -alter system modify backend "be4:9050" set ("tag.location" = "rg2"); -``` - -Step 2: Bind the workload group to the BE nodes. -1. Create a new workload group and bind it to wg1 and wg2 respectively. -``` --- Create a workload group for the wg1 group. -create workload group a properties ("memory_limit"="45%","tag"="wg1") -create workload group b properties ("memory_limit"="45%","tag"="wg1") - --- Create a workload group for the wg2 group. -create workload group c properties ("memory_limit"="45%","tag"="wg2") -create workload group d properties ("memory_limit"="45%","tag"="wg2") -``` - -2. Bind the BE to wg1 and wg2. At this point, Workload Group a and b will only take effect on be1 and be2, while Workload Group c and d will only take effect on be3 and be4. - -(Note that when modifying, the tag.location is specified here because the current interface for modifying BE configurations does not support incremental updates. Therefore, when adding new attributes, you must also carry over the existing attributes.) -``` --- Bind be1 and be2 to wg1. -alter system modify backend "be1:9050" set ("tag.location" = "rg1",tag.workload_group="wg1"); -alter system modify backend "be2:9050" set ("tag.location" = "rg1",tag.workload_group="wg1"); - --- Bind be3 and be4 to wg2. -alter system modify backend "be3:9050" set ("tag.location" = "rg2",tag.workload_group="wg2"); -alter system modify backend "be4:9050" set ("tag.location" = "rg2",tag.workload_group="wg2"); -``` - -3. Reduce the resource usage of the normal workload group, serving as a fallback workload group when users do not carry Workload Group information. It can be observed that no tag attributes have been specified for the normal group, allowing it to be effective on all BE nodes. -``` -alter workload group normal properties("memory_limit=1%") -``` -To simplify maintenance, the BE's tag.location and tag.workload_group can use the same value, effectively merging rg1 with wg1 and rg2 with wg2 under a unified name. For example, set the BE's tag.workload_group to rg1, and also specify the tag for Workload Group a and b as rg1. - - -## Principle explanation -### Default situation -The user has created a new Doris cluster with only one BE (defaulting to the default group). The system typically creates a group named normal by default. The user then creates a Workload Group A, with each group allocated 50% of the memory. At this point, the distribution of Workload Groups in the cluster is as follows: - - - -If a new BE named BE2 is added at this point, the Workload Group distribution in the new BE will be as follows:: - - - -The distribution of Workload Groups in the new BE is the same as in the existing BE. - -### Add a new BE cluster -Doris supports the feature of physical isolation for BE nodes. When a new BE node (named BE3) is added and assigned to a separate group (the new BE group is named vip_group), the distribution of Workload Groups is as follows: - - - -It can be seen that by default, the Workload Group in the system is effective across all sub-clusters, which may have certain limitations in some scenarios. - -### Grouping Workload Groups -Suppose there are two physically isolated BE clusters in the cluster: vip_group and default, serving different business entities. These two entities may have different requirements for load management. For instance, vip_group may need to create more Workload Groups, and the resource configurations for each Workload Group may differ significantly from those of the default group. - -In this case, the functionality of Workload Group grouping is needed to address this issue. For example, the vip_group cluster needs to create three Workload Groups, each of which can obtain equal resources. - - - -The user has created three workload groups, named vip_wg_1, vip_wg_2, and vip_wg_3, and specified the tag for the workload groups as vip_wg. This means that these three workload groups are categorized into one group, and their combined memory resource allocation cannot exceed 100%. - -At the same time, the tag.workload_group attribute for BE3 is set to vip_wg, meaning that only Workload Groups with the tag attribute set to vip_wg will take effect on BE3. - -BE1 and BE2 have their tag.workload_group attribute set to default_wg, and the Workload Groups normal and A are also assigned the tag default_wg, so normal and A will only take effect on BE1 and BE2. - -It can be simply understood that BE1 and BE2 form one sub-cluster, which has two Workload Groups: normal and A; while BE3 forms another sub-cluster, which has three Workload Groups: vip_wg_1, vip_wg_2, and vip_wg_3. - -:::tip -NOTE: - -It can be noted that the BE has two attributes: tag.location and tag.workload_group, which are not directly related. - -The tag.location is used to specify which data replica group the BE belongs to. The data replicas also have a location attribute, and the replicas are distributed to BEs with the same location attribute, thereby achieving physical resource isolation. - -The tag.workload_group is used to specify which Workload Group the BE belongs to. Workload Groups also have a tag attribute to indicate which group they belong to, and Workload Groups will only take effect on BEs with the specified grouping. - -In the Doris integrated storage and computing mode, data replicas and computation are typically bound together. Therefore, it is also recommended that the values of BE's tag.location and tag.workload_group be the same value. -::: - - -"The current matching rules for the Workload Group tag and the BE's tag.workload_group are as follows: -1. When the Workload Group tag is empty, this Workload Group can be sent to all BEs, regardless of whether the BE has specified a tag. -2. When the Workload Group tag is not empty, the Workload Group will only be sent to BEs with the same tag. - - diff --git a/docs/admin-manual/workload-management/best-practice/workload-group-best-practice.md b/docs/admin-manual/workload-management/best-practice/workload-group-best-practice.md deleted file mode 100644 index bef24317e2b..00000000000 --- a/docs/admin-manual/workload-management/best-practice/workload-group-best-practice.md +++ /dev/null @@ -1,412 +0,0 @@ ---- -{ -"title": "Workload Group Best Practice", -"language": "en" -} ---- - -<!-- -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. ---> - -## Test hard memory limit - -Ad-hoc queries typically have unpredictable SQL input and uncertain memory usage, which carries the risk of a few queries consuming a large amount of memory. This type of load can be assigned to a separate group. By using the hard memory limits feature of the Workload Group, sudden large queries can be prevented from consuming all available memory, which would otherwise leave no memory for other queries or cause an Out of Memory (OOM) error. - -When the memory usage of this Workload Group exceeds the configured hard limit, memory will be freed by killing queries, thus preventing the process memory from being completely consumed. - - -### Test env -1FE,1BE,BE(96 cores),memory is 375G。 - -Test data is clickbench, run q29 in 3 concurrent. - -### Not using Workload Group's memory limit. -1. Show process memory usage, ps shows memory usage, the memory is 7.7G. -``` -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 2.0 7896792 -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 2.0 7929692 -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 2.0 8101232 -``` - -2. Show Workload Group memory by system table, it's 5.8G. -``` -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+-------------------+ -| wg_mem_used_mb | -+-------------------+ -| 5797.524360656738 | -+-------------------+ -1 row in set (0.01 sec) - -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+-------------------+ -| wg_mem_used_mb | -+-------------------+ -| 5840.246627807617 | -+-------------------+ -1 row in set (0.02 sec) - -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+-------------------+ -| wg_mem_used_mb | -+-------------------+ -| 5878.394917488098 | -+-------------------+ -1 row in set (0.02 sec) -``` -Here, you can see that the memory usage of the process is usually much greater than the memory usage of a single Workload Group, even if only one Workload Group is running in the process. This is because the Workload Group only accounts for the memory used by queries and some parts of data import. Other components within the process, such as metadata and various caches, are not included in the Workload Group's memory usage and are not managed by the Workload Group. - -### Use Workload Group limit memory -1. Alter workload group. -``` -alter workload group g2 properties('memory_limit'='0.5%'); -alter workload group g2 properties('enable_memory_overcommit'='false'); -``` - -2. Run test, the workload group uses 1.5G memory. -``` -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+--------------------+ -| wg_mem_used_mb | -+--------------------+ -| 1575.3877239227295 | -+--------------------+ -1 row in set (0.02 sec) - -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+------------------+ -| wg_mem_used_mb | -+------------------+ -| 1668.77405834198 | -+------------------+ -1 row in set (0.01 sec) - -mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; -+--------------------+ -| wg_mem_used_mb | -+--------------------+ -| 499.96760272979736 | -+--------------------+ -1 row in set (0.01 sec) -``` - -3. Show memory by ps command, the max memory is 3.8G. -``` -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 1.0 4071364 -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 1.0 4059012 -[ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 -1407481 doris_be 1.0 4057068 -``` - -4. There are many query failed because of oom. -``` -1724074250162,14126,1c_sql,HY000 1105,"java.sql.SQLException: errCode = 2, detailMessage = (127.0.0.1)[MEM_LIMIT_EXCEEDED]GC wg for hard limit, wg id:11201, name:g2, used:1.71 GB, limit:1.69 GB, backend:10.16.10.8. cancel top memory used tracker <Query#Id=4a0689936c444ac8-a0d01a50b944f6e7> consumption 1.71 GB. details:process memory used 3.01 GB exceed soft limit 304.41 GB or sys available memory 101.16 GB less than warning water mark 12.80 GB., Execute again after enough memory, details [...] -``` -In this error message, you can see that the Workload Group used 1.7GB of memory, while the Workload Group's limit is 1.69GB. The calculation works as follows: 1.69GB = Physical machine memory (375GB) * mem_limit (value in be.conf, default is 0.9) * 0.5% (Workload Group's configuration). This means that the memory percentage configured in the Workload Group is calculated based on the available memory of the Doris process. - - -### Suggestions -As demonstrated in the previous test, the hard limit can control the memory usage of a Workload Group, but it releases memory by killing queries, which can be a very unfriendly experience for users and may cause all queries to fail in extreme cases. Therefore, in a production environment, it is recommended to use memory hard limits in conjunction with query queuing. This approach can limit memory usage while ensuring the success rate of queries. - - -## CPU hard limit Test -The workloads in Doris can generally be divided into three categories: - -Core Report Queries: These are typically used by company executives to view reports. The load may not be very high, but the availability requirements are high. These queries can be grouped together and assigned a higher-priority soft limit, ensuring they receive more CPU resources when CPU availability is limited. - -Ad-hoc Queries: These queries are usually exploratory, with random SQL and unpredictable resource usage. They typically have a lower priority, so they can be managed with a CPU hard limit set to a lower value, preventing them from consuming excessive CPU resources and reducing cluster availability. - -ETL Queries: These queries have relatively fixed SQL and stable resource usage, though occasionally, a sudden increase in upstream data volume can cause a spike in resource usage. Therefore, they can be managed with a CPU hard limit configuration. - -Different workloads consume CPU resources differently, and users have varying requirements for response latency. When the BE's CPU is heavily utilized, availability decreases and response latency increases. For example, an ad-hoc analytical query might fully utilize the cluster's CPU, causing increased latency for core reports and impacting the SLA. Therefore, a CPU isolation mechanism is needed to separate different types of workloads, ensuring cluster availability and meeting SLAs. - -Workload Groups support both soft and hard CPU limits, with a current recommendation to configure Workload Groups with hard limits in production environments. This is because soft limits only come into effect when the CPU is fully utilized, but when the CPU is maxed out, internal components of Doris (e.g., RPC components) and available CPU resources for the operating system are reduced, leading to a significant decline in overall cluster availability. Therefore, in production environment [...] - -### Test env -1FE, 1BE(96 cores) -Test data is clickbench,sql is q29. - -### Test -1. Run query in 3 concurrent, using top command we can see it uses 76 cores. - - - -2. Alter workload group. -``` -alter workload group g2 properties('cpu_hard_limit'='10%'); -``` - -3. Enable cpu hard limit,then all workload group could convert to hard limit. -``` -ADMIN SET FRONTEND CONFIG ("enable_cpu_hard_limit" = "true"); -``` - -4. Test again, the BE using 9 ~ 10 cores, about 10%. - - - -It should be noted that it's best to use query workloads for testing here, as they are more likely to reflect the intended effects. If you use high-throughput data import instead, it may trigger compaction, causing the observed values to be higher than the configured Workload Group limits. Currently, the compaction workload is not managed by the Workload Group. - -5. Use system table to show cpu usage, it's about 10%; -``` -mysql [information_schema]>select CPU_USAGE_PERCENT from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+-------------------+ -| CPU_USAGE_PERCENT | -+-------------------+ -| 9.57 | -+-------------------+ -1 row in set (0.02 sec) -``` - -### NOTE -1. When configuring in practice, it's best not to have the total CPU allocation of all Groups add up to exactly 100%. This is primarily to ensure availability in low-latency scenarios, as some resources need to be reserved for other components. However, if the scenario is not sensitive to latency and the goal is maximum resource utilization, you can consider configuring the total CPU allocation of all Groups to equal 100%. - -2. Currently, the time interval for the Frontend (FE) to synchronize Workload Group metadata to the Backend (BE) is 30 seconds, so it may take up to 30 seconds for changes to the Workload Group to take effect. - - -## Test limit local IO -In OLAP systems, when performing ETL or large ad-hoc queries, a significant amount of data needs to be read. To speed up data analysis, Doris internally uses multithreading to scan multiple disk files in parallel, which generates a large amount of disk I/O and can negatively impact other queries, such as report analysis. - -By using Workload Groups, you can group offline ETL data processing and online report queries separately and limit the I/O bandwidth for offline data processing, thereby reducing its impact on online report analysis. - - -### Test -1FE,1BE(96 cores), test data is clickbench - -### Not limit IO -1. Clear cache. -``` -// clear OS cache. -sync; echo 3 > /proc/sys/vm/drop_caches - -// disable BE's cache. -disable_storage_page_cache = true -``` - -2. Run query one by one. -``` -set dry_run_query = true; -select * from hits.hits; -``` - -3. Show local IO by system table, is's 3G/s. -``` -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 1146.6208400726318 | -+--------------------+ -1 row in set (0.03 sec) - -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 3496.2762966156006 | -+--------------------+ -1 row in set (0.04 sec) - -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 2192.7690029144287 | -+--------------------+ -1 row in set (0.02 sec) -``` - -4.Show IO by pidstat, the first column in picture is process id, the second column is IO(kb/s), it's 2G/s. - - - - -### Test IO limit. -1. Clear cache. -``` -// clear os cache -sync; echo 3 > /proc/sys/vm/drop_caches - -// disable BE cache -disable_storage_page_cache = true -``` - -2. Alter workload group. -``` -alter workload group g2 properties('read_bytes_per_second'='104857600'); -``` - -3. Show IO by system table, it's about 98M/s. -``` -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 97.94296646118164 | -+--------------------+ -1 row in set (0.03 sec) - -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 98.37584781646729 | -+--------------------+ -1 row in set (0.04 sec) - -mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; -+--------------------+ -| mb_per_sec | -+--------------------+ -| 98.06641292572021 | -+--------------------+ -1 row in set (0.02 sec) -``` - -4. Show IO by pidstat, the process IO is about 131M/s。 - - - -### NOTE -1. The LOCAL_SCAN_BYTES_PER_SECOND field in the system table represents the aggregated statistics at the process level for the current Workload Group. For example, if 12 file paths are configured, LOCAL_SCAN_BYTES_PER_SECOND represents the maximum I/O value across these 12 file paths. If you want to see the I/O throughput for each file path individually, you can view detailed values in Grafana or through the BE's bvar monitoring. -2. Due to the presence of the operating system's and Doris's Page Cache, the I/O values observed using Linux's I/O monitoring scripts are usually smaller than those seen in the system table. - - -BrokerLoad and S3Load are commonly used methods for importing large volumes of data. Users can first upload data to HDFS or S3 and then use BrokerLoad and S3Load for parallel data imports. To speed up the import process, Doris uses multithreading to pull data from HDFS/S3 in parallel. This can put significant pressure on HDFS/S3, potentially causing instability for other jobs running on HDFS/S3. - -You can use the remote I/O limitation feature of Workload Groups to limit the bandwidth used during the import process, thereby reducing the impact on other operations. - -## Test limit remote IO -### Test env -1FE,1BE(16 cores, 64G), test data is clickbench,Before testing, the dataset needs to be uploaded to S3. To save time, we will upload only 10 million rows of data, and then use the TVF (Table-Valued Function) feature to query the data from S3. - -Show schema info after upload. -``` -DESC FUNCTION s3 ( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" -); -``` - -### Test not limit remote IO -1. Run query one by one. -``` -// just scan, not return value. -set dry_run_query = true; - -SELECT * FROM s3( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" -); -``` - -2. Show remote IO by system table,it's about 837M/s, It should be noted that the actual I/O throughput here is significantly affected by the environment. If the machine hosting the BE has a low bandwidth connection to external storage, the actual throughput may be lower. -``` -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 837 | -+---------+ -1 row in set (0.104 sec) - -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 867 | -+---------+ -1 row in set (0.070 sec) - -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 867 | -+---------+ -1 row in set (0.186 sec) -``` - -3. Using sar(sar -n DEV 1 3600) to show network bandwidth of the machine, the max value is about 1033M/s.The first column of the output is the number of bytes received per second by a certain network card of the current machine, in KB per second. - - - - -### Test limit remote IO -1. Alter workload group. -``` -alter workload group normal properties('remote_read_bytes_per_second'='104857600'); -``` - -2. Run query one by one. -``` -// just scan not return. -set dry_run_query = true; - - -SELECT * FROM s3( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" -); -``` - -3. Use the system table to check the current remote read I/O throughput. At this moment, the I/O throughput is around 100M, with some fluctuation. This fluctuation is influenced by the current algorithm design and typically includes a peak, but it does not last long and is considered normal. -``` -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 56 | -+---------+ -1 row in set (0.010 sec) - -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 131 | -+---------+ -1 row in set (0.009 sec) - -MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; -+---------+ -| read_mb | -+---------+ -| 111 | -+---------+ -1 row in set (0.009 sec) -``` - -4. Using sar(sar -n DEV 1 3600) to show network bandwidth, the max IO is about 207M, This indicates that remote limit IO works. However, since the sar command shows machine-level traffic, the values may be higher than those reported by Doris. - - diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/group-workload-groups.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/group-workload-groups.md deleted file mode 100644 index d36ecc7d41e..00000000000 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/group-workload-groups.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -{ -"title": "Workload Group 分组功能", -"language": "zh-CN" -} ---- - -<!-- -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. ---> - -Workload Group 分组功能常用于当一个 Doris 集群中有多个物理隔离的 BE 集群时,可以将 Workload Group 进行分组,不同分组的 Workload Group 可以绑定到不同的 BE 集群中。 - -## 推荐用法 -假如目前集群中已有了两个隔离的 BE 子集群,命名为 rg1 和 rg2,且这两个分组之间是完全物理隔离的,数据和计算不会有共享的情况。 -那么比较推荐的配置方式是: -1. 把 normal group 的资源配置量尽量调小,作为保底的查询分组,比如查询如果不携带任何 Workload Group 信息,那么就会自动使用这个默认的 group,作用是避免查询失败。 -2. 为这两个子集群分别创建对应的 Workload Group,绑定到对应的子集群上。 - 例如,为 rg1 集群创建第一个名为 wg1 的 Workload Group 分组,包含 Workload Group a 和 Workload Group b 两个 Workload Group。为 rg2 集群创建第二个名为 wg2 的 Workload Group 分组,包含 Workload Group c 和 Workload Group d。 - 那么最终效果如下: - - - -操作流程如下: - -第一步:把数据副本绑定到 BE 节点,其实也就是完成 rg1 子集群和 rg2 子集群的划分,实现数据副本的隔离,如果集群已经完成了子集群的划分,那么可以跳过这个步骤,直接进入第二步。 - -1. 把数据副本绑定到 rg1 集群和 rg2 集群 - - ```sql - -- 为 rg1 集群建表时需要指定副本分布到 rg1 - create table table1 - (k1 int, k2 int) - distributed by hash(k1) buckets 1 - properties( - "replication_allocation"="tag.location.rg1:3" - ) - - -- 为 rg2 集群建表时需要指定副本分布到 rg2 - create table table2 - (k1 int, k2 int) - distributed by hash(k1) buckets 1 - properties( - "replication_allocation"="tag.location.rg2:3" - ) - ``` - -2. 把 BE 节点绑定到 rg1 集群和 rg2 集群 - - ```sql - -- 把 be1 和 be2 绑定到 rg1 集群 - alter system modify backend "be1:9050" set ("tag.location" = "rg1"); - alter system modify backend "be2:9050" set ("tag.location" = "rg1"); - - -- 把 be3 和 be4 绑定到 rg2 集群 - alter system modify backend "be3:9050" set ("tag.location" = "rg2"); - alter system modify backend "be4:9050" set ("tag.location" = "rg2"); - ``` - -第二步:把 workload group 绑定到 BE 节点 - -1. 新建 workload group,并把 workload group 分别绑定到 wg1 和 wg2 - - ```sql - -- 创建 wg1 分组的 workload group - create workload group a properties ("memory_limit"="45%","tag"="wg1") - create workload group b properties ("memory_limit"="45%","tag"="wg1") - - -- 创建 wg2 分组的 workload group - create workload group c properties ("memory_limit"="45%","tag"="wg2") - create workload group d properties ("memory_limit"="45%","tag"="wg2") - ``` - -2. 把 BE 绑定到 wg1 和 wg2,此时 Workload Group a 和 b 只会在 be1 和 be2 上生效。Workload Group c 和 d 只会在 be3 和 be4 上生效。 - (需要注意的是这里在修改时指定了 tag.location,原因是修改 BE 配置的接口目前暂时不支持增量更新,因此在新加属性时要把存量的属性也携带上) - - ```sql - -- 把 be1 和 be2 绑定到 wg1 - alter system modify backend "be1:9050" set ("tag.location" = "rg1",tag.workload_group="wg1"); - alter system modify backend "be2:9050" set ("tag.location" = "rg1",tag.workload_group="wg1"); - - -- 把 be3 和 be4 绑定到 wg2 - alter system modify backend "be3:9050" set ("tag.location" = "rg2",tag.workload_group="wg2"); - alter system modify backend "be4:9050" set ("tag.location" = "rg2",tag.workload_group="wg2"); - ``` - -3. 调小 normal workload group 的资源用量,作为用户不携带 Workload Group 信息时保底可用的 Workload Group,可以看到没有为 normal group 指定 tag 属性,因此 normal 可以在所有 BE 生效。 - - ```sql - alter workload group normal properties("memory_limit"="1%") - ``` - -为了维护更加简单,BE 的 tag.location 和 tag.workload_group 可以使用相同的值,也就是把 rg1 和 wg1 进行合并,rg2 和 wg2 进行合并,统一使用一个名称。比如把 BE 的 tag.workload_group 设置为 rg1,Workload Group a 和 b 的 tag 也指定为 rg1。 - - -## 原理讲解 -### 默认情况 -用户新建了一个 Doris 的集群,集群中只有一个 BE(默认为 default 分组),系统通常默认会创建一个名为 normal 的 group,然后用户又创建了一个 Workload Group A,各自分配 50% 的内存,那么此时集群中 Workload Group 的分布情况如下: - - - -如果此时添加一个名为 BE2 的新 BE,那么新 BE 中的分布情况如下: - - - -新增 BE 的 Workload Group 的分布和现有 BE 相同。 - -### 添加新的 BE 集群 -Doris 支持 BE 物理隔离的功能,当添加新的 BE 节点 (名为 BE3) 并划分到独立的分组时 (新的 BE 分组命名为 vip_group),Workload Group 的分组如下: - - - -可以看到默认情况下,系统中的 Workload Group 会在所有的子集群生效,在有些场景下会具有一定的局限性。 - -### 对 Workload Group 使用分组的功能 -假如集群中有 vip_group 和 default 两个物理隔离的 BE 集群,服务于不同的业务方,这两个业务方对于负载管理可能有不同的诉求。比如 vip_group 可能需要创建更多的 Workload Group,每个 Workload Group 的资源配置和 default 分组的差异也比较大。 - -此时就需要 Workload Group 分组的功能解决这个问题,比如 vip_group 集群需要创建三个 Workload Group,每个 group 可以获得均等的资源。 - - - -用户新建了三个 workload group,分别名为 vip_wg_1, vip_wg_2, vip_wg_3,并指定 workload group 的 tag 为 vip_wg,含义为这三个 workload group 划分为一个分组,它们的内存资源累加值不能超过 100%。 -同时指定 BE3 的 tag.workload_group 属性为 vip_wg,含义为只有指定了 tag 属性为 vip_wg 的 Workload Group 才会在 BE3 上生效。 - -BE1 和 BE2 指定了 tag.workload_group 属性为 default_wg,Workload Group normal 和 A 则指定了 tag 为 default_wg,因此 normal 和 A 只会在 BE1 和 BE2 上生效。 - -可以简单理解为,BE1 和 BE2 是一个子集群,这个子集群拥有 normal 和 A 两个 Workload Group;BE3 是另一个子集群,这个子集群拥有 vip_wg_1,vip_wg_2 和 vip_wg_3 三个 Workload Group。 - -:::tip 注意事项 - -可以注意到上文中 BE 有两个属性,tag.location 和 tag.workload_group,这两个属性没有什么直接的关联。 -tag.location 用于指定 BE 归属于哪个数据副本分组,数据副本也有 location 属性,数据副本会被分发到具有相同 location 属性的 BE,从而完成物理资源的隔离。 - -tag.workload_group 用于指定 BE 归属于哪个 Workload Group 的分组,Workload Group 也具有 tag 属性用于指定 Workload Group 归属于哪个分组,Workload Group 也只会在具有分组的 BE 上生效。 -Doris 存算一体模式下,数据副本和计算通常是绑定的,因此也比较推荐 BE 的 tag.location 和 tag.workload_group 值是对齐的。 -::: - -目前 Workload Group 的 tag 和 Be 的 tag.workload_group 的匹配规则为: -1. 当 Workload Group 的 tag 为空,那么这个 Workload Group 可以发送给所有的 BE,不管该 BE 是否指定了 tag。 -2. 当 Workload Group 的 tag 不为空,那么 Workload Group 只会发送给具有相同标签的 BE。 \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/workload-group-best-practice.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/workload-group-best-practice.md deleted file mode 100644 index d79c5ff1c50..00000000000 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/best-practice/workload-group-best-practice.md +++ /dev/null @@ -1,437 +0,0 @@ ---- -{ -"title": "Workload Group 最佳实践", -"language": "zh-CN" -} ---- - -<!-- -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. ---> - -## 测试内存硬限 -Adhoc 类查询通常输入的 SQL 不确定,使用的内存资源也不确定,因此存在少数查询占用很大内存的风险。 -可以对这类负载可以划分到独立的分组,通过 Workload Group 对内存的硬限的功能,避免突发性的大查询占满所有内存,导致其他查询没有可用内存或者 OOM。 -当这个 Workload Group 的内存使用超过配置的硬限值时,会通过杀死查询的方式释放内存,避免进程内存被打满。 - -### 测试环境 -1FE,1BE,BE 配置为 96 核,内存大小为 375G。 - -测试数据集为 clickbench,测试方法为使用 jmeter 起三并发执行 q29。 - -### 测试不开启 Workload Group 的内存硬限 - -1. 查看进程使用内存。ps 命令输出第四列代表进程使用的物理内存的用量,单位为 kb,可以看到当前测试负载下,进程的内存使用为 7.7G 左右。 - - ```sql - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 2.0 7896792 - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 2.0 7929692 - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 2.0 8101232 - ``` - -2. 使用 Doris 系统表查看当前 Workload Group 的内存用量,Workload Group 的内存用量为 5.8G 左右。 - - ```sql - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +-------------------+ - | wg_mem_used_mb | - +-------------------+ - | 5797.524360656738 | - +-------------------+ - 1 row in set (0.01 sec) - - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +-------------------+ - | wg_mem_used_mb | - +-------------------+ - | 5840.246627807617 | - +-------------------+ - 1 row in set (0.02 sec) - - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +-------------------+ - | wg_mem_used_mb | - +-------------------+ - | 5878.394917488098 | - +-------------------+ - 1 row in set (0.02 sec) - ``` - -这里可以看到进程的内存使用通常要远大于一个 Workload Group 的内存用量,即使进程内只有一个 Workload Group 在跑,这是因为 Workload Group 只统计了查询和部分导入的内存,进程内的其他组件比如元数据,各种 Cache 的内存是不计算 Workload Group 内的,也不由 Workload Group 管理。 - -### 测试开启 Workload Group 的内存硬限 -1. 执行 SQL 命令修改内存配置。 - - ```sql - alter workload group g2 properties('memory_limit'='0.5%'); - alter workload group g2 properties('enable_memory_overcommit'='false'); - ``` - -2. 执行同样的测试,查看系统表的内存用量,内存用量为 1.5G 左右。 - - ```sql - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +--------------------+ - | wg_mem_used_mb | - +--------------------+ - | 1575.3877239227295 | - +--------------------+ - 1 row in set (0.02 sec) - - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +------------------+ - | wg_mem_used_mb | - +------------------+ - | 1668.77405834198 | - +------------------+ - 1 row in set (0.01 sec) - - mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; - +--------------------+ - | wg_mem_used_mb | - +--------------------+ - | 499.96760272979736 | - +--------------------+ - 1 row in set (0.01 sec) - ``` - -3. 使用 ps 命令查看进程的内存用量,内存用量为 3.8G 左右。 - - ```sql - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 1.0 4071364 - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 1.0 4059012 - [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 - 1407481 doris_be 1.0 4057068 - ``` - -4. 同时客户端会观察到大量由于内存不足导致的查询失败。 - - ```sql - 1724074250162,14126,1c_sql,HY000 1105,"java.sql.SQLException: errCode = 2, detailMessage = (127.0.0.1)[MEM_LIMIT_EXCEEDED]GC wg for hard limit, wg id:11201, name:g2, used:1.71 GB, limit:1.69 GB, backend:10.16.10.8. cancel top memory used tracker <Query#Id=4a0689936c444ac8-a0d01a50b944f6e7> consumption 1.71 GB. details:process memory used 3.01 GB exceed soft limit 304.41 GB or sys available memory 101.16 GB less than warning water mark 12.80 GB., Execute again after enough memory, det [...] - ``` - -这个报错信息中可以看到,Workload Group 使用了 1.7G 的内存,但是 Workload Group 的限制是 1.69G,这里的计算方式是这样的 1.69G = 物理机内存 (375) * mem_limit(be.conf 中的值,默认为 0.9) * 0.5%(Workload Group 的配置) -也就是说,Workload Group 中配置的内存百分比是基于 Doris 进程可用内存再次进行计算的。 - - -### 使用建议 -如上文测试,硬限可以控制 Workload Group 的内存使用,但却是通过杀死查询的方式释放内存,这对用户来说体验会非常不友好,极端情况下可能会导致所有查询都失败。 -因此在生产环境中推荐内存硬限配合查询排队的功能一起使用,可以在限制内存使用的同时保证查询的成功率。 - - - -## CPU 硬限测试 -Doris 的负载大体可以分为三类: -1. 核心报表查询,通常给公司高层查看报表使用,负载不一定很高,但是对可用性要求较高,这类查询可以划分到一个分组,配置较高优先级的软限,保证 CPU 资源不够时可以获得更多的 CPU 资源。 -2. Adhoc 类查询,这类查询通常偏探索分析,SQL 比较随机,具体的资源用量也比较未知,优先级通常不高。因此可以使用 CPU 硬限进行管理,并配置较低的值,避免占用过多 CPU 资源降低集群可用性。 -3. ETL 类查询,这类查询的 SQL 比较固定,资源用量通常也比较稳定,偶尔会出现上游数据量增长导致资源用量暴涨的情况,因此可以使用 CPU 硬限进行配置。 - -不同的负载对 CPU 的消耗不一样,用户对响应延时的需求也不一样。当 BE 的 CPU 被用的很满时,可用性会变差,响应延时会变高。比如可能一个 Adhoc 的分析类查询把整个集群的 CPU 打满,导致核心报表的延时变大,影响到了 SLA。所以需要 CPU 隔离机制来对不同的业务进行隔离,保障集群的可用性和 SLA。 -Workload Group 支持 CPU 的软限和硬限,目前比较推荐在线上环境把 Workload Group 配置成硬限。原因是 CPU 的软限通常在 CPU 被打满时才能体现出优先级的作用,但是在 CPU 被用满时,Doris 的内部组件(例如 rpc 组件)以及操作系统可用的 CPU 会减少,此时集群整体的可用性是下降比较严重的,因此生产环境通常需要避免 CPU 资源被打满的情况,当然其他资源也一样,内存资源同理。 - - -### 测试环境 -1FE,1BE,96 核机器。 -数据集为 clickbench,测试 sql 为 q29。 - -### 测试 -1. 使用 jmeter 发起 3 并发查询,把 BE 进程的 CPU 使用压到比较高的使用率,这里测试的机器是 96 核,使用 top 命令看到 BE 进程 CPU 使用率为 7600% 的含义是该进程目前使用中的核数是 76 个。 - -  - -2. 修改使用中的 Workload Group 的 CPU 硬限为 10%。 - - ```sql - alter workload group g2 properties('cpu_hard_limit'='10%'); - ``` - -3. 集群开启硬限模式,此时集群中所有 Group 都会切换为硬限。 - - ```sql - ADMIN SET FRONTEND CONFIG ("enable_cpu_hard_limit" = "true"); - ``` - -4. 重新压测查询负载,可以看到当前进程只能使用 9 到 10 个核,占总核数的 10% 左右。 - -  - -需要注意的是,这里的测试最好使用查询负载会比较能体现出效果,因为如果是高吞吐导入的话,可能会触发 Compaction,使得实际观测的值要比 Workload Group 配置的值大。而 Compaction 的负载目前是没有归入 Workload Group 的管理的。 - -5. 除了使用 Linux 的系统命令外,还可以通过使用 Doris 的系统表观察 Group 目前的 CPU 使用为 10% 左右。 - - ```sql - mysql [information_schema]>select CPU_USAGE_PERCENT from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +-------------------+ - | CPU_USAGE_PERCENT | - +-------------------+ - | 9.57 | - +-------------------+ - 1 row in set (0.02 sec) - ``` - -### 注意事项 -1. 在实际配置的时候,所有 Group 的 CPU 累加值最好不要正好等于 100%,这主要是为了保证低延迟场景的可用性。因为需要让出一部分资源给其他组件使用。当然如果对延迟不是很敏感的场景,期望最高的资源利用率,那么可以考虑所有 Group 的 CPU 累加值配置等于 100%。 -2. 目前 FE 向 BE 同步 Workload Group 元数据的时间间隔为 30 秒,因此对于 Workload Group 的变更最大需要等待 30 秒才能生效。 - - -## 测试本地 IO 硬限 -OLAP 系统在做 ETL 或者大的 Adhoc 查询时,需要读取大量的数据,Doris 为了加速数据分析过程,内部会使用多线程并行的方式对多个磁盘文件扫描,会产生巨大的磁盘 IO,就会对其他的查询(比如报表分析)产生影响。 -可以通过 Workload Group 对离线的 ETL 数据处理和在线的报表查询做分组,限制离线数据处理 IO 带宽的方式,降低它对在线报表分析的影响。 - -### 测试环境 -1FE,1BE, 配置为 96 核。 - -测试数据集为 clickbench。 - -### 不开启 IO 硬限测试 -1. 关闭缓存。 - - ```sql - // 清空操作系统缓存 - sync; echo 3 > /proc/sys/vm/drop_caches - - // 禁用 BE 的 page cache - disable_storage_page_cache = true - ``` - -2. 对 clickbench 的表执行全表扫描,执行单并发查询即可。 - - ```sql - set dry_run_query = true; - select * from hits.hits; - ``` - -3. 通过 Doris 的内表查看当前 Group 的最大吞吐为 3GB 每秒。 - - ```sql - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 1146.6208400726318 | - +--------------------+ - 1 row in set (0.03 sec) - - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 3496.2762966156006 | - +--------------------+ - 1 row in set (0.04 sec) - - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 2192.7690029144287 | - +--------------------+ - 1 row in set (0.02 sec) - ``` - -4. 使用 pidstat 命令查看进程 IO,图中第一列是进程 id,第二列是读 IO 的吞吐(单位是 kb/s)。可以看到不限制 IO 时,最大吞吐为 2G 每秒。 - -  - - -### 开启 IO 硬限后测试 -1. 关闭缓存。 - - ```sql - // 清空操作系统缓存 - sync; echo 3 > /proc/sys/vm/drop_caches - - // 禁用 BE 的 page cache - disable_storage_page_cache = true - ``` - -2. 修改 Workload Group 的配置,限制每秒最大吞吐为 100M。 - - ```sql - // 限制当前 Group 的读吞吐为每秒 100M - alter workload group g2 properties('read_bytes_per_second'='104857600'); - ``` - -3. 使用 Doris 系统表查看 Workload Group 的最大 IO 吞吐为每秒 98M。 - - ```sql - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 97.94296646118164 | - +--------------------+ - 1 row in set (0.03 sec) - - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 98.37584781646729 | - +--------------------+ - 1 row in set (0.04 sec) - - mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; - +--------------------+ - | mb_per_sec | - +--------------------+ - | 98.06641292572021 | - +--------------------+ - 1 row in set (0.02 sec) - ``` - -4. 使用 pid 工具查看进程最大 IO 吞吐为每秒 131M。 - -  - -### 注意事项 -1. 系统表中的 LOCAL_SCAN_BYTES_PER_SECOND 字段代表的是当前 Workload Group 在进程粒度的统计汇总值,比如配置了 12 个文件路径,那么 LOCAL_SCAN_BYTES_PER_SECOND 就是这 12 个文件路径 IO 的最大值,如果期望查看每个文件路径分别的 IO 吞吐,可以在 grafana 上或者 BE 的 bvar 监控查看明细的值。 - -2. 由于操作系统和 Doris 的 Page Cache 的存在,通过 linux 的 IO 监控脚本看到的 IO 通常要比系统表看到的要小。 - - -## 测试远程 IO 限制 -BrokerLoad 和 S3Load 是常用的大批量数据导入方式,用户可以把数据先上传到 HDFS 或者 S3,然后通过 Brokerload 和 S3Load 对数据进行并行导入。Doris 为了加快导入速度,会使用多线程并行的方式从 HDFS/S3 拉取数据,此时会对 HDFS/S3 产生巨大的压力,会导致 HDFS/S3 上运行的别的作业不稳定。 -可以通过 Workload Group 远程 IO 的限制功能来限制导入过程中对 HDFS/S3 的带宽,降低对其他业务的影响。 - - -### 测试环境 -1FE,1BE 部署在同一台机器,配置为 16 核 64G 内存。测试数据为 clickbench 数据集,测试前需要把数据集上传到 S3 上。考虑到上传时间的问题,我们只取其中的 1 千万行数据上传,然后使用 tvf 的功能查询 s3 的数据。 - -上传成功后可以使用命令查看 Schema 信息。 - - ```sql - // 查看schema - DESC FUNCTION s3 ( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" - ); - ``` - -### 测试不限制远程读的 IO -1. 发起单并发测试,全表扫描 clickbench 表。 - - ```sql - // 设置只 scan 数据,不返回结果 - set dry_run_query = true; - - // 使用 tvf 查询 s3 的数据 - SELECT * FROM s3( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" - ); - ``` - -2. 使用系统表查看此时的远程 IO 吞吐。可以看到这个查询的远程 IO 吞吐为 837M 每秒,需要注意的是,这里的实际 IO 吞吐受环境影响较大,如果 BE 所在的机器连接外部存储的带宽比较低,那么可能实际的吞吐会小。 - - ```sql - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 837 | - +---------+ - 1 row in set (0.104 sec) - - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 867 | - +---------+ - 1 row in set (0.070 sec) - - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 867 | - +---------+ - 1 row in set (0.186 sec) - ``` - -3. 使用 sar(sar -n DEV 1 3600) 命令查看机器的网络带宽,可以看到机器级别最大网络带宽为 1033M 每秒。 - 输出的第一列为当前机器某个网卡每秒接收的字节数,单位为 KB 每秒。 - -  - -### 测试限制远程读的 IO -1. 修改 Workload Group 的配置,限制远程读的 IO 吞吐为 100M 每秒。 - - ```sql - alter workload group normal properties('remote_read_bytes_per_second'='104857600'); - ``` - -2. 发起单并发扫全表的查询。 - - ```sql - // 设置只 scan 数据,不返回结果 - set dry_run_query = true; - - // 使用 tvf 查询 s3 的数据 - SELECT * FROM s3( - "URI" = "https://bucketname/1kw.tsv", - "s3.access_key"= "ak", - "s3.secret_key" = "sk", - "format" = "csv", - "use_path_style"="true" - ); - ``` - -3. 使用系统表查看此时的远程读 IO 吞吐,此时的 IO 吞吐在 100M 左右,会有一定的波动,这个波动是受目前算法设计的影响,通常会有一个高峰,但不会持续很长时间,属于正常情况。 - - ```sql - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 56 | - +---------+ - 1 row in set (0.010 sec) - - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 131 | - +---------+ - 1 row in set (0.009 sec) - - MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; - +---------+ - | read_mb | - +---------+ - | 111 | - +---------+ - 1 row in set (0.009 sec) - ``` - -4. 使用 sar 命令(sar -n DEV 1 3600)查看目前的网卡接收流量,第一列为每秒接收的数据量,可以看到最大值变成了 207M 每秒,说明读 IO 的限制是生效的,但是由于 sar 命令看到的是机器级别的流量,因此要比 Doris 统计到的会大一些。 - -  \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/sql-blocking.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/sql-blocking.md index 20d869ce909..9eb5abac90a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/sql-blocking.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/sql-blocking.md @@ -24,7 +24,7 @@ specific language governing permissions and limitations under the License. --> -查询熔断是一种保护机制,用于防止长时间运行或消耗过多资源的查询对系统产生负面影响。当查询超过预设的资源或时间限制时,熔断机制会自动终止该查询,以避免对系统性能、资源使用以及其他查询造成不利影响。这种机制确保了集群在多用户环境下的稳定性,防止单个查询导致系统资源耗尽、响应变慢或发生死锁,从而提高整体的可用性和效率。 +查询熔断是一种保护机制,用于防止长时间运行或消耗过多资源的查询对系统产生负面影响。当查询超过预设的资源或时间限制时,熔断机制会自动终止该查询,以避免对系统性能、资源使用以及其他查询造成不利影响。这种机制确保了集群在多用户环境下的稳定性,防止单个查询导致系统资源耗尽、响应变慢,从而提高整体的可用性和效率。 在 Doris 内,有两种熔断策略: @@ -213,20 +213,17 @@ A:可以。修改阻止规则,将其属性中的"enable"改为"false"即可 #### Q:阻止规则中的正则表达式使用哪种规范? A:阻止规则的正则表达式使用 java 的正则表达式规范。常用表达式可以参考 SQL 语法手册。完整的手册可以参考 https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html -## Workload Group Policy - -### 注意事项 -- 同一个 Policy 的 Condition 和 Action 要么都是 FE 的,要么都是 BE 的,比如 set_session_variable 和 cancel_query 无法配置到同一个 Policy 中。Condition be_scan_rows 和 Condition username 无法配置到同一个 Policy 中。 -- 由于目前的 Policy 是异步线程以固定时间间隔执行的,因此策略的生效存在一定的滞后性。比如用户配置了 scan 行数大于 100 万就取消查询的策略,如果此时集群资源比较空闲,那么有可能在取消策略生效之前查询就已经结束了。目前这个时间间隔为 500ms,这意味着运行时间过短的查询可能会绕过策略的检查。 -- 当前支持的负载类型包括 select/insert select/stream load/broker load/routine load。 -- 一个查询可能匹配到多个 Policy,但是只有优先级最高的 Policy 会生效。 -- 目前不支持 Action 和 Condition 的修改,只能通过删除新建的方式修改。 +## Workload Policy +Workload Policy主要用于对运行时状态不符合预期的查询进行熔断,避免部分大查询占用过多资源从而影响集群的稳定性,常用的运行时监控指标如下: +* 查询时间 +* 查询在单BE上的扫描行数/扫描字节数 +* 查询的在单BE上的内存使用 ### 熔断策略范围 自 Doris 2.1 版本起,可以通过 Workload Policy 可以实现大查询的熔断。 -| 版本 | 2.1 | +| 版本 | 2.1 | |--------------------|-----| | select | √ | | insert into select | √ | @@ -234,7 +231,7 @@ A:阻止规则的正则表达式使用 java 的正则表达式规范。常用 | stream load | √ | | routine load | √ | | backup | X | -| compAction | X | +| compaction | X | ### 创建熔断策略 使用 `CREATE WORKLOAD Policy` 命令可以创建资源管理策略。 @@ -280,6 +277,13 @@ Actions(cancel_query) properties('workload_group'='normal') ``` +### 注意事项 +- 同一个 Policy 的 Condition 和 Action 要么都是 FE 的,要么都是 BE 的,比如 set_session_variable 和 cancel_query 无法配置到同一个 Policy 中。Condition be_scan_rows 和 Condition username 无法配置到同一个 Policy 中。 +- 由于目前的 Policy 是异步线程以固定时间间隔执行的,因此策略的生效存在一定的滞后性。比如用户配置了 scan 行数大于 100 万就取消查询的策略,如果此时集群资源比较空闲,那么有可能在取消策略生效之前查询就已经结束了。目前这个时间间隔为 500ms,这意味着运行时间过短的查询可能会绕过策略的检查。 +- 当前支持的负载类型包括 select/insert select/stream load/broker load/routine load。 +- 一个查询可能匹配到多个 Policy,但是只有优先级最高的 Policy 会生效。 +- 目前不支持 Action 和 Condition 的修改,只能通过删除新建的方式修改。 + ### Workload Policy 效果演示 #### 1 session 变量修改测试 @@ -343,5 +347,5 @@ Actions(cancel_query) 再次执行 SQL 可以看到 SQL 执行会直接报错 ```sql mySQL [hits]>SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\.)?([^/]+)/.*$', '\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; -ERROR 1105 (HY000): errCode = 2, detailMessage = (10.16.10.8)[CANCELLED]query cancelled by workload Policy,id:12345 +ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[CANCELLED]query cancelled by workload Policy,id:12345 ``` \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/workload-group.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/workload-group.md index cc325ca3290..51e08d00d61 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/workload-group.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/admin-manual/workload-management/workload-group.md @@ -24,162 +24,216 @@ specific language governing permissions and limitations under the License. --> -在 Doris 中使用 Workload Group 管理与限制资源。通过资源管控方式可以有效限制查询与导入等负载所用的 CPU、内存与 IO 资源,也可以创建查询队列,控制集群中的查询最大并发量。自 Doris 2.1 版本后,使用基于 CGroup 对 CPU 资源进行限制。在使用 Workload 资源管控功能前,需要先配置 CGroup 环境。在创建 Workload Group 管控资源前,需要根据业务选择对资源进行软限或硬限: +用户可以使用Workload Group管理Doris集群中查询和导入负载,支持以下几种管控能力: +* 管理CPU资源,支持CPU硬限和CPU软限 +* 管理内存资源,支持内存硬限和内存软限 +* 管理IO资源,包括读本地文件和远程文件产生的IO +* 控制集群中的最大查询数量 -- 设置资源软限,在没有资源争用时,可以借用其他 Workload Group 资源,超过软限; - -- 设置资源硬限,无论是否存在资源争用,都无法超过硬限设置的资源配额。 - -在使用 Workload 资源管控时,需要执行以下操作: - -1. 创建 Workload Group; - -2. 向 Workload Group 中添加资源限制规则; - -3. 为租户绑定 Workload Group。 +在以下场景使用Workload Group通常会取得不错的效果: +1. 偏好性能稳定性胜过高资源利用率的场景,期望查询的延迟比较稳定,那么可以配置Workload Group的CPU硬限和IO硬限。 +2. 当集群整体负载过高导致可用性下降时,此时可以通过对集群中资源占用过高的WorkloadGroup进行降级处理来恢复集群的可用性,例如降低Workload Group的可用线程数,调低CPU硬限和IO上限。 ## 版本升级说明 -自 Doris 2.0 版本开始提供 Workload 资源管控功能。在 Doris 2.0 版本中,Workload 资源管控不依赖于 CGroup,而 Doris 2.1 版本中需要依赖 CGroup。 +自 Doris 2.0 版本开始提供 Workload Group 功能。在 Doris 2.0 版本中,Workload Group 功能不依赖于 CGroup,而 Doris 2.1 版本中需要依赖 CGroup。 -- 从 Doris 1.2 升级到 2.0:建议集群升级完成后,再开启 Workload 资源管控功能。只升级部分 follower FE 节点,可能会因为未升级的 FE 节点没有 Workload Group 的元数据信息,导致已升级的 follower FE 节点查询失败。 +- 从 Doris 1.2 升级到 2.0:建议集群升级完成后,再开启 Workload Group功能。只升级部分 follower FE 节点,可能会因为未升级的 FE 节点没有 Workload Group 的元数据信息,导致已升级的 follower FE 节点查询失败。 -- 从 Doris 2.0 升级到 2.1:由于 2.1 版本的 Workload 资源管控功能依赖于 CGroup,需要先配置 CGroup 环境,在升级到 Doris 2.1 版本。 +- 从 Doris 2.0 升级到 2.1:由于 2.1 版本的 Workload Group 功能依赖于 CGroup,需要先配置 CGroup 环境,再升级到 Doris 2.1 版本。 ## 配置 CGroup 环境 +在使用2.1版本的Workload Group功能之前,需要 BE 所在的节点上已经安装好 CGroup 的环境。 -在 Doris 的 2.0 版本使用基于 Doris 的调度实现 CPU 资源的限制,虽然提供了极大的灵活性,但由于 CPU 的隔离不够精准,无法提供 CPU 的硬隔离限制。从 2.1 版本起,Doris 使用基于 CGroup 对 CPU 资源进行限制,因此建议对资源隔离有强烈需求的用户升级到 2.1 版本,同时在所有 BE 节点上已经安装好 CGroup 的环境。 -用户如果在 2.0 版本使用了 Workload Group 的软限并升级到了 2.1 版本,那么也需要配置 CGroup,否则可能导致软限失效。在不配置 cgroup 的情况下,用户可以使用 Workload Group 除 CPU 限制外的所有功能。 +用户如果在 2.0 版本使用了 Workload Group 的软限并升级到了 2.1 版本,那么也需要配置 CGroup,否则可能导致CPU软限失效。 -:::tip -1. Doris BE 节点能够很好的使用机器的 CPU 与内存资源,建议单台机器上只部署一个 BE 实例,目前的 Workload 资源管控不支持一个机器多个 BE 的部署方式; -2. 当机器重启之后,以下的 CGroup 配置就会清空。如果期望配置重启之后可以也可以生效,可以使用 systemd 把操作设置成系统的自定义服务,这样在每次机器重启的时候,自动完成创建和授权操作 -3. 如果是在容器内使用 CGroup,需要容器具备操作宿主机的权限。 -::: +目前支持的 CGroup 版本为 CGroup v1 和 CGroup v2。 -### 确定 BE 节点安装 CGroup -通过检查 /proc/filesystems 文件可以判断是否安装 CGroup: +如果是在容器内使用 CGroup,需要容器具备操作宿主机的权限。 -``` -cat /proc/filesystems | grep cgroup -nodev cgroup -nodev cgroup2 -nodev cgroupfs -``` +在不配置 CGroup 的情况下,用户可以使用 Workload Group 除 CPU 限制外的所有功能。 -在上述返回结果中,列出了 cgroup,cgroup2 与 cgroupfs,这表明内核支持了 CGroup。还需要进一步查看 CGroup 版本。 - -#### 确定 CGroup 版本 -系统使用 CGroup V1,会有多个子系统分别挂在在 /sys/fs/cgroup 目录下。如果包含了 /sys/fs/cgroup/cpu 目录,说明目前生效的是 CGroup V1: +以下为CGroup环境配置流程: +1. 首先确认 BE 所在节点是否已经安装好 GGroup,输出结果中```cgroup``` 代表目前的环境已经安装CGroup V1,```cgroup2``` 代表目前的环境已安装CGroup V2,至于具体是哪个版本生效,可以通过下一步确认。 ```shell -## 包含 /sys/fs/cgroup/cpu 目录,CGroup V1 生效 -ls /sys/fs/cgroup/cpu +cat /proc/filesystems | grep cgroup +nodev cgroup +nodev cgroup2 +nodev cgroupfs ``` -系统使用 CGroup V2,会采用统一的层级结构,所有的控制器都在一个文件系统中管理。如果包含了 /sys/fs/cgroup/cgroup.controllers 目录,则证明目前生效的是 CGroup V2: - +2. 通过路径名称可以确认目前生效的 CGroup 版本。 ```shell -## 包含 /sys/fs/cgroup/cgroup.controllers 目录,CGroup V2 生效 -ls /sys/fs/cgroup/cgroup.controllers +如果存在这个路径说明目前生效的是cgroup v1 +/sys/fs/cgroup/cpu/ + + +如果存在这个路径说明目前生效的是cgroup v2 +/sys/fs/cgroup/cgroup.controllers ``` -在 Doris 中使用 Workload 管控资源,需要针对于 CGroup 的版本分别配置。 -### 使用 CGroup V1 版本 -如果使用 CGroup V1 版本,需要为 Doris 在 /sys/fs/cgroup/cpu 目录下创建 CPU 管控目录。您可以自定义该目录名称,下例中使用 /sys/fs/cgroup/cpu/doris: +3. 在 CGroup 路径下新建一个名为 doris 的目录,这个目录名用户可以自行指定 ```shell -## Create cgroup dir for Doris +如果是cgroup v1就在cpu目录下新建 mkdir /sys/fs/cgroup/cpu/doris -## Modify the Doris cgroup directory permissions -chmod 770 /sys/fs/cgroup/cpu/doris -## Grant user permissions for Doris usage -chown -R doris:doris /sys/fs/cgroup/cpu/doris +如果是cgroup v2就在直接在cgroup目录下新建 +mkdir /sys/fs/cgroup/doris ``` -### 使用 CGroup V2 版本 -因为 CGroup V2 对于权限管控比较严格,需要具备根目录的 cgroup.procs 文件的写权限才能实现进程在 group 之间的移动。 -通过以下命令为 cgroup.procs 目录授权: +4. 需要保证 Doris 的 BE 进程对于这个目录有读/写/执行权限 +```shell +// 如果是CGroup v1,那么命令如下: +// 1. 修改这个目录的权限为可读可写可执行 +chmod 770 /sys/fs/cgroup/cpu/doris +// 2. 把这个目录的归属划分给doris的账户 +chown -R doris:doris /sys/fs/cgroup/cpu/doris + + +// 如果是CGroup v2,那么命令如下: +// 1. 修改这个目录的权限为可读可写可执行 +chmod 770 /sys/fs/cgroup/doris +// 2. 把这个目录的归属划分给doris的账户 +chown -R doris:doris /sys/fs/cgroup/doris +``` +5. 如果目前环境里生效的是CGroup v2版本,那么还需要做以下操作。这是因为CGroup v2对于权限管控比较严格,需要具备根目录的cgroup.procs文件的写权限才能实现进程在group之间的移动。 + 如果是CGroup v1那么不需要这一步。 ```shell chmod a+w /sys/fs/cgroup/cgroup.procs ``` -### 为 BE 节点配置 CGroup 环境 -在使用 Workload 进行资源管控前,需要在 BE 的配置文件 be/conf/be.conf 中配置 CGroup 的路径: -``` +6. 修改 BE 的配置,指定 cgroup 的路径 +```shell +如果是Cgroup v1,那么配置路径如下 doris_cgroup_cpu_path = /sys/fs/cgroup/cpu/doris + +如果是Cgroup v2,那么配置路径如下 +doris_cgroup_cpu_path = /sys/fs/cgroup/doris ``` -在配置 be.conf 文件后,需要重启 BE 节点,在 BE.INFO 日志文件中可以查看到 add thread {pid} to group 提示,表示配置成功。 -## 使用 Workload Group 管理资源 -在创建 Workload Group 后,可以为 Workload Group 添加资源限制规则。Doris 目前支持以下资源的规则限制: +7. 重启 BE,在日志(be.INFO)可以看到"add thread xxx to group"的字样代表配置成功 -- 对 CPU 进行硬限或软限 +:::tip +1. 建议单台机器上只部署一个 BE 实例,目前的 Workload Group 功能不支持一个机器上部署多个 BE ; +2. 当机器重启之后,CGroup 路径下的所有配置就会清空。如果期望CGroup配置持久化,可以使用 systemd 把操作设置成系统的自定义服务,这样在每次机器重启的时可以自动完成创建和授权操作 +3. 如果是在容器内使用 CGroup,需要容器具备操作宿主机的权限。 +::: -- 对内存进行硬限或软限 +### 在K8S中使用Workload Group的注意事项 +Workload的CPU管理是基于CGroup实现的,如果期望在容器中使用Workload Group,那么需要以特权模式启动容器,容器内的Doris进程才能具备读写宿主机CGroup文件的权限。 +当Doris在容器内运行时,Workload Group的CPU资源用量是在容器可用资源的情况下再划分的,例如宿主机整机是64核,容器被分配了8个核的资源,Workload Group配置的CPU硬限为50%, +那么Workload Group实际可用核数为4个(8核 * 50%)。 -- 对远程或本地 IO 进行限制 +WorkloadGroup的内存管理和IO管理功能是Doris内部实现,不依赖外部组件,因此在容器和物理机上部署使用并没有区别。 -- 创建查询队列管理查询作业 +如果要在K8S上使用Doris,建议使用Doris Operator进行部署,可以屏蔽底层的权限细节问题。 -### 创建自定义 Workload Group -需要使用具有 ADMIN 权限的用户创建 Workload Group,同时添加资源规则。通过 `CREATE WORKLOAD GROUP` 语句可以创建自定义 Workload Group。自 Doris 2.1 版本起,系统会自动创建名为 Normal 的 Workload Group,用户会默认绑定到 Normal 下。在以下示例中创建了 Workload Group g1,同时添加了 CPU 与内存资源的限制规则: +## Workload Group基本使用 -``` -CREATE Workload Group IF NOT EXISTS g1 -PROPERTIES( - "cpu_share"="1024", - "memory_limit"="30%" -); -``` +### Workload Group属性 +* cpu_share: 可选,默认值为 -1。有效值的取值范围是正整数。用于设置 workload group 获取 CPU 时间的多少,可以实现 CPU 资源软隔离。cpu_share 是相对值,表示正在运行的 workload group 可获取 CPU 资源的权重。例如,用户创建了 3 个 workload group g-a、g-b 和 g-c,cpu_share 分别为 10、30、40,某一时刻 g-a 和 g-b 正在跑任务,而 g-c 没有任务,此时 g-a 可获得 25% (10 / (10 + 30)) 的 CPU 资源,而 g-b 可获得 75% 的 CPU 资源。如果系统只有一个 workload group 正在运行,则不管其 cpu_share 的值为多少,它都可获取全部的 CPU 资源。 -### 修改 Workload Group 的资源规则 +* memory_limit: 可选,默认值 -1,含义为不限制内存使用。有效值的取值范围 1%~100%,用于设置 workload group 可以使用 be 内存的百分比。Workload Group 可用的最大内存,所有 group 的累加值不可以超过 100%,通常与 enable_memory_overcommit 配合使用。如果一个机器的内存为 64G,mem_limit=50%,那么该 group 的实际物理内存=64G * 90%(be conf mem_limit) * 50%= 28.8G,这里的 90% 是 BE 进程级别的 mem_limit 参数,限制整个 BE 进程的内存用量。一个集群中所有 Workload Group 的 memory_limit 的累加值不能超过 100%。 -访问 Doris 系统表 `information_schema.workload_groups` 可以查看创建的 Workload Group 信息。 -删除 Workload Group 可以参考 [DROP WORKLOAD GROUP](../../sql-manual/sql-statements/cluster-management/compute-management/DROP-RESOURCE); -通过 ALTER-WORKLOAD-GROUP 命令可以调整与修改 Workload Group 配置,参考 [ALTER-WORKLOAD-GROUP](../../sql-manual/sql-statements/cluster-management/compute-management/ALTER-WORKLOAD-GROUP.md). +* enable_memory_overcommit: 可选,用于开启 workload group 内存软隔离,默认为 true。如果设置为 false,则该 workload group 为内存硬隔离,系统检测到 workload group 内存使用超出限制后将立即 cancel 组内内存占用最大的若干个任务,以释放超出的内存;如果设置为 true,则该 workload group 为内存软隔离,如果系统有空闲内存资源则该 workload group 在超出 memory_limit 的限制后可继续使用系统内存,在系统总内存紧张时会 cancel 组内内存占用最大的若干个任务,释放部分超出的内存以缓解系统内存压力。建议在有 workload group 开启该配置时,所有 workload group 的 memory_limit 总和低于 100%,剩余部分用于 workload group 内存超发。 -#### 添加与修改资源项 -在以下示例中,为 g1 资源组修改了内存限制规则: +* cpu_hard_limit:可选,默认值 -1,含义为不限制CPU上限。取值范围 1%~100%,CPU 硬限制模式下,Workload Group 最大可用的 CPU 百分比,不管当前机器的 CPU 资源是否被用满,Workload Group 的最大 CPU 用量都不能超过 cpu_hard_limit, + 所有 Workload Group 的 cpu_hard_limit 累加值不能超过 100%。2.1 版本新增属性,2.0版本不支持该功能。 -```sql -ALTER Workload Group g1 PROPERTIES('memory_limit'='10%'); +* max_concurrency:可选,最大查询并发数,默认值为整型最大值,也就是不做并发的限制。运行中的查询数量达到该值时,新来的查询会进入排队的逻辑。 + +* max_queue_size:可选,查询排队队列的长度,当排队队列已满时,新来的查询会被拒绝。默认值为 0,含义是不排队。 + +* queue_timeout:可选,查询在排队队列中的超时时间,单位为毫秒,如果查询在队列中的排队时间超过这个值,那么就会直接抛出异常给客户端。默认值为 0,含义是不排队。 + +* scan_thread_num:可选,当前 workload group 用于 scan 的线程个数,默认值为 -1,含义是不生效,此时以 be 配置中的 scan 线程数为准。取值为大于 0 的整数。 + +* max_remote_scan_thread_num:可选,读外部数据源的scan线程池的最大线程数,默认值为-1,当该值为-1时,实际的线程数由BE自行决定,通常和核数相关。 + +* min_remote_scan_thread_num:可选,读外部数据源的scan线程池的最小线程数,默认值为-1,当该值为-1时,实际的线程数由BE自行决定,通常和核数相关。 + +* tag:可选,默认为空,为Workload Group指定标签,相同标签的Workload Group资源累加值不能超过100%,如果期望指定多个值,可以使用英文逗号分隔。 + +* read_bytes_per_second:可选,含义为读Doris内表时的最大IO吞吐,默认值为-1,也就是不限制IO带宽。需要注意的是这个值并不绑定磁盘,而是绑定文件夹。 + 比如为Doris配置了2个文件夹用于存放内表数据,那么每个文件夹的最大读IO不会超过该值,如果这2个文件夹都配置到同一块盘上,最大吞吐控制就会变成2倍的read_bytes_per_second。落盘的文件目录也受该值的约束。 + +* remote_read_bytes_per_second:可选,含义为读Doris外表时的最大IO吞吐,默认值为-1,也就是不限制IO带宽。 + +:::tip + +1. 目前暂不支持 CPU 的软限和硬限的同时使用,一个集群某一时刻只能是软限或者硬限,下文中会描述切换方法。 + +2. 所有属性均为可选,但是在创建 Workload Group 时需要指定至少一个属性。 + +3. 需要注意 CGroup v1 CGroup v2 版本 CPU 软限默认值是有区别的, CGroup v1 的 CPU 软限默认值为1024,取值范围为2到262144。而 CGroup v2 的 CPU 软限默认值为100,取值范围是1到10000。 + 如果软限填了一个超出范围的值,这会导致 CPU 软限在BE修改失败。是在CGroup v1的环境上如果按照CGroup v2的默认值100设置,这可能导致这个workload group的优先级在该机器上是最低的。 + ::: + +## workload group 基本使用 +### 创建Workload Group ``` +mysql [information_schema]>create workload group if not exists g1 + -> properties ( + -> "cpu_share"="1024" + -> ); +Query OK, 0 rows affected (0.03 sec) -通过 information_schema.workload_groups 系统表可以查看到修改后的内存限制: +``` +可以参考 [CREATE-WORKLOAD-GROUP](../../sql-manual/sql-statements/Data-Definition-Statements/Create/CREATE-WORKLOAD-GROUP)。 -```sql -SELECT name, memory_limit FROM information_schema.workload_groups; -+--------+--------------+ -| name | memory_limit | -+--------+--------------+ -| normal | 30% | -| g1 | 10% | -+--------+--------------+ +此时配置的 CPU 限制为软限。自 2.1 版本起,系统会自动创建一个名为```normal```的 group,不可删除。 + +### 查看Workload Group +1. 通过show语句查看 +``` +show workload groups; ``` +可以参考[SHOW-WORKLOAD-GROUPS](../../sql-manual/sql-statements/Show-Statements/SHOW-WORKLOAD-GROUPS)。 -#### 配置资源软限与硬限 +2. 通过系统表查看 +``` +mysql [information_schema]>select * from information_schema.workload_groups where name='g1'; ++-------+------+-----------+--------------+--------------------------+-----------------+----------------+---------------+----------------+-----------------+----------------------------+----------------------------+----------------------+-----------------------+------+-----------------------+------------------------------+ +| ID | NAME | CPU_SHARE | MEMORY_LIMIT | ENABLE_MEMORY_OVERCOMMIT | MAX_CONCURRENCY | MAX_QUEUE_SIZE | QUEUE_TIMEOUT | CPU_HARD_LIMIT | SCAN_THREAD_NUM | MAX_REMOTE_SCAN_THREAD_NUM | MIN_REMOTE_SCAN_THREAD_NUM | MEMORY_LOW_WATERMARK | MEMORY_HIGH_WATERMARK | TAG | READ_BYTES_PER_SECOND | REMOTE_READ_BYTES_PER_SECOND | ++-------+------+-----------+--------------+--------------------------+-----------------+----------------+---------------+----------------+-----------------+----------------------------+----------------------------+----------------------+-----------------------+------+-----------------------+------------------------------+ +| 14009 | g1 | 1024 | -1 | true | 2147483647 | 0 | 0 | -1 | -1 | -1 | -1 | 50% | 80% | | -1 | -1 | ++-------+------+-----------+--------------+--------------------------+-----------------+----------------+---------------+----------------+-----------------+----------------------------+----------------------------+----------------------+-----------------------+------+-----------------------+------------------------------+ +1 row in set (0.05 sec) +``` -使用 Workload Group 功能,可以为 CPU 以及内存资源设置软限与硬限,对于远程与本地 IO,只提供硬限能力: +### 修改Workload Group +``` +mysql [information_schema]>alter workload group g1 properties('cpu_share'='2048'); +Query OK, 0 rows affected (0.00 sec -- 软限:软限作为资源的警戒线,用户正常操作中不会超过这个限度。当其他 Workload Group 负载较低时,可以借用其他 Workload Group 资源,超过软限设置; +mysql [information_schema]>select cpu_share from information_schema.workload_groups where name='g1'; ++-----------+ +| cpu_share | ++-----------+ +| 2048 | ++-----------+ +1 row in set (0.02 sec) -- 硬限:硬限作为资源的绝对使用上限,无论其他 Workload Group 是否有负载,都不能超过硬限上限。硬限通常用来防止系统资源被滥用。 +``` -| | 软限开关与参数 | 硬限开关与参数 | 说明 | -| ----------- |----------------------------------------------------------------------|------------------------------------------------------------------------------------|-----| -| CPU | 开关:FE Config - enable_cpu_hard_limit = false 参数:Property - cpu_share | 开关:FE Config - enable_cpu_hard_limit = true <br /> 参数:property - cpu_hard_limit 修改 CPU 硬限 |不同 Workload Group 只能同时设置软限或硬限,无法设置部分组硬限及部分组软限 | -| Memory | 开关:property - enable_memory_overcommit = true <br /> 参数:property - memory_limit | 开关:property - enable_memory_overcommit = false <br /> 参数:property - memory_limit | 不同 Workload Group 可以任意设置软限或硬限,部分组可以设置硬限,部分组可以设置软限 | -| 本地 IO | 无 | 参数:read_bytes_per_second | 暂时只提供本地 IO 硬限 | -| 远程 IO | 无 | 参数:remote_read_bytes_per_second | 暂时只提供远程 IO 硬限 | +可以参考:[ALTER-WORKLOAD-GROUP](../../sql-manual/sql-statements/Data-Definition-Statements/Alter/ALTER-WORKLOAD-GROUP)。 +### 删除Workload Group +``` +mysql [information_schema]>drop workload group g1; +Query OK, 0 rows affected (0.01 sec) +``` -### 为租户绑定 Workload Group +可以参考:[DROP-WORKLOAD-GROUP](../../sql-manual/sql-statements/Data-Definition-Statements/Drop/DROP-WORKLOAD-GROUP)。 -使用非 ADMIN 用户,需要先确定是否具有该 Workload Group 的权限。通过查看 information_schema.workload_groups 系统表判断是否具有使用 Workload Group 的权限。当可以查询到 Workload Group 时,代表具有使用该 Workload Group 的权限。下例中代表可以使用 g1 与 normal Workload Group: +### 用户绑定Workload Group +在把用户绑定到某个Workload Group之前,需要先确定该用户是否具有某个 Workload Group 的权限。 +可以使用这个用户查看 information_schema.workload_groups 系统表,返回的结果就是当前用户有权限使用的Workload Group。 +下面的查询结果代表当前用户可以使用 g1 与 normal Workload Group: ```sql SELECT name FROM information_schema.workload_groups; @@ -191,56 +245,488 @@ SELECT name FROM information_schema.workload_groups; +--------+ ``` -如果无法看到 g1 Workload Group,可以使用 GRANT 语句为用户授权。 -在为租户绑定 Workload Group 时,可以通过设置 user property 或指定 session 变量两种方式。当同时使用了两种方式时,session 变量的优先级要高于 user property: +如果无法看到 g1 Workload Group,可以使用ADMIN账户执行 GRANT 语句为用户授权。例如: +``` +"GRANT USAGE_PRIV ON WORKLOAD GROUP 'g1' TO 'user_1'@'%';" +``` +这个语句的含义是把名为 g1 的 Workload Group的使用权限授予给名为 user_1 的账户。 +更多授权操作可以参考[grant 语句](../../sql-manual/sql-statements/Account-Management-Statements/GRANT)。 + +**两种绑定方式** +1. 通过设置 user property 将 user 默认绑定到 workload group,默认为`normal`,需要注意的这里的value不能填空,否则语句会执行失败,如果不知道要设置哪些group,可以设置为`normal`,`normal`为全局默认的group。 +``` +set property 'default_workload_group' = 'g1'; +``` +执行完该语句后,当前用户的查询将默认使用'g1'。 + + +2. 通过 session 变量指定 workload group, 默认为空: +``` +set workload_group = 'g1'; +``` +当同时使用了两种方式时为用户指定了Workload Group,session 变量的优先级要高于 user property 。 + +### CPU 软硬限模式切换的说明 +目前 Doris 暂不支持同时运行 CPU 的软限和硬限,一个 Doris 集群在任意时刻只能是 CPU 软限或者 CPU 硬限。 +用户可以在两种模式之间进行切换,切换方法如下: + +1 假如当前的集群配置是默认的 CPU 软限,期望改成 CPU 的硬限,需要把 Workload Group 的 cpu_hard_limit 参数修改成一个有效的值 +``` +alter workload group test_group properties ( 'cpu_hard_limit'='20%' ); +``` +集群中所有的Workload Group都需要修改,所有 Workload Group 的 cpu_hard_limit 的累加值不能超过 100% 。 + +由于 CPU 的硬限无法给出一个有效的默认值,因此如果只打开开关但是不修改属性,那么 CPU 的硬限也无法生效。 + +2 在所有 FE 中打开 CPU 硬限的开关 +``` +1 修改磁盘上fe.conf的配置 +experimental_enable_cpu_hard_limit = true +2 修改内存中的配置 +ADMIN SET FRONTEND CONFIG ("enable_cpu_hard_limit" = "true"); +``` + +如果用户期望从 CPU 的硬限切换回 CPU 的软限,需要在所有 FE 修改 enable_cpu_hard_limit 的值为 false 即可。 +CPU 软限的属性 cpu_share 默认会填充一个有效值 1024(如果之前未指定 cpu_share 的值),用户可以根据 group 的优先级对 cpu_share 的值进行重新调整。 + +### 查询排队功能 +``` +create workload group if not exists queue_group +properties ( + "max_concurrency" = "10", + "max_queue_size" = "20", + "queue_timeout" = "3000" +); +``` +如果集群中目前有1台FE,那么这个配置的含义为,集群中同时运行的查询数最大不超过10个,当最大并发已满时,新来的查询会排队,队列的长度不超过20。查询在队列中排队的时间最长为3s,排队超过3s的查询会直接返回失败给客户端。 + + +1. 需要注意的是,目前的排队设计是不感知 FE 的个数的,排队的参数只在单 FE 粒度生效,例如: + +一个 Doris 集群配置了一个 work load group,设置 max_concurrency = 1 +如果集群中有 1FE,那么这个 workload group 在 Doris 集群视角看同时只会运行一个 SQL +如果有 3 台 FE,那么在 Doris 集群视角看最大可运行的 SQL 个数为 3 + +2. 在有些运维情况下,管理员账户需要绕开排队的逻辑,那么可以通过设置session变量: +``` +set bypass_workload_group = true; +``` + +## 效果测试 +### 测试内存硬限 +Adhoc 类查询通常输入的 SQL 不确定,使用的内存资源也不确定,因此存在少数查询占用很大内存的风险。 +可以对这类负载可以划分到独立的分组,通过 Workload Group 对内存的硬限的功能,避免突发性的大查询占满所有内存,导致其他查询没有可用内存或者 OOM。 +当这个 Workload Group 的内存使用超过配置的硬限值时,会通过杀死查询的方式释放内存,避免进程内存被打满。 + +**测试环境** + +1FE,1BE,BE 配置为 96 核,内存大小为 375G。 + +测试数据集为 clickbench,测试方法为使用 jmeter 起三并发执行 q29。 + +**测试不开启 Workload Group 的内存硬限** + +1. 查看进程使用内存。ps 命令输出第四列代表进程使用的物理内存的用量,单位为 kb,可以看到当前测试负载下,进程的内存使用为 7.7G 左右。 + + ```sql + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 2.0 7896792 + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 2.0 7929692 + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 2.0 8101232 + ``` + +2. 使用 Doris 系统表查看当前 Workload Group 的内存用量,Workload Group 的内存用量为 5.8G 左右。 + + ```sql + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +-------------------+ + | wg_mem_used_mb | + +-------------------+ + | 5797.524360656738 | + +-------------------+ + 1 row in set (0.01 sec) + + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +-------------------+ + | wg_mem_used_mb | + +-------------------+ + | 5840.246627807617 | + +-------------------+ + 1 row in set (0.02 sec) + + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +-------------------+ + | wg_mem_used_mb | + +-------------------+ + | 5878.394917488098 | + +-------------------+ + 1 row in set (0.02 sec) + ``` + +这里可以看到进程的内存使用通常要远大于一个 Workload Group 的内存用量,即使进程内只有一个 Workload Group 在跑,这是因为 Workload Group 只统计了查询和部分导入的内存,进程内的其他组件比如元数据,各种 Cache 的内存是不计算 Workload Group 内的,也不由 Workload Group 管理。 + +**测试开启 Workload Group 的内存硬限** +1. 执行 SQL 命令修改内存配置。 + + ```sql + alter workload group g2 properties('memory_limit'='0.5%'); + alter workload group g2 properties('enable_memory_overcommit'='false'); + ``` + +2. 执行同样的测试,查看系统表的内存用量,内存用量为 1.5G 左右。 + + ```sql + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +--------------------+ + | wg_mem_used_mb | + +--------------------+ + | 1575.3877239227295 | + +--------------------+ + 1 row in set (0.02 sec) + + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +------------------+ + | wg_mem_used_mb | + +------------------+ + | 1668.77405834198 | + +------------------+ + 1 row in set (0.01 sec) + + mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201; + +--------------------+ + | wg_mem_used_mb | + +--------------------+ + | 499.96760272979736 | + +--------------------+ + 1 row in set (0.01 sec) + ``` + +3. 使用 ps 命令查看进程的内存用量,内存用量为 3.8G 左右。 + + ```sql + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 1.0 4071364 + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 1.0 4059012 + [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481 + 1407481 doris_be 1.0 4057068 + ``` + +4. 同时客户端会观察到大量由于内存不足导致的查询失败。 + + ```sql + 1724074250162,14126,1c_sql,HY000 1105,"java.sql.SQLException: errCode = 2, detailMessage = (127.0.0.1)[MEM_LIMIT_EXCEEDED]GC wg for hard limit, wg id:11201, name:g2, used:1.71 GB, limit:1.69 GB, backend:10.16.10.8. cancel top memory used tracker <Query#Id=4a0689936c444ac8-a0d01a50b944f6e7> consumption 1.71 GB. details:process memory used 3.01 GB exceed soft limit 304.41 GB or sys available memory 101.16 GB less than warning water mark 12.80 GB., Execute again after enough memory, det [...] + ``` + +这个报错信息中可以看到,Workload Group 使用了 1.7G 的内存,但是 Workload Group 的限制是 1.69G,这里的计算方式是这样的 1.69G = 物理机内存 (375) * mem_limit(be.conf 中的值,默认为 0.9) * 0.5%(Workload Group 的配置) +也就是说,Workload Group 中配置的内存百分比是基于 Doris 进程可用内存再次进行计算的。 + + +**使用建议** + +如上文测试,硬限可以控制 Workload Group 的内存使用,但却是通过杀死查询的方式释放内存,这对用户来说体验会非常不友好,极端情况下可能会导致所有查询都失败。 +因此在生产环境中推荐内存硬限配合查询排队的功能一起使用,可以在限制内存使用的同时保证查询的成功率。 + + + +### CPU 硬限测试 +Doris 的负载大体可以分为三类: +1. 核心报表查询,通常给公司高层查看报表使用,负载不一定很高,但是对可用性要求较高,这类查询可以划分到一个分组,配置较高优先级的软限,保证 CPU 资源不够时可以获得更多的 CPU 资源。 +2. Adhoc 类查询,这类查询通常偏探索分析,SQL 比较随机,具体的资源用量也比较未知,优先级通常不高。因此可以使用 CPU 硬限进行管理,并配置较低的值,避免占用过多 CPU 资源降低集群可用性。 +3. ETL 类查询,这类查询的 SQL 比较固定,资源用量通常也比较稳定,偶尔会出现上游数据量增长导致资源用量暴涨的情况,因此可以使用 CPU 硬限进行配置。 + +不同的负载对 CPU 的消耗不一样,用户对响应延时的需求也不一样。当 BE 的 CPU 被用的很满时,可用性会变差,响应延时会变高。比如可能一个 Adhoc 的分析类查询把整个集群的 CPU 打满,导致核心报表的延时变大,影响到了 SLA。所以需要 CPU 隔离机制来对不同的业务进行隔离,保障集群的可用性和 SLA。 +Workload Group 支持 CPU 的软限和硬限,目前比较推荐在线上环境把 Workload Group 配置成硬限。原因是 CPU 的软限通常在 CPU 被打满时才能体现出优先级的作用,但是在 CPU 被用满时,Doris 的内部组件(例如 rpc 组件)以及操作系统可用的 CPU 会减少,此时集群整体的可用性是下降比较严重的,因此生产环境通常需要避免 CPU 资源被打满的情况,当然其他资源也一样,内存资源同理。 + + +**测试环境** + +1FE,1BE,96 核机器。 +数据集为 clickbench,测试 sql 为 q29。 + +**发起测试** +1. 使用 jmeter 发起 3 并发查询,把 BE 进程的 CPU 使用压到比较高的使用率,这里测试的机器是 96 核,使用 top 命令看到 BE 进程 CPU 使用率为 7600% 的含义是该进程目前使用中的核数是 76 个。 + +  + +2. 修改使用中的 Workload Group 的 CPU 硬限为 10%。 + + ```sql + alter workload group g2 properties('cpu_hard_limit'='10%'); + ``` + +3. 集群开启硬限模式,此时集群中所有 Group 都会切换为硬限。 + + ```sql + ADMIN SET FRONTEND CONFIG ("enable_cpu_hard_limit" = "true"); + ``` + +4. 重新压测查询负载,可以看到当前进程只能使用 9 到 10 个核,占总核数的 10% 左右。 + +  + +需要注意的是,这里的测试最好使用查询负载会比较能体现出效果,因为如果是高吞吐导入的话,可能会触发 Compaction,使得实际观测的值要比 Workload Group 配置的值大。而 Compaction 的负载目前是没有归入 Workload Group 的管理的。 + +5. 除了使用 Linux 的系统命令外,还可以通过使用 Doris 的系统表观察 Group 目前的 CPU 使用为 10% 左右。 + + ```sql + mysql [information_schema]>select CPU_USAGE_PERCENT from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +-------------------+ + | CPU_USAGE_PERCENT | + +-------------------+ + | 9.57 | + +-------------------+ + 1 row in set (0.02 sec) + ``` + +**注意事项** + +1. 在实际配置的时候,所有 Group 的 CPU 累加值最好不要正好等于 100%,这主要是为了保证低延迟场景的可用性。因为需要让出一部分资源给其他组件使用。当然如果对延迟不是很敏感的场景,期望最高的资源利用率,那么可以考虑所有 Group 的 CPU 累加值配置等于 100%。 +2. 目前 FE 向 BE 同步 Workload Group 元数据的时间间隔为 30 秒,因此对于 Workload Group 的变更最大需要等待 30 秒才能生效。 + + +### 测试本地 IO 硬限 +OLAP 系统在做 ETL 或者大的 Adhoc 查询时,需要读取大量的数据,Doris 为了加速数据分析过程,内部会使用多线程并行的方式对多个磁盘文件扫描,会产生巨大的磁盘 IO,就会对其他的查询(比如报表分析)产生影响。 +可以通过 Workload Group 对离线的 ETL 数据处理和在线的报表查询做分组,限制离线数据处理 IO 带宽的方式,降低它对在线报表分析的影响。 -- 使用 user property 绑定 Workload Group:一般由管理员使用 SET-PROPERTY 命令为租户绑定默认的 Workload Group。在以下示例中,为 test_wlg 租户绑定了默认 Workload Group g1: +**测试环境** - ```sql - set property for 'test_wlg' 'default_workload_group' = 'g1'; - ``` +1FE,1BE, 配置为 96 核。 -- 使用 session 变量绑定 Workload Group:在业务开发的过程中,即便管理员配置了默认的 Workload Group,也可以在 session 中通过 workload_group 变量修改。在以下示例中,为当前 session 配置了绑定 Workload Group g1: +测试数据集为 clickbench。 - ```sql - SET workload_group = 'g1'; - ``` +**不开启 IO 硬限测试** +1. 关闭缓存。 -## 为 Workload Group 设置分组 + ```sql + // 清空操作系统缓存 + sync; echo 3 > /proc/sys/vm/drop_caches -在多负载或多租户环境中,一个 Doris 集群可能被拆分成多个子集群使用,如部分节点用于外部存储的联邦查询,部分节点用于内表实时查询。Workload Group 可以为 BE 节点打标签(tag),标签相同的 BE 节点组成子集群。每个子集群的资源独立计算,子集群内累加值不能超过 100%。在下例中,将七台机器分成 sub_a 与 sub_b 两个子集群,两个子集群中分别创建了两个 Workload Group。 -在多负载或多租户的环境中,一个 Doris 集群可能被拆分成多个子集群使用,如部分节点用于外部存储的联邦查询,部分节点用于内部表的事实查询,两个自己群在数据分布与资源使用上完全隔离。在同一个子集群群内,需要创建多个租户并创建租户之间的资源使用隔离规则。针对于这类复杂的资源隔离要求,可以结合 Resource Group 与 Workload Group 功能,使用 Resource Group 实现多个子集群的节点粒度隔离,在自己群内使用 Workload Group 进行租户间的资源隔离。如下图中划分成 A、B 两个子集群,每个子集群中有各自的 Workload Group 进行资源管控: + // 禁用 BE 的 page cache + disable_storage_page_cache = true + ``` - +2. 对 clickbench 的表执行全表扫描,执行单并发查询即可。 -1. 创建 A 与 B 两个 Resource Group,将 7 台机器划分成两个子集群 + ```sql + set dry_run_query = true; + select * from hits.hits; + ``` + +3. 通过 Doris 的内表查看当前 Group 的最大吞吐为 3GB 每秒。 ```sql - -- create resource group sub_cluster_a - ALTER SYSTEM MODIFY BACKEND "192.168.88.31:9050" SET("tag.location" = "sub_cluster_a"); - ALTER SYSTEM MODIFY BACKEND "192.168.88.32:9050" SET("tag.location" = "sub_cluster_a"); - ALTER SYSTEM MODIFY BACKEND "192.168.88.33:9050" SET("tag.location" = "sub_cluster_a"); + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 1146.6208400726318 | + +--------------------+ + 1 row in set (0.03 sec) + + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 3496.2762966156006 | + +--------------------+ + 1 row in set (0.04 sec) + + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 2192.7690029144287 | + +--------------------+ + 1 row in set (0.02 sec) + ``` + +4. 使用 pidstat 命令查看进程 IO,图中第一列是进程 id,第二列是读 IO 的吞吐(单位是 kb/s)。可以看到不限制 IO 时,最大吞吐为 2G 每秒。 - -- create resource group sub_cluster_b - ALTER SYSTEM MODIFY BACKEND "192.168.88.34:9050" SET("tag.location" = "sub_cluster_b"); - ALTER SYSTEM MODIFY BACKEND "192.168.88.35:9050" SET("tag.location" = "sub_cluster_b"); +  + + +**开启 IO 硬限后测试** +1. 关闭缓存。 + + ```sql + // 清空操作系统缓存 + sync; echo 3 > /proc/sys/vm/drop_caches + + // 禁用 BE 的 page cache + disable_storage_page_cache = true ``` -2. 为子集群创建 Workload Group 进行内存资源隔离 +2. 修改 Workload Group 的配置,限制每秒最大吞吐为 100M。 ```sql - -- create Workload Groups for sub cluster A - CREATE Workload Group a_wlg_1 PROPERTIES('tag' = "sub_cluster_a", "memory_limit" = "30"); - CREATE Workload Group a_wlg_2 PROPERTIES('tag' = "sub_cluster_a", "memory_limit" = "30"); - CREATE Workload Group a_wlg_3 PROPERTIES('tag' = "sub_cluster_a", "memory_limit" = "30"); + // 限制当前 Group 的读吞吐为每秒 100M + alter workload group g2 properties('read_bytes_per_second'='104857600'); + ``` - -- create Workload Groups for sub cluster B - CREATE Workload Group b_wlg_1 PROPERTIES('tag' = "sub_cluster_b", "memory_limit" = "30"); - CREATE Workload Group b_wlg_2 PROPERTIES('tag' = "sub_cluster_b", "memory_limit" = "30"); +3. 使用 Doris 系统表查看 Workload Group 的最大 IO 吞吐为每秒 98M。 + + ```sql + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 97.94296646118164 | + +--------------------+ + 1 row in set (0.03 sec) + + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 98.37584781646729 | + +--------------------+ + 1 row in set (0.04 sec) + + mysql [information_schema]>select LOCAL_SCAN_BYTES_PER_SECOND / 1024 / 1024 as mb_per_sec from workload_group_resource_usage where WORKLOAD_GROUP_ID=11201; + +--------------------+ + | mb_per_sec | + +--------------------+ + | 98.06641292572021 | + +--------------------+ + 1 row in set (0.02 sec) ``` -## 注意事项 +4. 使用 pid 工具查看进程最大 IO 吞吐为每秒 131M。 + +  + +**注意事项** +1. 系统表中的 LOCAL_SCAN_BYTES_PER_SECOND 字段代表的是当前 Workload Group 在进程粒度的统计汇总值,比如配置了 12 个文件路径,那么 LOCAL_SCAN_BYTES_PER_SECOND 就是这 12 个文件路径 IO 的最大值,如果期望查看每个文件路径分别的 IO 吞吐,可以在 grafana 上或者 BE 的 bvar 监控查看明细的值。 + +2. 由于操作系统和 Doris 的 Page Cache 的存在,通过 linux 的 IO 监控脚本看到的 IO 通常要比系统表看到的要小。 + + +### 测试远程 IO 限制 +BrokerLoad 和 S3Load 是常用的大批量数据导入方式,用户可以把数据先上传到 HDFS 或者 S3,然后通过 Brokerload 和 S3Load 对数据进行并行导入。Doris 为了加快导入速度,会使用多线程并行的方式从 HDFS/S3 拉取数据,此时会对 HDFS/S3 产生巨大的压力,会导致 HDFS/S3 上运行的别的作业不稳定。 +可以通过 Workload Group 远程 IO 的限制功能来限制导入过程中对 HDFS/S3 的带宽,降低对其他业务的影响。 + + +**测试环境** + +1FE,1BE 部署在同一台机器,配置为 16 核 64G 内存。测试数据为 clickbench 数据集,测试前需要把数据集上传到 S3 上。考虑到上传时间的问题,我们只取其中的 1 千万行数据上传,然后使用 tvf 的功能查询 s3 的数据。 + +上传成功后可以使用命令查看 Schema 信息。 + + ```sql + // 查看schema + DESC FUNCTION s3 ( + "URI" = "https://bucketname/1kw.tsv", + "s3.access_key"= "ak", + "s3.secret_key" = "sk", + "format" = "csv", + "use_path_style"="true" + ); + ``` + +**测试不限制远程读的 IO** +1. 发起单并发测试,全表扫描 clickbench 表。 + + ```sql + // 设置只 scan 数据,不返回结果 + set dry_run_query = true; + + // 使用 tvf 查询 s3 的数据 + SELECT * FROM s3( + "URI" = "https://bucketname/1kw.tsv", + "s3.access_key"= "ak", + "s3.secret_key" = "sk", + "format" = "csv", + "use_path_style"="true" + ); + ``` + +2. 使用系统表查看此时的远程 IO 吞吐。可以看到这个查询的远程 IO 吞吐为 837M 每秒,需要注意的是,这里的实际 IO 吞吐受环境影响较大,如果 BE 所在的机器连接外部存储的带宽比较低,那么可能实际的吞吐会小。 + + ```sql + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 837 | + +---------+ + 1 row in set (0.104 sec) + + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 867 | + +---------+ + 1 row in set (0.070 sec) + + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 867 | + +---------+ + 1 row in set (0.186 sec) + ``` + +3. 使用 sar(sar -n DEV 1 3600) 命令查看机器的网络带宽,可以看到机器级别最大网络带宽为 1033M 每秒。 + 输出的第一列为当前机器某个网卡每秒接收的字节数,单位为 KB 每秒。 + +  + +**测试限制远程读的 IO** +1. 修改 Workload Group 的配置,限制远程读的 IO 吞吐为 100M 每秒。 + + ```sql + alter workload group normal properties('remote_read_bytes_per_second'='104857600'); + ``` + +2. 发起单并发扫全表的查询。 + + ```sql + // 设置只 scan 数据,不返回结果 + set dry_run_query = true; + + // 使用 tvf 查询 s3 的数据 + SELECT * FROM s3( + "URI" = "https://bucketname/1kw.tsv", + "s3.access_key"= "ak", + "s3.secret_key" = "sk", + "format" = "csv", + "use_path_style"="true" + ); + ``` + +3. 使用系统表查看此时的远程读 IO 吞吐,此时的 IO 吞吐在 100M 左右,会有一定的波动,这个波动是受目前算法设计的影响,通常会有一个高峰,但不会持续很长时间,属于正常情况。 + + ```sql + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 56 | + +---------+ + 1 row in set (0.010 sec) + + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 131 | + +---------+ + 1 row in set (0.009 sec) + + MySQL [(none)]> select cast(REMOTE_SCAN_BYTES_PER_SECOND/1024/1024 as int) as read_mb from information_schema.workload_group_resource_usage; + +---------+ + | read_mb | + +---------+ + | 111 | + +---------+ + 1 row in set (0.009 sec) + ``` -1. 在 Kubernetes 中使用 Workload 管控资源。Workload 的 CPU 管理是基于 CGroup 实现的,如果期望在容器中使用 Workload Group,那么需要以特权模式启动容器,容器内的 Doris 进程才能具备读写宿主机 CGroup 文件的权限。当 Doris 在容器内运行时,Workload Group 的 CPU 资源用量是在容器可用资源的情况下再划分的,例如宿主机整机是 64 核,容器被分配了 8 个核的资源,Workload Group 配置的 CPU 硬限为 50%,那么 Workload Group 实际可用核数为 4 个(8 核 * 50%)。 +4. 使用 sar 命令(sar -n DEV 1 3600)查看目前的网卡接收流量,第一列为每秒接收的数据量,可以看到最大值变成了 207M 每秒,说明读 IO 的限制是生效的,但是由于 sar 命令看到的是机器级别的流量,因此要比 Doris 统计到的会大一些。 -2. WorkloadGroup 的内存管理和 IO 管理功能是 Doris 内部实现,不依赖外部组件,因此在容器和物理机上部署使用并没有区别。如果要在 K8S 上使用 Doris,建议使用 Doris Operator 进行部署,可以屏蔽底层的权限细节问题。 \ No newline at end of file +  \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org