前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【腾讯云TDSQL-C Serverless 产品测评】一场ServerLess方案和Native方案的小PK!

【腾讯云TDSQL-C Serverless 产品测评】一场ServerLess方案和Native方案的小PK!

原创
作者头像
67101342
修改2023-11-15 10:31:19
2650
修改2023-11-15 10:31:19
举报
文章被收录于专栏:烂笔头和随想录

一、背景介绍

1.1 TDSQL-C ServerLess

在开始测评之前,先来认识下今天的主角吧——TDSQL-C ServerLess

关于该产品的说明,官方站点有非常详细且生动的介绍。

其实,某种程度上,我们就可以把这个产品理解成MySQL Plus或PostgreSQL Plus,也就是不用在关心,安装,性能,扩缩容,自动备份等复杂的配置性操作,这些将全部由腾讯云自动完成,我们只需要关注和业务的对接,就像办理手机套餐,只需月初月末关注下资费,真正做到即开即用。

更多介绍:👉https://cloud.tencent.com/product/cynosdb

截止到发文(2023.8.29,serverless形态的TDSQL-C只有MySQL版是可用的,PostgreSQL的产品架构正在升级,笔者其实对PostgreSQL相对更熟悉一点,这次没体验到PostgreSQL的版本有点小遗憾,后续可能还会有更多版本的数据库支持)

1.2 测评思路

根据活动的测评要求,我这里主要的测评目标是兼容性并发可靠性3个方面。

测评形式就是在本地跑通一个简单的项目,然后不修改任何代码,直接切换到TDSQL-C ServerLess产品,并分别进行一场压力测试,看看结果如何。

*注意:此次测评不涉及部分量化的性能指标,因为内网环境VS云端环境,有一个绕不开的变量,就是网络,在这方面内网肯定是碾压云端的,而此次测评的环境是在我本地的内网环境,不在腾讯云的服务器上,那通过外网链接到TDSQL-C Serverless数据库时,网络延时是避不开的,所以,我这次重点只关注刚提到的兼容性,并发和可靠性3方面。

1.3 开通服务

在开始之前,再简单介绍一下开通服务的流程,虽然本次活动主办方为开发者提供了免费账号👇

但了解过计费规则之后,我觉得,使用ServerLess形态的产品,按量计费完成这次测评顶天也就十来块钱不到的成本,所以决定真正的开一个服务来测试!

开通基本流程如下

  • 进入TDSQL产品页👉https://cloud.tencent.com/product/tdsqlc,点【立即选购】
  • 形态选Serverless,引擎目前支持MySQL和PGSQL,其他按需填写,自动暂停选项勾上(省钱省心省力),计费模式我就直接选的按量计费
  • 填写集群的基础信息和配置,点【立即购买】即可

整体的流程其实也没啥可说,按页面提示一步步操作即可,我这边截了两个图👇!

开通之后,到控制台界面,可以看到我们自己开通的数据库集群,需要注意的是,为了方便后面的使用,我们可能需要创建一个非root账号,创建流程就是点击下面👇,这个界面的【账号管理】,根据页面提示创建即可,非常简单,不再赘述。

配置好后,可以用本地的客GUI工具连接一下看下效果👇

好了,到此,云数据库就准备好了,接下来可以进入下一环节~

二、PK方案

我这里的测评PK方案是这样👇

  • 先使用内网环境的数据库,跑通一个简单的业务
  • 分表
  • 编写一些简单的涵盖修改,查询数据库的操作,直接面向数据库,不经过任何中间件
  • 跑一下性能测试
  • 不修改任何代码,直接切换到TDSQL-C ServeLess地址,再跑一下性能测试

本地数据库使用的MySQL 8.0.34,因为用Mysql比较少,不太熟,稍微花了点时间安装,如果只是常规开发的话,还是直接用docker更方便一些。

通过测评,可以得出迁移到TDSQL的平滑程度也就是兼容性,并发能力和稳定性的相关数据,为我们实际的业务上云提供客观的数据支撑。

三、搭擂台

在测评之前,咱先来准备个简单的项目,为了尽可能把变量控制在数据库层面,我这里采用统一的项目框架(.net 6),统一的ORM(EFCore 7.0),分表中间件采用ShardingCore,建立2个数据模型,并通过显示声明外键的方式建立一对多关联(避免分表查询时产生笛卡尔积而造成连接数爆炸)。

