分库分表下极致的优化

分库分表之历史表如何选择最佳分片路由规则 分库分表之历史表如何选择最佳分片路由规则 前言 背景 首先我相信很多人使用分表分库一定有这么一个情况,就是目前我们的系统有一张表可能会非常的庞大,然后希望通过分片技术将其进行水平拆分,但是如何拆分或者说如何拆分可以保证让目前的数据性能达到最优解,是一个很值得探讨的问题。 这边简单举一个例子,譬如我们的订单表,目前我们的订单表可能已经达到一定的数量级了比如百万或者千万级别了,可能光是简单的查询性能是很高的,但是新增订单可能就没这么乐观了,随着索引的增多新增的数目也会不断地变慢,不仅仅是查询一个维度迫使 阅读详情

题外话

这边说一句题外话,就是ShardingCore目前已经正式加入 NCC 开源组织了,也是希望框架和社区能发展的越来越好,希望为更多.netter提供解决方案和开源组件

介绍

依照惯例首先介绍本期主角:ShardingCore 一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵

dotnet下唯一一款全自动分表,多字段分表框架,拥有高性能,零依赖、零学习成本、零业务代码入侵,并且支持读写分离动态分表分库,同一种路由可以完全自定义的新星组件框架

你的star和点赞是我坚持下去的最大动力,一起为.net生态提供更好的解决方案

项目地址

  • github地址 https://github.com/dotnetcore/sharding-core

  • gitee地址 https://gitee.com/dotnetchina/sharding-core

本次优化点

直奔主题来讲下本次的极致优化具体是优化了什么,简单说就是CircuitBreaker和FastFail.

断路器CircuitBreaker

我们假设这么一个场景,现在我们有一个订单order表,订单会按照月份进行分片,那么订单表会有如下几个order_202201、order_202202、order_202203、order_202204、order_202205,假设我们有5张表。
首先我们来看一条普通的语句

select * from order where id='xxx' limit 1

这是一条普通的不能在普通的sql了,查询第一条id是xxx的订单,
那么他在分表下面会如何运行

//开启5个线程并发查询
select * from order_202201 where id='xxx' limit 1
select * from order_202202 where id='xxx' limit 1
select * from order_202203 where id='xxx' limit 1
select * from order_202204 where id='xxx' limit 1
select * from order_202205 where id='xxx' limit 1
//查询出来的结果在内存中进行聚合成一个list集合
//然后在对这个list集合进行第一条的获取
list.Where(o=>o is not null).FirstOrDefault()

这个操作我相信很多同学都是可以了解的,稍微熟悉点分表分库的同学应该都知道这是基本操作了,但是这个操作看似高效(时间上)但是在连接数上而言并不是那么的高效,因为同一时间需要开打的连接数将由5个

那么在这个背景下ShardingCore参考ShardingSphere 提供了更加友好的连接控制和内存聚合模式ConnectionMode

7473b4b9d9850bab45f815b52e8be7b2.png

这个张图上我们可以清晰的看到不同的数据库直接才用了一个并发限制,比如设置的是2,那么在相同库里面的查询将是每2个一组,进行查询,这样可以控制在同一个数据库下的连接数,进而解决了客户端连接模式下的连接数消耗猛烈的一个弊端。

//开启5个线程并发查询
{
  //并行
  select * from order_202201 where id='xxx' limit 1
  select * from order_202202 where id='xxx' limit 1
}
  //串行
{
  //并行
  select * from order_202203 where id='xxx' limit 1
  select * from order_202204 where id='xxx' limit 1
}
  //串行
{
  select * from order_202205 where id='xxx' limit 1
}
//查询出来的结果在内存中进行聚合成一个list集合
//然后在对这个list集合进行第一条的获取
list.Where(o=>o is not null).FirstOrDefault()

到目前为止这边已经对分片的查询优化到了一个新的高度。但是虽然我们优化了连接数的处理,但是就查询速度而言基本上是没有之前的那么快,可以说和你分组的组数成线性增加时间的消耗。
所以到此为止ShardingCore又再一次进化出了全新的翅膀CircuitBreaker断路器,我们继续往下看

我们现在的sql是

select * from order where id='xxx' limit 1

那么如果我们针对这个sql进行优化呢,譬如

select * from order where id='xxx' order by create_time desc limit 1

