【腾讯云 TDSQL-C Serverless 产品测评】深度实测TDSQL-C Serverless 弹性伸缩策略及稳定性

文章目录

    • 前言
    • 一、什么是 TDSQL-C Serverless
    • 二、TDSQL-C Serverless 的弹性伸缩方案
    • 三、弹性伸缩策略及稳定性实测
      • 1.测试设计
      • 2.测试流程:
      • 3.测试准备工作
      • 4.开始测试
      • 5.测试结果分析
        • 5.1.整体过程分析
        • 5.2.扩容过程分析
        • 5.3.缩容过程分析
    • 四、总结

前言

Serverless 数据库作为近几年云原生数据库领域的重要发展方向,自 2018 年 AWS 率先推出 Aurora Serverless MySQL 服务,打响 Serverless 数据库之战的第一枪以来,各大云平台厂商一直在该领域不断深耕探索。9 月 7 日,在 2023 腾讯全球数字生态大会云原生数据库技术演进与实践专场上,腾讯云数据库团队重磅发布了云原生数据库 TDSQL- C Serverless 2.0 版本。在这场分享中,腾讯云数据库产品经理陈昊老师介绍了腾讯云 TDSQL-C Serverless 独有的弹性伸缩方案,本文就以此为引,深度探索一下 TDSQL-C Serverless 的纵向弹性伸缩策略及稳定性

一、什么是 TDSQL-C Serverless

TDSQL-C Serverless 服务是腾讯云自研的新一代云原生关系型数据库 TDSQL-C MySQL 版的无服务器架构版,是全 Serverless 架构的云原生数据库。架构图如下:

TDSQL-C Serverless 架构介绍截图

TDSQL-C Serverless 的三大核心特性:

  • 算存分离,资源池化
    • 计算存储分离,根据负载独立弹性,不受单机瓶颈限制,根据业务发展平滑拓展集群
    • 多个计算节点共享存储,存储层容量在线平滑拓展,可承载 PB 级数据规模
    • 冷数据可落冷到 COS 存储中,进一步压缩存储成本,做到不使用不付费
  • 极致弹性,自动扩缩容
    • CPU、内存、存储三层解耦,数十种监控指标触发弹性,根据实际负载情况进行三层独立弹性,将资源利用率发挥到极致
    • 多种弹性方式融合,针对不同场景的业务形态,融合共享资源与独立资源的优势,保证资源利用率
    • 结合时序算法等预测式弹性,提前触发扩缩容
  • 全面 Serverless 化,充分调度
    • 支持集群全面 Serverless 化,将资源更细粒度进行拆解,快速添加 RO 节点,每个实例可进行独立弹性,贴合业务使用情况
    • 支持 Serverless 节点混部,供业务侧灵活搭配 Serverless 能力,丰富数据库使用场景
    • 自动读写分离,屏蔽后端扩缩容动作,用户只需关注业务层
    • 依赖调度器全方面分析资源使用情况,多种算法加持保证弹性伸缩的准确性

二、TDSQL-C Serverless 的弹性伸缩方案

数字生态大会PPT截图

关于 Serverless 数据库的纵向弹性方案,业内通用的方案如上图左侧所示,低负载时分配较低规格的计算资源,当负载压力触发阈值后,再扩容更多的计算资源。这种方案的弊端是,对计算资源的调整速度有很高的要求,计算资源调整速度不及时且数据库负载压力极大的情况下可能会触发实例 OOM,如果多个实例同时面临负载高峰时,还可能会发生资源抢占的问题。这可能也是 Serverless 数据库在早期只能用于开发环境或测试环境的原因之一。

TDSQL-C Serverless 的弹性伸缩方案与这种“抠抠搜搜”的释放计算资源的方案不同,TDSQL-C Serverless 会根据用户配置的最大 CCU(1CCU ≈ 1C2G)在一开始就将 CPU、内存资源限制到最大规格,极大程度降低因 CPU 和内存扩容带来的时间影响和使用限制,之后通过监控计算层的负载情况,当集群触发到自动弹性的负载阈值后,Buffer Pool 会根据监控进行秒级扩容,准秒级缩容。在这个方案下用户使用数据库可以无感知进行计算资源扩容,并且不会因为连接突增导致实例 OOM 和资源抢占的问题。