除此之外,不再额外引用任何和数据读写相关的中间件,直接把请求打到数据库层,看看效果如何。

本篇会贴上一些关键的代码,并不完整,只为让此次测评过程更加的清晰,完整地址在这里:https://e.coding.net/tony_df/TestWeb/TestWeb.git

3.1 创建项目

通过命令行,或者使用VS集成开发工具,创建一个测试项目,项目形态可以是web,控制台,或是.net框架支持的任何终端形态(现在的.net已经是全平台框架了哟~)

我这里选择的是web项目,下图是准备好的项目结构。

3.2 配置项目

用熟悉的方式,引入此次需要的一些包文件,我这里主要用到了Pomelo.EntityFrameworkCore.MySql,ShardingCore。

全部的包引用配置如下👇

代码语言:html
复制
<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.21" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
  <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
  <PackageReference Include="ShardingCore" Version="7.7.1.13" />
  <PackageReference Include="Spectre.Console" Version="0.47.0" />
  <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

3.3 创建模型,配置分表规则

这里,我引入的模型关系是考试和试卷的关系,每场考试包含多张试卷,这里采用EFCore的CodeFirst模式来维护数据库模型,其中对试卷表(Paper)进行分表操作。

3.3.1 创建模型

代码语言:c#
复制
public class Examination
{
    //主键,采用Yitid插件提供的数字生成器ID
	public string Id { get; set; }=YitIdHelper.NextId().ToString();
    
    public List<Paper> Papers { get; set; } = new List<Paper> { };
	
    //其他属性,节约篇幅这里就不一一列举了
    ...
}
代码语言:c#
复制
public class Paper
{
    //主键,采用Yitid插件提供的数字生成器ID
	public string Id { get; set; }=YitIdHelper.NextId().ToString();
	
    public Examination Examination { get; set; }
	
    //显示声明考试id外键 
	public string ExaminationId { get; set; } = "";
    
    //其他属性,节约篇幅这里就不一一列举了
    ...
}

3.3.2 FluentAPI定义模型属性

配置完成后,使用EFCore提供的FluentAPI,设定其模型关系

代码语言:c#
复制
public class ExaminationEntityConfig:IEntityTypeConfiguration<Examination>
{
    public void Configure(EntityTypeBuilder<Examination> builder)
    {
        builder.ToTable(nameof(Examination));
        builder.HasKey(x => x.Id);
        //...
    }
}

public class PaperEntityConfig : IEntityTypeConfiguration<Paper>
{
    public void Configure(EntityTypeBuilder<Paper> builder)
    {
        builder.ToTable(nameof(Paper));
        builder.HasKey(p => p.Id);
        //设定1对多关联关系,并声明外键Id
        builder.HasOne<Examination>(e => e.Examination).WithMany(p => p.Papers).IsRequired().HasForeignKey(p => p.ExaminationId);
    	//...
    }
}

3.3.3 创建数据库上下文,引入ShardingCore扩展

创建一个类文件,继承AbstractShardingDbContext,如果不分库也不分表的话,继承DbContext就可以了,而ShardingCore实际上是DbContext的扩展,所以我们直接继承该扩展即可。

因为涉及到分表,所以还需要IShardingTableDbContext接口。

代码语言:c#
复制
public class MyDbContext:AbstractShardingDbContext,IShardingTableDbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) 
    { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
    }

    /// <summary>
    /// 分表路由的尾部命名规则,默认是{表名}_{从大到小的索引}
    /// </summary>
    public IRouteTail RouteTail { get; set; }
}

到这里,如果我们不使用分表,就可以去注入服务,执行迁移来生成库表了,但因为我们想把测评的维度拉高一点,所以还要再多一些步骤。

3.3.4 配置分表路由

这里,对paper进行分表操作,通过对主键取模的规则来分表,更多关于分表的信息,大家可以参照ShardingCore的官方文档,这里由于篇幅有限,不过多介绍了~