同样是查询第一条,添加了一个order排序那么情况就会大大的不一样,首先我们来观察我们的分片查询

//开启5个线程并发查询
--  select * from order_202201 where id='xxx' order by create_time desc  limit 1
--  select * from order_202202 where id='xxx' order by create_time desc  limit 1
--  select * from order_202203 where id='xxx' order by create_time desc  limit 1
--  select * from order_202204 where id='xxx' order by create_time desc  limit 1
--  select * from order_202205 where id='xxx' order by create_time desc  limit 1
-- 抛弃上述写法

  select * from order_202205 where id='xxx' order by create_time desc  limit 1
  select * from order_202204 where id='xxx' order by create_time desc  limit 1
  select * from order_202203 where id='xxx' order by create_time desc  limit 1
  select * from order_202202 where id='xxx' order by create_time desc  limit 1
  select * from order_202201 where id='xxx' order by create_time desc  limit 1

如果在连接模式下那么他们将会是2个一组,那么我们在查询第一组的结果后是否就可以直接抛弃掉下面的所有查询,也就是我们只需要查询

select * from order_202205 where id='xxx' order by create_time desc  limit 1
  select * from order_202204 where id='xxx' order by create_time desc  limit 1

只要他们是有返回一个以上的数据那么本次分片查询将会被终止,ShardingCore目前的大杀器,本来年前已经开发完成了,奈何太懒只是发布了版本并没有相关的说明和使用方法

CircuitBreaker

断路器,它具有类似拉闸中断操作的功能,这边简单说下linq操作下的部分方法的断路器点在哪里

方法名是否支持中断操作中断条件
First支持按顺序查询到第一个时就可以放弃其余查询
FirstOrDefault支持按顺序查询到第一个时就可以放弃其余查询
Last支持按顺序倒叙查询到第一个时就可以放弃其余查询
LastOrDefault支持按顺序倒叙查询到第一个时就可以放弃其余查询
Single支持查询到两个时就可以放弃,因为元素个数大于1个了需要抛错
SingleOrDefault支持查询到两个时就可以放弃,因为元素个数大于1个了需要抛错
Any支持查询一个结果true就可以放弃其余查询
All支持查询到一个结果fasle就可以放弃其余查询
Contains支持查询一个结果true就可以放弃其余查询
Count不支持--
LongCount不支持--
Max支持按顺序最后一条并且查询最大字段是分片顺序同字段是,max的属性只需要查询一条记录
Min支持按顺序第一条并且查询最小字段是分片顺序同字段,min的属性只需要查询一条记录
Average不支持--
Sum不支持--

这边其实只有三个操作是任何状态下都可以支持中断,其余操作需要在额外条件顺序查询的情况下才可以,并且我们本次查询分片涉及到过多的后缀表那么性能和资源的利用将会大大提升

查询配置

废话不多说我们开始以mysql作为本次案例(不要问我为什么不用SqlServer,因为写文章的时候我是mac电脑),这边我们创建一个项目新建一个订单按月分表

新建项目

安装依赖

32d8f690f023ec8454415d289280875b.png

添加订单表和订单表映射
public class Order
    {
        public string Id  { get; set; }
        public string Name  { get; set; }
        public DateTime Createtime  { get; set; }
    }

    public class OrderMap : IEntityTypeConfiguration<Order>
    {
        public void Configure(EntityTypeBuilder<Order> builder)
        {
            builder.HasKey(o => o.Id);
            builder.Property(o => o.Id).HasMaxLength(32).IsUnicode(false);
            builder.Property(o => o.Name).HasMaxLength(255);
            builder.ToTable(nameof(Order));
        }
    }
添加DbContext
public class ShardingDbContext:AbstractShardingDbContext,IShardingTableDbContext
    {
        public ShardingDbContext(DbContextOptions<ShardingDbContext> options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfiguration(new OrderMap());
        }

        public IRouteTail RouteTail { get; set; }
    }
添加订单分片路由

从5月份开始按创建时间建表

public class OrderRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<Order>
    {
        public override void Configure(EntityMetadataTableBuilder<Order> builder)
        {
            builder.ShardingProperty(o => o.Createtime);
        }

        public override bool AutoCreateTableByTime()
        {
            return true;
        }

        public override DateTime GetBeginTime()
        {
            return new DateTime(2021, 5, 1);
        }
    }