相比于计算资源的动态调整,调整 Buffer Pool 的大小更为轻量便捷,调整速度也会更快。总结来说,前者的方案更像是传统人工扩缩容的云端自动化实现,后者则是从业务角度出发,去做了更多的思考和优化来提供更好的使用体验。

三、弹性伸缩策略及稳定性实测

TDSQL-C Serverless 控制台和数据库智能管家 DBbrain 给出的监控信息最小粒度只有 5 秒,无法做到秒级的指标监控,因此这里参考了周振兴老师(《高性能 MySQL》第三、四版的译者)针对 Aurora Serverless v2 的测试方法,选择响应时间作为稳定性指标,同时观测innodb_buffer_pool_size的秒级变化判断伸缩节点,并结合 TDSQL-C Serverless 的特性对测试时长等进行了部分调整。最终的测试方案如下:

1.测试设计

  • 使用 Sysbench 作为测试程序,场景选用 oltp_read_write,将 --report-interval 设置成 1s,将 --percentile 设置为 99 作为平均延迟(响应时间 rt)
  • 同时使用 SHOW VARIABLES LIKE "innodb_buffer_pool_size" 命令持续观测 Buffer Pool Size,以该数值的大小变化作为资源调整变化的指标

2.测试流程:

  • 首先,启动一个单线程 Sysbench,作为测试 “主进程”,程序运行 1200 秒
  • “主进程” 运行 300 秒后,再启动一个 “压力进程”(24 并发的 Sysbench 进程)向数据库施压,该进程运行 300 秒后退出
  • 将 Sysbench 每秒返回的报告信息和与之对应的 Buffer Pool Size 数据存入 csv,之后读取 csv 数据使用 Echarts 生成散点图以供分析

3.测试准备工作

  • TDSQL-C Serverless 规格:MySQL5.7 引擎,单节点(只有一个读写实例),最小 CCU0.5,最大 CCU32

    在这里插入图片描述

  • 客户端规格:腾讯云轻量应用服务器,配置为 4C8G

  • 网络环境:通过云联网功能实现轻量应用服务器到 TDSQL-C Serverless 的内网互联

  • 准备测试数据

    • 使用 TDSQL-C Serverless 控制台的 数据库管理 功能创建测试库 test_scaling
      在这里插入图片描述
    • 使用 Sysbench 生成测试数据
      sysbench --db-driver=mysql --mysql-host=172.21.0.15 --mysql-port=3306 \
      --mysql-user=root --mysql-password=xxxx \
      --mysql-db=test_scaling --table_size=100000 --tables=1 --threads=1 \
      oltp_read_write prepare
      
      在这里插入图片描述