代码语言:c#
复制
 /// <summary>
 /// 创建虚拟路由
 /// 该路由为简单的取模hash路由,分表字段是string类型,接受3个参数,第一个参数表示后缀的位数,第二位表示取模的基数,第三位是取模后缀不足的左补字符.
 /// </summary>
 public class PaperVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<Paper>
 {
     public PaperVirtualTableRoute() : base(2, 3)
     {
     }

     public override void Configure(EntityMetadataTableBuilder<Paper> builder)
     {
         builder.ShardingProperty(o => o.Id);
         builder.AutoCreateTable(null);
         builder.TableSeparator("_");
     }
 }

3.3.5 注入服务,启动项目

因为是测试项目,我们采用默认方式注入服务(实际上,生产项目应该考虑集成AutoFac来完成容器注入)

我这里使用了.net 6 的顶级语句,没有之前常见的Startup.cs文件,为了保证入口文件的简洁,这里把配置服务也分到了一个单独的文件中,

主要代码如下

代码语言:c#
复制
public static WebApplicationBuilder SetupServices(this WebApplicationBuilder builder)
{
     _configuration = builder.Configuration;
     builder.Services.ConfigureMvc();
     //..其他服务
     return builder;
}
private static void ConfigureSharding(this IServiceCollection services)
{            
    //添加分片配置
    services.AddShardingDbContext<MyDbContext>()
        .UseRouteConfig(op =>
        {
            op.AddShardingTableRoute<PaperVirtualTableRoute>();
        }).UseConfig((sp, op) =>
        {
            var serverVersion = new MySqlServerVersion(new Version(8, 0));
            op.UseShardingQuery((conn, builder) =>
            {
                builder.UseMySql(conn, serverVersion);
            });
            op.UseShardingTransaction((conn, builder) =>
            {
                builder.UseMySql(conn,serverVersion);
            });
            op.AddDefaultDataSource(Guid.NewGuid().ToString("n"),_configuration.GetConnectionString("DefaultConnection")
               );
        }).AddShardingCore();
}

以上配置完成后,就可以执行迁移,启动项目啦

四、擂台赛开始

4.1 Warm-up

正式测评之前,先来一个热身赛,项目准备好以后,我想先准备一些种子数据,虽然都是随机的,但我这里准备的多一点,10,000条考试记录搞里头,每个考试下再配10条试卷记录,共100,000条试卷记录,总共11万条记录,然后分别写入到本地库和ServerLess库,看看写入这批种子数据的效率如何

  • 这是本地的执行截图👇
  • 这是切换到TDSQL后的执行截图👇

这里实际已经可以印证TDSQL的兼容性了,我只是改了下连接串,然后分别启动了一下项目,10万+条记录,就这样平滑的插入了。

这里TDSQL的用时之所以比本地长是意料之中的,并不是它性能不行,而是网络因素影响,毕竟云端再快,也跑不过本地内网链接,所以这个执行时间具体的值参考价值不大,重要的是稳定。当然如果我把环境架到腾讯云的服务器,然后通过serverless提供的内网ip来测试,那情况就有不一样了,这里因为成本因素,我的测试程序还是在我本地的内网环境下运行。 除此之外,云服务的最大CCU我只开到了2,按官方的介绍,相当于2核4G内存,所以硬件配置也确实比不上本地内网服务器的配置,在此情况下,我分别执行了几次,所用时长几乎没有波动。 稳定性兼容性可见一斑。

4.2 压力测试

4.2.1 测试接口

压测之前,我分别准备了三个接口,分别用于模拟实际的简单检索,复杂检索和入库操作

代码语言:c#
复制
[Route("[controller]/[action]")]
public class TestController : Controller
{
    private readonly ILogger<TestController> _logger;
    private readonly MyDbContext _ctx;
    public TestController(ILogger<TestController> logger, MyDbContext ctx)
    {
        _logger = logger;
        _ctx = ctx;
    }

    public async Task<IActionResult> QuerySimple() 
    {
       //模拟简单查询
        //代码略
    }

    public async Task<IActionResult> QueryComplex()
    {
        //模拟复杂查询
        //代码略
    }

    public async Task<IActionResult> Insert()
    {
        //模拟插入
        //代码略
    }    
}

这部分具体的业务代码不在贴了,后续提供完整地址,主要就模拟2种不同程度的读操作和1种写操作

4.2.2 部署测试环境

这里我是把测试系统分别部署到了内网的两台服务器上,然后通过nginx做了一个负载均衡,如下图👇