启动配置

简单的配置启动创建表和库,并且添加种子数据

ILoggerFactory efLogger = LoggerFactory.Create(builder =>
{
    builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
});
builder.Services.AddControllers();
builder.Services.AddShardingDbContext<ShardingDbContext>()
    .AddEntityConfig(op =>
    {
        op.CreateShardingTableOnStart = true;
        op.EnsureCreatedWithOutShardingTable = true;
        op.AddShardingTableRoute<OrderRoute>();
        op.UseShardingQuery((conStr, b) =>
        {
            b.UseMySql(conStr, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
        });
        op.UseShardingTransaction((conn, b) =>
        {
            b.UseMySql(conn, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
        });
    }).AddConfig(op =>
    {
        op.ConfigId = "c1";
        op.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=db2;userid=root;password=root;");
        op.ReplaceTableEnsureManager(sp=>new MySqlTableEnsureManager<ShardingDbContext>());
    }).EnsureConfig();
var app = builder.Build();

app.Services.GetRequiredService<IShardingBootstrapper>().Start();
using (var scope=app.Services.CreateScope())
{
    var shardingDbContext = scope.ServiceProvider.GetRequiredService<ShardingDbContext>();
    if (!shardingDbContext.Set<Order>().Any())
    {
        var begin = new DateTime(2021, 5, 2);
        List<Order> orders = new List<Order>(8);
        for (int i = 0; i < 8; i++)
        {
            orders.Add(new Order()
            {
                Id = i.ToString(),
                Name = $"{begin:yyyy-MM-dd HH:mm:ss}",
                Createtime = begin
            });
            begin = begin.AddMonths(1);
        }
        shardingDbContext.AddRange(orders);
        shardingDbContext.SaveChanges();
    }
}
app.UseAuthorization();
app.MapControllers();
app.Run();

这边默认连接模式的分组是Environment.ProcessorCount

编写查询

c9b79f8fa560e573d90e7e8d0f8bde0f.png
没有配置的情况下那么这个查询将是十分糟糕

接下来我们将配置Order的查询

public class OrderQueryConfiguration:IEntityQueryConfiguration<Order>
    {
        public void Configure(EntityQueryBuilder<Order> builder)
        {
            //202105,202106...是默认的顺序,false表示使用反向排序,就是如果存在分片那么分片的tail将进行反向排序202202,202201,202112,202111....
            builder.ShardingTailComparer(Comparer<string>.Default, false);
            //order by createTime asc的顺序和分片ShardingTailComparer一样那么就用true
            //但是目前ShardingTailComparer是倒序所以order by createTime asc需要和他一样必须要是倒序,倒序就是false
            builder.AddOrder(o => o.CreateTime,false);
            //配置当不存在Order的时候如果我是FirstOrDefault那么将采用和ShardingTailComparer相反的排序执行因为是false
            //默认从最早的表开始查询
            builder.AddDefaultSequenceQueryTrip(false, CircuitBreakerMethodNameEnum.FirstOrDefault);
            ////默认从最近表开始查询
            //builder.AddDefaultSequenceQueryTrip(true, CircuitBreakerMethodNameEnum.FirstOrDefault);
            //内部配置单表查询的FirstOrDefault connections limit限制为1
            builder.AddConnectionsLimit(1, LimitMethodNameEnum.FirstOrDefault);
        }
    }

    public class OrderRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<Order>
    {
        //......
        //配置路由才用这个对象查询
        public override IEntityQueryConfiguration<Order> CreateEntityQueryConfiguration()
        {
            return new OrderQueryConfiguration();
        }
    }

c1258724b889303fd64df213e2bf937d.png
带配置的Order
75318b015d30c2692f45f412de5d818a.png

现在我们将默认的配置修改回正确

//不合适因为一般而言我们肯定是查询最新的所以应该和ShardingComparer一样都是倒序查询
//builder.AddDefaultSequenceQueryTrip(false, CircuitBreakerMethodNameEnum.FirstOrDefault);
builder.AddDefaultSequenceQueryTrip(true, CircuitBreakerMethodNameEnum.FirstOrDefault);

58a76c760f3eac2ac9476cb7343c748c.png
当然如果你希望本次查询不使用配置的连接数限制可以进行如下操作

_shardingDbContext.Set<Order>().UseConnectionMode(2).Where(o=>o.Id=="7").FirstOrDefaultAsync();

结论:当我们配置了默认分片表应该以何种顺序进行分片聚合时,如果相应的查询方法也进行了配置那么将这种查询视为顺序查询,
所有的顺序查询都符合上述表格模式,遇到对应的将直接进行熔断,不在进行后续的处理直接返回,保证高性能和防止无意义的查询。

快速失败FastFail

顾名思义就是快速失败,但是很多小伙伴可能不清楚这个快速失败的意思,失败就是失败了为什么有快速失败一说,因为ShardingCore内部的本质是将一个sql语句进行才分N条然后并行执行

-- 普通sql

select * from order where id='1' or id='2'

-- 分片sql
select * from order_1 where id='1' or id='2'
select * from order_2 where id='1' or id='2'
-- 分别对这两个sql进行并行执行

在正常情况下程序是没有什么问题的,但是由于程序是并行查询后迭代聚合所以会带来一个问题,就是假设执行order_1的线程挂掉了,那么Task.WhenAll会一致等待所有线程完成,然后抛出响应的错误,
那么这在很多情况下等于其余线程都在多无意义的操作,各自管各自。

static async Task Main(string[] args)
        {
            try
            {
                await Task.WhenAll(DoSomething1(), DoSomething2());
                Console.WriteLine("execute success");
            }
            catch 
            {
                Console.WriteLine("error");
            }

            Console.ReadLine();
        }

        static async Task<int> DoSomething1()
        {
            for (int i = 0; i < 10; i++)
            {
                if (i == 2)
                    throw new Exception("111");
                await Task.Delay(1000);
                Console.WriteLine("DoSomething1"+i);
            }

            return 1;
        }
        static async Task<int> DoSomething2()
        {
            for (int i = 0; i < 10; i++)
            {
                await Task.Delay(1000);
                Console.WriteLine("DoSomething2"+i);
            }
            return 1;
        }

代码很简单就是Task.WhenAll的时候执行两个委托方法,然后让其中一个快速抛异常的情况下看看是否马上返回
a1d8045555585d0de397211ba63ccf90.png

结果是TaskWhenAll哪怕出现异常也需要等待所有的线程完成任务,这会在某些情况下浪费不必要的性能,所以这边ShardingCore参考资料采用了FastFail版本的

public static Task WhenAllFailFast(params Task[] tasks)
        {
            if (tasks is null || tasks.Length == 0) return Task.CompletedTask;

            // defensive copy.
            var defensive = tasks.Clone() as Task[];

            var tcs = new TaskCompletionSource();
            var remaining = defensive.Length;

            Action<Task> check = t =>
            {
                switch (t.Status)
                {
                    case TaskStatus.Faulted:
                        // we 'try' as some other task may beat us to the punch.
                        tcs.TrySetException(t.Exception.InnerException);
                        break;
                    case TaskStatus.Canceled:
                        // we 'try' as some other task may beat us to the punch.
                        tcs.TrySetCanceled();
                        break;
                    default:

                        // we can safely set here as no other task remains to run.
                        if (Interlocked.Decrement(ref remaining) == 0)
                        {
                            // get the results into an array.
                            tcs.SetResult();
                        }
                        break;
                }
            };

            foreach (var task in defensive)
            {
                task.ContinueWith(check, default, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }

            return tcs.Task;
        }

366a9df19c97fbe9a2f48b2164a54148.png
采用failfast后当前主线程会直接在错误时返回,其余线程还是继续执行,需要自行进行canceltoken.cancel或者通过共享变量来取消执行

总结

ShardngCore目前还在不断努力成长中,也希望各位多多包涵可以在使用中多多提出响应的意见和建议

  • demo https://github.com/xuejmnet/ShardingCircuitBreaker

参考资料

https://stackoverflow.com/questions/57313252/how-can-i-await-an-array-of-tasks-and-stop-waiting-on-first-exception

下期预告

下一篇我们将讲解如何让流式聚合支持更多的sql查询,如何将不支持的sql降级为union all

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全      

骁龙X Elite笔记本重装Windows 11 Arm64系统完整指南与避坑手册 UEFI安全启动和Arm64架构是理解现代计算设备系统部署的基础。UEFI取代传统BIOS,提供了更安全的启动环境和模块化固件接口,而Arm64架构则以其高能效特性,在移动和新兴PC领域日益重要。其技术价值在于为设备带来更快的启动速度、更强的安全防护以及更优的功耗表现。在应用场景上,这直接关系到搭载高通骁龙X Elite等Arm处理器的笔记本电脑的系统安装与维护。对于这类设备,重装系统远非插入通用安装盘那么简单,核心挑战在于必须使用专为Arm64编译的Windows镜像,并需提前集成芯片组、网络等硬件的专属 阅读详情

相关推荐

在WPS/Office中免费使用AI,快速提升办公效率!​

《免费解锁WPS/Office AI办公神器教程》摘要: 本教程详解如何通过第三方插件OfficeAI免费实现WPS/Office智能办公,突破官方付费限制。从安全设置到安装配置,手把手教学,涵盖文档生成、PPT美化、Excel图表等核心功能。关键优势包括零成本、全场景支持及云端/本地双模式切换,并附常见问题解决方案。注意需使用WPS 2024+版本,安装时需临时关闭杀毒软件。教程强调工具来源合法性,建议商用购买正版授权。(149字)

杜哥无敌的博客 2305

使用ShardingCore插件分表实践

使用ShardingCore插件分表实践

dandingwangzi的专栏 1006

深入解析SSD报错“READ FPDMA QUEUED”:从诊断到修复全流程

本文深入解析了SSD报错“READ FPDMA QUEUED”的含义、成因与全流程解决方案。该错误通常指示硬盘硬件或健康状态问题。文章详细介绍了如何通过系统日志定位错误、解读关键的S.M.A.R.T.健康报告(重点关注重分配扇区计数等指标),并逐步进行硬件排查(如更换SATA数据线)、软件修复与数据抢救,最终指导用户根据诊断结果做出维修或更换SSD的决策。

weixin_29233333的博客 400

深入了解:MyBatisPlus条件构造器带条件排序方法orderBy、orderByDesc、orderByAsc使用

MyBatisPlus是一个优秀的持久层框架,它在MyBatis的基础上进行了增强和封装,提供了更加便捷的数据库操作方式。其中,条件构造器是MyBatisPlus的重要特性之一,它可以帮助我们动态地构建SQL查询条件。而在条件构造器中,排序是一个常见的需求,MyBatisPlus提供了​​orderBy​​、​​和​​三个方法来实现条件排序。本文将介绍这三个方法的使用方式。MyBatisPlus的条件构造器提供了丰富的方法来构建SQL查询条件,其中排序是一个常见的需求。通过​​orderBy​​、​​和​。

牛肉胡辣汤 1万+

告别jom Error 2:深入理解QtCreator、CMake与MSVC工具链的协作机制

本文深入解析QtCreator构建过程中常见的jom Error 2问题,揭示CMake与MSVC工具链的协作机制。从CMake生成器的工作原理到MSVC工具链的组件协作,帮助开发者系统化诊断构建错误,提升开发效率。

weixin_30654419的博客 432

星座SAR动目标检测(GMTI)

参考代码 星座SAR动目标检测 www.youwenfan.com/contentcsg/52399.html。

feifeigo123的博客 549

我们为什么要分库分表?

在文章开头先抛几个问题:(1)什么时候才需要分库分表呢?我们的评判标准是什么?(2)一张表存储了多少数据的时候,才需要考虑分库分表?(3)数据增长速度很快,每天产生多少数据,才需要考虑做...

架构师小秘圈 536

qemu(2) -- 定制开发板

向qemu源码中添加自定义开发板

xflm的博客 843

难题来了:分库分表后,查询太慢了,如何优化?

难题来了:分库分表后,查询太慢了,如何优化?

浩浩的博客 1495

[Dify实战] 多轮对话状态管理:上下文保持与槽位填充

本文探讨了基于LLM的对话应用中多轮对话状态管理的核心挑战与解决方案。文章指出,单纯的"能聊"远远不够,关键在于建立有效的状态管理机制,包括上下文保持和槽位填充两大核心能力。通过Dify实战视角,详细阐述了如何设计工程化落地方案:采用混合策略的上下文管理(窗口+摘要+关键槽位)、JSON Schema强约束的槽位抽取、统一状态对象存储、冲突处理机制和优化追问策略。文章特别强调,合理的状态管理能将"聊天"转化为"可执行的业务流程",避免模型成为&qu

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 240

Innovus: dbGet 快速学习教程

是取反的意思,如下例子,这个选中的instance一共四个pin,当用regexp筛选CK pin后只获得CK pin,加上-v取反后就返回的值就是除CK pin以外的其他三个pin。dbGet有很多option,具体都是干嘛的,怎么用,做个简单介绍。,-p是最常用的option,-p和-p0 -p1是一个东西,-p x它代表从后往前推第x个选项,与-p搭配使用的pattern也是必须的。的意思是返回database整数,而一般我们用的是浮点数,database整数可以参考DEF里的单位去输出。

m0_61544122的博客 6958

分库分表路由算法深度优化:从 % 到 & 的极致性能追求

id & (n-1)不仅比id % n快8倍,更关键的是它为未来的扩容铺平了道路。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 4314

基于STM32设计的温室大棚种植监测系统(onenet+GPRS通信)

当前所设计的温室大棚种植监测系统基于STM32单片机开发,它能够对温室大棚内的温度、湿度、光照强度、土壤湿度、二氧化碳含量等环境参数进行实时监测,并将数据传输至OneNET云平台,实现了远程监测和管理。该系统具有体积小、功耗低、可靠性高等特点,适合在温室大棚等场合使用。

7873

海量用户也不怕!深度剖析多用户商城系统如何支撑高并发访问?

双十一、618等购物节期间,电商平台如何承受住每秒数百万次的请求而不崩溃?本文将深入探讨多用户商城系统在面临大规模并发用户访问时,从架构设计到技术实现的完整解决方案,涵盖负载均衡、缓存、数据库、微服务等核心知识点。

827

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

FLUX小红书极致真实V2图像生成工具数据库优化实战

本文介绍了如何在星图GPU平台上自动化部署FLUX.小红书极致真实 V2 图像生成工具镜像,高效支撑小红书种草笔记、商品主图及达人素材库所需的高质量人像图批量生成任务,显著提升AI内容生产稳定性与响应速度。

weixin_31139479的博客 111

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

防伪溯源系统开发性能优化:高并发验真接口优化实战分析

大促期间真正被反复扫的是少数"热码",把它们前置到缓存,就能挡住绝大多数重复请求。——也就是说,99% 的用户里最慢的那一批,要在手机上转圈超过 1 秒才能看到验真结果。:验真主链路本来是"读 + 写"都在做——验证完要把扫码记录同步写库,写操作耗时约 120ms,还占着连接。——当一个从没被扫过的新码进来,Redis 必然 miss,还是得穿透到 DB。:P99 已到 220ms,但还有地域差异——偏远地区网络往返时间长,拉高整体延迟。四步走下来,机器没多买多少,体验却是质变。不仅是体验差,更严重的是。

LJWDml的博客 328

为什么选择Redis缓存?

为了追求极致的产品体验,互联网企业架构的高性能和高可用便不可避免。 而在数据库层面,一般有以下几种优化: 1.主从配置:比如为mysql服务配置主从,则一台宕机,另一台顶上,达到高可用的要求。 2.读写分离:配置一主多从,将读取请求分发到从服务器上,可以有效的提高响应速度。 3.分库分表:当数据量不断增加,单库单表无法满足需求时,分布式数据库中间件可以解决这一问题。 而在系统层面来说,为...

yang401059441的博客 543

高并发系统设计:从 TPS 10 到 10W 的完整优化路径

本文系统性地介绍了电商系统从TPS 15到12万的全链路性能优化路径,分为五个关键阶段:首先通过索引优化、SQL调优和代码重构将性能提升到120;接着通过读写分离和缓存设计提升到1200;然后利用消息队列和分库分表实现削峰填谷,达到8000;最后通过JVM调优、连接池优化和网络配置等极致手段突破到12万。文章强调性能优化需要遵循"测量-解决瓶颈-权衡成本"的原则,指出数据库优化贡献80%收益,并提醒避免过早优化和过度设计。整个优化过程历时一年以上,是持续迭代的系统工程,最终目标是构建高可

C_x_330的博客 565

MySQL查询性能优化实战从慢查询到毫秒级响应的蜕变之路

MySQL查询性能优化不是一次性的任务,而是一个持续的过程。随着数据量的增长和业务需求的变化,新的性能瓶颈会不断出现。建立完善的监控体系,培养性能优化的思维方式,让每个开发人员都能在编写SQL时考虑到性能影响,这才是实现从慢查询到毫秒级响应蜕变的根本之道。优秀的数据库性能不仅是技术的胜利,更是团队工程卓越文化的体现。

qq_33836401的博客 429

2025年sagacity-sqltoy终极指南:企业级ORM框架深度解析与实战避坑

在当今Java开发领域,ORM框架的选择直接影响着项目的开发效率和系统性能。sagacity-sqltoy作为一款真正智慧的Java ORM框架,融合了JPA的对象化操作便利性与MyBatis的SQL灵活性,为企业级应用提供了一站式数据访问解决方案。本文将带你深入探索这个被1000+企业验证的ORM框架,从快速入门到生产实践,全面掌握其核心特性与应用技巧。 ## 快速入门:10分钟搭建开发环境

gitblog_00270的博客 893

FLUX小红书极致真实V2图像生成工具数据库设计规范

本文介绍了如何在星图GPU平台自动化部署FLUX.小红书极致真实V2图像生成工具,并详细阐述了其数据库设计规范。该工具能够高效生成高质量AI图像,适用于社交媒体内容创作、电商配图等场景,通过优化的数据库结构提升图像管理和检索效率。

weixin_42174098的博客 116

后端视角:拆解春晚背后的高可用技术架构

作为后端开发者,我们研究春晚的技术架构,不仅是为了了解其实现细节,更重要的是学习其**问题驱动、精准优化、分层解耦**的设计思想

码刀攻城 945

年流水超十亿的.NET项目,我是怎么把服务器成本压到 5 万/年以内的?

ASP.NET Core 的性能,是降本的最大底牌。我用 .NET 4核8G、2核4G 就能稳稳扛住。是**.NET 天生省资源 + 架构做对了**。但我每年的服务器总成本,控制在 5 万以内。.NET 最大的优势之一,就是极致性价比。高并发、大流量、分布式,不堆机器怎么扛?二、我做对了 6 件事,成本直接砍到地板。- 详情页、列表页、配置、字典,全部缓存。- 禁用 .Result、.Wait()一年服务器成本 5 万以内,我做到了。- 能异步就不同步,能不查库就不查库。

dotNET跨平台 46

浅谈分库分表

文章目录前言一、为什么要分库分表1.数数据性能瓶颈的出现2.数据库优化方案对比2.1 重启2.2 SQL与索引2.3 表与存储引擎2.4 架构2.5 数据库配置2.6 操作系统3. 什么时候分表二、分库分表的类型和特点1. 垂直切分2. 水平切分3. 分库分表带来的问题总结 前言 理解分库分表的意义 理解数据切分的不同方式,以及带来的问题与解决方案 通过实际案例掌握MyCat特性与详细配置含义 理解MyCat监控与日志查看 一、为什么要分库分表 随着业务变得越来越复杂,用户越来越多,集中式的架构.

本人是个小小程序员,此博客一是为了激励自己学习,二是为了记录自己的学习历程,三是为了能够及时回顾相关知识。 1299

Mycat (一) —— 数据库优化和分库分表

一.数据库优化方案 当数据库遇到瓶颈,比如高并发情况下连接数不够;数据量太大;因存储问题,数据库所在机器性能下降。就需要进行优化: 1.SQL与索引:检查自己的慢SQL,进行优化,用到索引 2.表和存储引擎:优化表设计,对于字段类型和长度的选择,看表结构是否需要拆分或合并,不同的表需要选择什么存储引擎,是不是需要分区等 3.架构:(1)数据是在磁盘存储,如果加了索引还是很慢,可以部署缓存服务器,把数据在内存里缓存起来。 (2)如果...

zhouhuahao的博客 483

MySQL 查询优化如何坐到极致?

什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS:QueriesPerSecond意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。 TPS:是TransactionsPerSecond的缩写,也就是事务数/秒。它是软件测试结果的测量单位。客户机在发送请求时开始计时,收到服务器响应后结...

Formor_的博客 311
上一篇: 使用Blazor做个简单的时间戳在线转换工具
下一篇: .NET Core中异常过滤器ExceptionFilter的使用介绍
zls365365
博客等级 码龄7年 1759粉丝 289原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值