4.开始测试

  • 编写 Python 脚本实现测试流程

    # -*- coding: utf-8 -*-
    import subprocess
    import re
    import time
    import csv
    import threading
    import mysql.connector
    from mysql.connector import pooling# 配置数据库连接参数
    db_config = {"host": "172.21.0.15","port": 3306,"user": "root","password": "xxxxxx","database": "test_scaling",
    }# 创建数据库连接池
    pool = pooling.MySQLConnectionPool(pool_name="my_pool",pool_size=5,**db_config
    )# 函数:连接数据库并查询innodb_buffer_pool_size
    def query_innodb_buffer_pool_size():with pool.get_connection() as connection:cursor = connection.cursor()cursor.execute('SHOW VARIABLES LIKE "innodb_buffer_pool_size"')result = cursor.fetchone()return int(result[1])# 函数:运行sysbench命令并解析输出
    def run_sysbench(command_type, command):print('command_type: ' + command_type + ', command: ' + command)result_list = [];process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT, text=True)for line in iter(process.stdout.readline, ''):print(line, end='')# 连接数据库查询innodb_buffer_pool_sizeinnodb_buffer_pool_size = query_innodb_buffer_pool_size()# 获取当前时间并格式化为时分秒time_now = time.strftime("%H:%M:%S", time.localtime())# 输出示例:# [ 1s ] thds: 16 tps: 850.05 qps: 17191.55 (r/w/o: 12053.34/3422.15/1716.06) lat (ms,99%): 27.17 err/s: 0.00 reconn/s: 0.00# 解析输出结果,获取lat (ms,99%):if line.startswith('[ '):times = re.search(r'\[ (\d+)s \]', line).group(1)latency = re.search('lat \(ms,99%\): (\d+\.\d+)', line).group(1)result_list.append([time_now, times, command_type, innodb_buffer_pool_size, latency])process.wait()return result_list# 函数:运行Sysbench测试
    def run_sysbench_thread(command_type, command, result_list):result_list.extend(run_sysbench(command_type, command))if __name__ == '__main__':# main:1 sub:24sysbench_command_main = 'sysbench --db-driver=mysql --mysql-host=' + db_config['host'] + ' --mysql-port=' + str(db_config['port']) + ' --mysql-user=' + db_config['user'] + ' --mysql-password=' + db_config['password'] + ' --mysql-db=' + db_config['database'] + ' --table-size=100000 --tables=1 --threads=1 --time=1200 --percentile=99 --report-interval=1 oltp_read_write run'sysbench_command_sub = 'sysbench --db-driver=mysql --mysql-host=' + db_config['host'] + ' --mysql-port=' + str(db_config['port']) + ' --mysql-user=' + db_config['user'] + ' --mysql-password=' + db_config['password'] + ' --mysql-db=' + db_config['database'] + ' --table-size=100000 --tables=1 --threads=24 --time=300 --percentile=99 --report-interval=1 oltp_read_write run'result_list_main = []result_list_sub = []# 创建两个线程分别运行主测试和子测试main_thread = threading.Thread(target=run_sysbench_thread, args=('main', sysbench_command_main, result_list_main))sub_thread = threading.Thread(target=run_sysbench_thread, args=('sub', sysbench_command_sub, result_list_sub))# 启动主线程main_thread.start()# 创建定时器,等待300秒后启动子线程sub_thread_timer = threading.Timer(300, sub_thread.start)sub_thread_timer.start()# 等待线程完成main_thread.join()sub_thread.join()# 合并结果result_list_main.extend(result_list_sub)print(result_list_main)# 指定要写入的CSV文件的文件名csv_file_name = 'test_scaling.csv'# 打开CSV文件并将数据写入with open(csv_file_name, mode='w', newline='') as file:writer = csv.writer(file)writer.writerow(['time_now', 'times', 'command_type','innodb_buffer_pool_size', 'rt'])for data_row in result_list_main:writer.writerow(data_row)
    
  • 使用 Echarts 散点图分析结果数据

    <!DOCTYPE html>
    <html><head><meta charset="utf-8"><title>ECharts Scatter Plot from CSV</title><!-- 引入 ECharts 文件 --><script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"></script>
    </head><body><!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --><div id="scatter-plot" style="width: 100vw; height: 80vh;"></div><script>// 初始化ECharts实例var myChart = echarts.init(document.getElementById('scatter-plot'), { pixelRatio: 2 });// 异步加载CSV文件fetch('test_scaling.csv').then(function (response) {return response.text();}).then(function (csvData) {// 解析CSV数据var lines = csvData.split('\n');var data = [];for (var i = 1; i < lines.length; i++) {var values = lines[i].split(',');data.push({time_now: values[0],times: values[1],command_type: values[2],innodb_buffer_pool_size: parseFloat(values[3]),rt: parseFloat(values[4])});}// 创建ECharts选项,其中左侧纵坐标显示rt(毫秒),右侧纵坐标显示Buffer Pool Size(MB)。// 其中,红点代表 "主进程" 响应时间(rt),灰点代表 "压力进程" 响应时间(rt),蓝色点代表Buffer Pool Size。// 时间以秒为单位显示在横坐标上,时间间隔为1秒。var option = {backgroundColor: '#FFFFFF',grid: {left: 50,right: 50,bottom: 60,top: 30,containLabel: true},tooltip: {trigger: 'axis',axisPointer: {type: 'cross'}},legend: {data: ['主进程响应时间(RT)', '压力进程响应时间(RT)', 'Buffer Pool Size']},// dataZoom: [{//     type: 'slider',//     start: 20,//     end: 50,// }, {//     type: 'inside',//     start: 20,//     end: 50,// }],toolbox: {show: true,feature: {saveAsImage: {show: true,pixelRatio: 2,name: "TDSQL-C_Test_Scaling"}}},xAxis: {type: 'value',name: 'Time',nameLocation: 'middle',nameGap: 25,interval: 30,minInterval: 1,splitLine: {show: false},axisLabel: {formatter: function (value) {value = parseInt(value.toFixed(0));return value;}}},yAxis: [{type: 'value',name: 'RT(ms)',nameLocation: 'middle',nameGap: 30,splitLine: {show: false}}, {type: 'value',name: 'Buffer Pool Size (MB)',nameLocation: 'middle',nameGap: 50,splitLine: {show: false}}],series: [{name: '主进程响应时间(RT)',type: 'scatter',symbolSize: 4,data: data.filter(function (item) {return item.command_type === 'main';}).map(function (item) {return [item.times, item.rt];}),itemStyle: {color: 'red'},markLine: {silent: true,symbol: "none",label: {show: true,position: 'insideMiddle',formatter: '{b}'},data: [{name: '压力进程开始',xAxis: 301}, {name: '压力进程结束',xAxis: 600}]}}, {name: '压力进程响应时间(RT)',type: 'scatter',symbolSize: 4,data: data.filter(function (item) {return item.command_type === 'sub';}).map(function (item) {// time加上秒数return [Number(item.times) + 300, item.rt];}),itemStyle: {color: 'gray'}}, {name: 'Buffer Pool Size',type: 'scatter',symbolSize: 2,yAxisIndex: 1,data: data.map(function (item) {return [item.command_type === 'sub' ? Number(item.times) + 300 : item.times,item.innodb_buffer_pool_size / 1024 / 1024]; // Convert to MB}),itemStyle: {color: 'blue'}}]};myChart.setOption(option);});</script>
    </body></html>
    
  • 执行脚本

    python3 test_tdsqlc_scaling.py | tee test_tdsqlc_scaling.log
    