如此,测试环境就准备好了

4.2.3 准备测试计划

测试计划如下,

  • 目标运行环境:Kestrel(Windows server)
  • 测试工具:JMeter 5.5
  • 负载:2台
  • UVs(线程数):200 * 2 (2台压力机,CentOS环境)
  • 压测时长:300s(5分钟)
  • 线程启动步长(ramp-up):20秒内全部线程启动

测试资源有限,暂时把压测参数定在这个范围

关键jmx配置信息如下👇

代码语言:html
复制
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="tdsql-c测评" enabled="true">
  <stringProp name="ThreadGroup.num_threads">500</stringProp>
  <stringProp name="ThreadGroup.ramp_time">20</stringProp>
  <boolProp name="ThreadGroup.scheduler">true</boolProp>
  <stringProp name="ThreadGroup.duration">600</stringProp>
</ThreadGroup>

4.4.4 开整!

第一组:将数据库设定为本地的内网环境,测试结果如下

第二组:将数据库设定为TDSQL-C Serverless,测试结果如下

*注意,将连接串切换到云数据库时要在控制台修改最大连接数,我刚开始就时没有改,压测刚开始没多久就拉了,一看默认的最大连接数是80

通过压测结果可以得出

  • 简单的单表查询和写入操作,本地库和云端库的并发能力相当,云端库弱一些,但差不了多少
  • 涉及到分表的查询时,TDSQL-C的优势就发挥出来了,压力测试场景下的平均响应时长反超了本地数据库(本地是1745ms,云端是571ms,差了3倍)!

注意:压测结果里出现的一些错误,是并不都是数据库造成的,还有框架的并发能力,服务器本身性能,网络等因素等,因为我是把请求直接打到了数据库,没有缓存层,所以测评的结果数据并不亮眼,这个就暂时不考虑了。 更多关于使用JMeter压力测试的知识大家可以参考其官方文档,笔者也曾写过一篇相关的博客,👉:https://blog.csdn.net/juanhuge/article/details/130830055

同时,可以看一下TDSQL的一些监控图表

QPS👇

TPS👇

CCU自动扩缩👇

最后再看一下,从开通,到完成这次测评,中间还折腾了好几次,一共花了多少钱

1.75元!

五、总结

通过整个的开发,部署,测试环节的对比情况,前面提到的对TDSQL的测评维度,基本可以得出以下结论

  • 稳定性
  • 兼容性
  • 并发能力

而且云数据库的控制台给出的各种监控图表非常丰富,可以帮助我们快速定位瓶颈所在,十分方便,如果服务器也在腾讯云,再搭配TDSQL-C一起使用,那性能应该会直接起飞。

好了,此次的测评就这样了.

最后的,一句话总结就是,TDSQL-C Serverless,可以闭眼入!

本篇同步发表于InfoQ:https://xie.infoq.cn/article/8fdd358dea4fbffadeaa4a15c

本篇同步发表于CSDN:https://blog.csdn.net/juanhuge/article/details/132563811

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景介绍
    • 1.1 TDSQL-C ServerLess
      • 1.2 测评思路
        • 1.3 开通服务
        • 二、PK方案
        • 三、搭擂台
          • 3.1 创建项目
            • 3.2 配置项目
              • 3.3 创建模型,配置分表规则
                • 3.3.1 创建模型
                • 3.3.2 FluentAPI定义模型属性
                • 3.3.3 创建数据库上下文,引入ShardingCore扩展
                • 3.3.4 配置分表路由
                • 3.3.5 注入服务,启动项目
            • 四、擂台赛开始
              • 4.1 Warm-up
                • 4.2 压力测试
                  • 4.2.1 测试接口
                    • 4.2.2 部署测试环境
                    • 4.2.3 准备测试计划
                    • 4.4.4 开整!
                • 五、总结
                相关产品与服务
                云原生数据库 TDSQL-C
                云原生数据库 TDSQL-C(Cloud Native Database TDSQL-C)简称 TDSQL-C。TDSQL-C 是腾讯云自研的新一代高性能高可用的企业级分布式云数据库。融合了传统数据库、云计算与新硬件技术的优势,100%兼容 MySQL 和 PostgreSQL,实现超百万级 QPS 的高吞吐,海量分布式智能存储,保障数据安全可靠。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档