5.测试结果分析

Tips:下文中的图片如果查看效果不佳,可点击鼠标右键,选择在新标签页中打开图片

5.1.整体过程分析

TDSQL-C_Test_Scaling_All
散点图说明:

  • 红点代表 ”主进程” 响应时间(rt)随时间(秒)变化趋势
  • 灰点代表 ”压力进程” 响应时间(rt)随时间(秒)变化趋势
  • 蓝点(连成线)代表 Buffer Pool Size 随时间(秒)变化趋势
  • 横坐标是时间,间隔为 1 秒
  • 左侧纵坐标单位为毫秒,是 rt 的单位;右侧纵坐标单位是 MB,是 Buffer Pool Size 单位

整个测试过程中,主进程响应时间(rt)、压力进程响应时间(rt)和 Buffer Pool Size 变化过程如下:

  • 0 秒—300 秒,主线程响应时间维持在 5ms 左右,Buffer Pool Size 为512M
  • 第 300 秒,压力进程开始运行,Buffer Pool 开始扩容,经过 5 次扩容之后稳定在 22912M(22.375G)
  • 300 秒—600 秒(压力进程运行期间),主进程响应时间由之前的 5ms 左右提升至 15ms 左右
  • 第 600 秒,压力进程退出,之后 Buffer Pool 经过了 5 次缩容,恢复至最小规格 512M
  • 600 秒之后,主进程响应时间回落至 5ms 左右
  • 整个测试过程中,Buffer Pool Size 按照固定规格呈阶梯性扩/缩容,规格阶梯:0.5G → 1G → 2.375G → 5.5G → 11.125G → 22.375G
5.2.扩容过程分析

TDSQL-C_Test_Scaling_UP

如上图所示,第 300 秒压力进程开始运行后,Buffer Pool 共经历 5 次扩容,每次扩容平均耗时 35 秒,这个耗时与数字生态大会上分享的 Buffer Pool 会根据监控进行秒级扩容,准秒级缩容 差异还是很大的,个人猜测 秒级扩容 应该只是指 Buffer Pool 扩容动作本身的耗时,而不包括这之前的监控采集、分析决策、指令下达等动作。

关于扩容期间的响应时间,测试前的预期变化是在压力进程开启后,响应时间上升到一个较高的值,之后随着 Buffer Pool 的扩容响应时间逐渐减低。但实测后发现,响应时间除了在最后 3 次完成扩容的那一秒有明显的增长(最大 63.32ms)外,其他时间响应时间都很稳定的维持在 15ms 上下。
从这里可以看出,TDSQL-C Serverless 的弹性伸缩方案优势很明显,充足的基础资源使得数据库在面临瞬间进入的流量洪峰时,不会出现过大的性能波动,再配合上合理的弹性伸缩策略,其最大程度的保证了业务高峰时的稳定性。

5.3.缩容过程分析

TDSQL-C_Test_Scaling_Down
TDSQL-C Serverless 的缩容过程同样是经历了 5 次 Buffer Pool 的调整,每一次的缩容规格都与扩容过程中的规格变化一致。与扩容过程不同的是,缩容的过程整体策略更保守,从监控采集到最后缩容成功的耗时更长。

从上图中可以看到,5 次缩容的耗时分别是 137 秒、93 秒、49 秒、53 秒、60 秒。这个时长相比于扩容耗时翻了至少一倍。之所以耗时这么久,应该是为了保证缩容过程中清除出内存池的数据页都是确确实实不再使用的,避免出现性能波动。观察缩容过程中的响应时间变化也可以证明这一点,从第 600 秒压力进程退出后,响应时间就回落至一开始的 5ms 上下,整个过程中未出现明显的异常点。

四、总结

经过上述的实测可以发现,归功于其独有的弹性伸缩方案、合理的弹性策略、以及底层内核的针对性优化,TDSQL-C Serverless 完美的实现了业务无感的平滑扩缩容。无论是 性能,还是 稳定性,都已经直逼传统数据库。

在 Serverless 数据库扩缩容性能波动问题的解决方案上,TDSQL-C Serverless 交上了一份几乎完美的答卷,这份答卷意味着 Serverless 数据库已经不再是以前那个只能用于开发测试环境的玩具。同时,TDSQL-C Serverless 2.0 版本还实现了全球首个可释放存储架构的 Serverless 服务:集群无访问时段数据可落冷归档,启动时可瞬时恢复服务,无需等待数据全量恢复,该版本还提供了集群版 Serverless,支持只读节点和 Proxy 弹性能力。随着这些能力的发布升级,极大的丰富了 Serverless 当前的应用场景,使 TDSQL-C Serverless 得以全面承载核心业务场景。

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

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

相关文章

小白也能看得懂的Jmeter性能测试中服务端资源监控技术

操作步骤&#xff1a; 1、安装插件管理器 插件管理器的作用&#xff1a;可以提供扩展插件的在线安装升级和卸载。因为我们需要在线安装监控插件&#xff0c;首先我们就要先安装插件管理器。 插件管理器的下载地址&#xff1a;https://jmeter-plugins.org/install/Install/ 如…

关于鸿蒙网络请求的问题

https://developer.huawei.com/consumer/cn/forum/topic/0204136145853212268?fid0102683795438680754 鸿蒙OS 代码 import http from ohos.net.http;export const httpUtils (url: string, data: any) > {return new Promise((resolve, reject) > {let httpRequest …

【黑马甄选离线数仓day05_核销主题域开发】

1. 指标分类 ​ 通过沟通调研&#xff0c;把需求进行分析、抽象和总结&#xff0c;整理成指标列表。指标有原子指标、派生指标、 衍生指标三种类型。 ​ 原子指标基于某一业务过程的度量值&#xff0c;是业务定义中不可再拆解的指标&#xff0c;原子指标的核心功能就是对指标…

03:2440--UART

目录 一:UART 1:概念 2:工作模式 3:逻辑电平 4:串口结构图 5:时间的计算 二:寄存器 1:简单的UART传输数据 A:GPHCON--配置引脚 B:GPHUP----使能内部上拉​编辑 C: UCON0---设置频率115200 D: ULCON0----数据格式8n1 E:发送数据 A:UTRSTAT0 B:UTXHO--发送数据输…

VCenter连接主机提示:未验证主机SSL证书的真实性

问题&#xff1a;VCenter主机断开连接了&#xff0c;重新连接主机报错SSL证书问题 移除重新加入ESXI6.0节点报错常规系统错误&#xff08;如下图&#xff09; 解决方案&#xff1a;需更改一下验证方式 VCenter Serevr设置→高级设置 将项cpxd.certmgmt.mode 值 vmca 改为&…

linux嵌入式时区问题

目录 操作说明实验参考 最近有个针对时区的需求&#xff0c;研究了下。 查询网上的一些设置&#xff0c;发现基本都是系统中自带的一些文件&#xff0c;然后开机时解析&#xff0c;或者是有个修改的命令。 操作 但针对嵌入式常用到的 busybox 制作的最小系统&#xff0c;并没…

N-134基于java实现捕鱼达人游戏

开发工具eclipse,jdk1.8 文档截图&#xff1a; package com.qd.fish;import java.awt.Graphics; import java.io.File; import java.util.ArrayList; import java.util.List;import javax.imageio.ImageIO;public class Fishes {//定义一个集合来管理鱼List<Fish> fish…

76. 最小覆盖子串 (滑动窗口)

Problem: 76. 最小覆盖子串 文章目录 思路相似滑动窗口题目 :Code 题目 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 注意&#xff1a; 对于 t 中重复字符&#xff0c;我…

[黑马程序员SpringBoot2]——原理篇1

目录&#xff1a; bean的加载方式(—)bean的加载方式(二)bean的加载方式(三)FactoryBeanproxyBeanMethod属性bean的加载方式(四)bean的加载方式(五)bean的加载方式(六)bean的加载方式(七)bean的加载方式(八)bean加载控制&#xff08;编程式)bean加载控制&#xff08;注解式)be…

基于sklearn实现LDA主题模型(附实战案例)

目录 LDA主题模型 1.LDA主题模型原理 2.LDA主题模型推演过程 3.sklearn实现LDA主题模型&#xff08;实战&#xff09; 3.1数据集介绍 3.2导入数据 3.3分词处理 3.4文本向量化 3.5构建LDA模型 3.6LDA模型可视化 3.7困惑度 LDA主题模型 1.LDA主题模型原理 其实说到LDA…

SpringMVC系列-7 @CrossOrigin注解与跨域问题

背景 前段时间帮同事分析了一个跨域问题&#xff0c;正好系统分析和整理一下。 1.跨域 理解同源策略是理解跨域的前提。同源策略定义如下&#xff1a; 在同一来源的页面和脚本之间进行数据交互时&#xff0c;浏览器会默认允许操作&#xff0c;而不会造成跨站脚本攻击&#x…

蓝桥杯每日一题2023.11.25

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 对于此题目最开始是递归想法&#xff0c;但发现题意中的匹配次数实际上是指在这8个字母中这8个字母每个字母对应的个数是否相同&#xff0c;如果相同则匹配。 此处我们可以使用subsrtr函数&#xff0c;每次循环截取8个字…