admin

  • 在今天凌晨的AWS re:Invent上,Aurora发布了最新的功能“Aurora Limitless”。这是一个基于水平拆分的分布式数据库,算是最近几年来说Aurora发布另一个非常大的功能点。

    Aurora Limitless主要是解决两个问题:一个是写扩展,另一个是容量扩展。这也是国内的分布式数据库(诸如PolarDB-X、TDSQL、OceanBase、TiDB等)所解决的最主要的问题,海外也有诸如YugabyteDB、CockroachDB等产品。现在Aurora也加入了这个战场。

    (more…)
  • 概述

    阿里云数据库在去年云栖大会上发布了基于阿里倚天芯片(ARM架构)的RDS实例,后正式命名为经济版。本文通过标准的sysbench测试,来看看相比与标准版,经济版是否更加“经济”,以帮助开发者选择适合自己的规格。

    这里选择了用户较为常用的4c16g的规格进行测试,测试工具使用了sysbencholtp_read_write模型进行测试。配置参数与选项,均尽量使用RDS购买过程中的默认选项,以给出更加接近用户使用时的配置。具体的,使用了默认的“高性能参数模板”、使用了ESSD PL1存储,选择了默认的8.0实例。

    结论

    在如上的默认配置中,分别使用了2、4、8、10、12、14、16、24、32个并发线程进行测试。整体上,经济版(ARM)实例性能相比x86版要低约4%,延迟要高约4%。价格上,该规格经济版(ARM)相比x86版要低约36%,使用阿里云RDS经济版(ARM)性价比确实更高,相比标准版(x86)性价比要高出32%。

    具体的,这里我们选取16并发为性能基准参考,那么,对应的经济版TPS为2185,标准版的TPS为2324。价格上,该规格经济版价格为1.61元/时,标准版价格为2.52元/时,那么对应每1000个TPS的价格分别为:0.74元与1.08元。从性价比的角度来看,经济版提升了31.5%。

    所以,经济版(ARM)RDS还是非常值得一试。另一方面也可以看到x86版本在性能、延迟上依旧有一定的优势,如果追求更极限的性能,以及更好的稳定性,依旧建议使用x86版本。

    测试方法说明

    这里使用了sysbench的读写混合模型(oltp_read_write)进行测试,单表大小为100万,共十个表,单次测试时长为300秒,分别测试了如下的并发度的性能表现:2、4、8、10、12、14、16、24、32

    测试使用的RDS为4c16g的高可用系列、“通用”规格、磁盘使用ESSD PL1/100GB云盘、双可用区、MySQL 8.0的实例。测试的ECS使用8c8g规格,测试的ECS也在杭州可用区J,所以,注意测试过程中,RDS表现的Latency整体是非常低的。

    规格与价格明细

    详细测试数据参考

    RDS经济版(ARM)4c16g通用型实例的测试详细结果如下:

    threads|transactions| queries| time |avg/Latency|95%/Latency
          2|      115305| 2306100|300.01|       5.20|       5.99
          4|      225711| 4514220|300.01|       5.32|       6.09
          8|      425336| 8506720|300.01|       5.64|       6.91
         10|      518460|10369200|300.01|       5.78|       7.17
         12|      604286|12085720|300.01|       5.96|       7.70
         14|      634556|12691120|300.01|       6.62|      13.22
         16|      655665|13113300|300.01|       7.32|      21.89
         24|      628932|12578640|300.01|      11.45|      45.79
         32|      628452|12569040|300.03|      15.27|      57.87

    RDS标准版(x86)4c16g实例的测试详细结果如下:

    threads|transactions| queries| time |avg/Latency|95%/Latency
          2|      113699| 2273980|300.01|       5.28|       5.57
          4|      228466| 4569320|300.01|       5.25|       5.57
          8|      439913| 8798260|300.01|       5.45|       5.77
         10|      540436|10808720|300.01|       5.55|       5.88
         12|      629480|12589600|300.01|       5.72|       6.09
         14|      710254|14205080|300.01|       5.91|       7.30
         16|      697323|13946460|300.01|       6.88|      18.61
         24|      661203|13224060|300.01|      10.89|      47.47
         32|      656784|13135680|300.01|      14.61|      58.92

    限制与说明

    真实的场景会更加复杂一些,需要考虑的因素更多,例如数据库的场景模型、不同的参数模板、不同的磁盘性能(ESSD PL1/2/3)、不同世代的CPU、不同规格(“通用”、“独享”)、价格折扣等。本文尝试通过测试一个常用规格的、常用配置,给开发者一个直观的性能的感受,以帮助开发者选择合适的、更具性价比的数据库规格与类型。

    小结

    阿里云RDS的经济型(ARM版)正式商业化已经有一年时间,从实测来看,相比x86版本有着非常明显的性价比优势,相同规格性能损失约5%的情况下,价格有35%的下降,是非常适合开发测试环境,已经小范围在生产环境尝试使用的。

    最后,这将是一个系列的文章,后续还将考虑对比华为云、AWS的ARM实例与x86实例的性能,以帮助开发者选择更具性价比,更适合自己的数据库架构与规格。

  • 虽说标题是“Alibaba Cloud Linux”,不过对于Amazon Linux、华为云EulerOS/openEuler、TencentOS等都均适用。

    1. 添加自己的密钥对,方便本地快速登录:

    vi .ssh/authorized_keys

    2. 修改 sshd 配置,防止ssh会话经常断开:

    vim /etc/ssh/sshd_config
    
    ...
    ClientAliveInterval 30
    ClientAliveCountMax 3
    ...
    
    service sshd restart

    3. 修改本地的环境变量,包括语言、vim配置等

    vi .bash_profile 
    # 很多程序的错误提示,还是希望能够是英文的,更利于搜索
    export LANG=en_US.UTF-8
    export LANGUAGE=en_US
    
    # 更改为中国时区
    export TZ=Asia/Shanghai
    
    # root账号下,经常使用vi,其实想要vim
    # 当然,用root账号是非常不好的习惯
    alias vi="vim"
    
    # 配置一些vim的初始化的配置
    vi ~/.vimrc
    set number
    set tabstop=4
    set shiftwidth=4
    set expandtab
    syntax on

    4. 个人使用的省钱大法:在主机不使用的时候,可以使用“节省停机模式”关闭ECS。这样ECS最贵的计算和内存资源将不再收费。可以大大降低个人在测试使用的时候成本。目前,AWS、华为云、腾讯云等基本都支持该能力。缺点在于,每次重启后,可能会重新分配新的公网IP,使用上略有不便。不过,如果你已经有99块的ECS的话,每次以此为跳板机,使用内网IP跳转也是一个办法。

  • MySQL在上个月正式EOL,意味着官方不会再发布新版本去修复Bug或者安全漏洞。一般来说,云厂商对老版本支持要更就一些,那么一起来看看各个云厂商对5.7的支持情况。概述:

    • AWS:首先,AWS RDS MySQL将提供额外的、免费的半年标准支持,期间提供bug修复、漏洞修复等;2024年2月后,AWS RDS将提供付费的扩展支持。届时,如果不选择付费扩展支持的实例,将会自动(可以理解为“强制”)被升级到8.0版本,“付费”的扩展支持应该持续3年。(注:Aurora的免费支持时间会更长一些,到2024年11月)
    • 阿里云:目前,对于5.7还没有看到正式的说明。但,对于5.6版本,阿里云数据库曾发通告,将提供额外的三年维护时间。不过鉴于5.7实例体量巨大(因为8.0版本拖的时间太长),对于5.7版本支持的时间可能会更长。
    • 其他云厂商:目前都比较模糊,可以理解为不会有任何动作,用户可以正常使用。

    AWS对MySQL 5.7的支持

    AWS有Aurora MySQL 5.7(即Aurora 2.x系列)、RDS MySQL 5.7两个版本。在Oracle MySQL官方到达EOL后,AWS额外提供了半年(Aurora约一年)的免费标准支持,以及三年的付费支持。即,AWS RDS将免费支持5.7到2024年02月底,Aurora到2024年11月底;另外,还将提供三年的付费支持,约到2027年。是的,要收费的(参考)。这段时间,AWS将继续提供安全相关的Bug修复、以及重要的功能Bug修复。

    这个收费策略应该是开了云厂商对于旧版本数据库支持的先河。维护老的版本,需要额外的技术人员投入,维护一个过期的版本的投入从长时间来看,是低效的,所以,用户是需要为这部分服务付费的。

    AWS 扩展支持的收费方式与费率

    收费方式是按照vCPU * HourACU * Hour计费,不同的区域会有不同,不同的时间也会不同,离官方EOL时间越长,费用会越贵。不过,在官方版本到达EOL之后,AWS预留了4个月~一年的免费时间,让用户安排升级。以RDS MySQL 5.7为例,自2024年2月底之后,以新加坡地区为例,前两年付费扩展支持价格为 $0.12/(vCPU * Hour),第三年的费用为$0.24/(vCPU * Hour)。以一个4c16g(db.m5.xlarge)的实例计算,一个月费扩展支持费用约为$345。而该实例本身的价格约为(两节点高可用):$677 = 0.47*24*30*2。所以,AWS的策略是,价格摆在这里了,升不升级,由用户自己定夺。

    (more…)
  • 自今年八月底开馆,今天是第九次来这里,娃来自习写作业,我来这里或学习一会儿、或工作一会儿。

    一楼大厅右侧,很有设计感,适合拍照发圈

    (more…)
  • 引言

    这是一个系列文章,旨在了解如何使用Flex/Lex和Yacc/Bison进行词法和语法解析。在前面,已经完成了使用Lex/flex做基础的词法解析。接着,开始这个系列的第二部分,使用flex和bison完成一个简单的计算器。

    为了简化实现,将注意力放在简单flex和bison使用上,这里对计算器做了几个简化:

    • 只支持加、减、乘计算,暂时不支持除法,除法可能涉及到浮点类型,故暂时忽略
    • 不考虑整数溢出的问题,这里使用int类型(那么他存储与计算范围是有限的)

    也就是该程序可以计算加法、减法、乘法,以及他们的任意组合,如: 3+4、 3+4*2、 3+4*2-3、 3+4*2-3*2

    后续,还将考虑增加更急复杂的计算器,包括:

    • 实现,带有变量的计算器程序
    • 实现带来循环、带有条件判断的程序

    这里先从简单的开始。

    初次手写一个cal.l和cal.y

    这是在vim中写出的第一遍代码,包含了词法文件cal.l和语法文件cal.y,详细如下。这其中当然是有很多错误的,之所以,依旧写出来,是为了和正确代码对比,以此看看对哪些概念理解有偏差。如果你是找一个正确例子的话,可以跳过这一段。

    %{
    #inlcude <stdlib.h>
    %}
    /* 十进制整数 */
    %token INTEGER
    
    %union { 
        int a;
    }
    
    /* 操作符 + - * / */
    %token OPERATOR
    
    %%
    program:
        program expression \n { printf("%d",$2); }   // 这里就是以回车结尾,也可以考虑使用 = 结尾
        |
    
    expression:
    		  INTEGER
    		| expression '+' expression {$$ = $1 + $2}
    		| expression '-' expression {$$ = $1 - $2}
    		| expression '*' expression {$$ = $1 * $2}
    
    dec_integer: 
    		INTEGER
    			{
    			$$ = $1.a;
    			}

    这里也有几个已知的问题,例如:运算符的优先级没有定义,也就说4+3*2可能会算成14。没错,如果眼尖的话,还发现有一些拼写错误。

    接着是cal.l文件:

    #inlcude <stdlib.h>
    #include "y.tab.h"
    ​
    %}
    [:digit:]+ {
                yylval.a = atoi(yytext)
                RETURN INTEGER;
    }

    当然,这里面有很多的错误。一会儿来看后面正确的内容。

    修改cal.l和cal.y

    • 首先,是去解决已知的问题:运算符优先级如何去解决?关于什么是优先级、什么是结合律这里不做详述,这里有一篇文章讲得比较细致,几幅图也非常直观:Precedence and Associativity of Operators in Python。虽然是不同的语言,但意思是一样的。理解这个点还是比较重要的,例如在关系型数据库中,之前有遇到过这样的案例,可以思考一下如下的表达式 t.col < 2 or t.col < 11 and t.col > 4 是什么意思:
    -- 猜测一下,如下的 SELECT 查询是否能够返回记录:
    
    CREATE TABLE t(col INT); 
    
    INSERT INTO t values (1);
    
    WHERE t.col < 2 or  t.col < 11 and  t.col > 4

    扯远了,再回到cal.y文件,优先级和结合律需要进行如下修改,以定义”*”优先级高于”+”、”-“:

    %left '+' '-'
    %left '*'

    这里的代码先后,就定义了优先级;优先级越高,定义在越在后面;left表示,左结合。

    • 除了优先级,在cal.y语法规则中的定义部分,如果有字符,并没有使用引号。例如上面的cal.y的第17行的\n,是需要加上引号的,即 '\n'

    • 对于cal.y的中定义的语法规则,并没有定义返回值存储在联合体(YYSTYPE,也就是如下这里cal.y定义的唯一的那个联合体)哪个类型中。例如,没有定义”expression”这个语法规则,返回值是使用哪个值,虽然这里的联合体只定义了一个类型(即int a)。具体的,添加了如下代码:
    %token <a> INTEGER
    %type <a> expression

    完成这样的定义后,在lex的文件cal.l中,就可以对yylval进行赋值,如:yylval.a = atoi(yytext); 这时,对于yacc文件中cal.y,如果引用这个TOKEN,就可以使用$1(或者是$2、$3)来引用lex解析后的返回值,如:expression: INTEGER { $$ = $1;}

    • 于是,重新使用了独立的Token重新定义了运算符,并定义了优先级,如下:
    cat cal.y
    ...
    %token O_ADD O_MINUS O_MULTIPLY O_EQ
    
    %left O_ADD O_MINUS
    %left O_MULTIPLY 
    
    %token <a> INTEGER
    %type <a> expression
    ...
    
    cat cal.l
    ...
    "=" { return O_EQ;};
    "+" { return O_ADD;};
    "-" { return O_MINUS;};
    "*" { return O_MULTIPLY;};
    ...
    • 没有定义 yyerror 函数,程序也会编译不过去,会报如下错误:
    cal.tab.c:(.text+0x53b): undefined reference to `yyerror'

    按照文档,可以定义一个最简单的yerror函数(参考:The Error Reporting Function yyerror),如下:

    void
    yyerror (char const *s)
    {
      fprintf (stderr, "something error: %s\n over", s);
    }
    • 删除了无效的dec_integer规则,如果有无效的规则,也会失败
    • 将[:digit:]修改为[0-9]+。至于为什么[:digit:]不生效,后面做了一些搜索。为了避免歧义,需要额外再加一层中括号,写法也就是[[:digit:]]。详细参考:Patterns@Lexical Analysis With Flex

    完整的计算器程序文件cal.l cal.y

    补充一个main入口函数,修改cal.l、cal.y即可。

    修正后的cal.l

    %{
        #include "cal.tab.h"
        #include <stdio.h> 
    %}
    %option noyywrap
    %%
    [0-9]+ {
    			yylval.a = atoi(yytext);
    			return INTEGER;
        	   }
    
    "=" { return O_EQ;};
    "+" { return O_ADD;};
    "-" { return O_MINUS;};
    "*" { return O_MULTIPLY;};
    
    %%

    修正后的cal.y

    %{
    	#include <stdlib.h>
    	#include <stdio.h>
    
    
    int main(){
    	yyparse();
    }
    
    void
    yyerror (char const *s)
    {
      fprintf (stderr, "something error: %s\n over", s);
    }
    
    %}
    
    
    %union { 
        int a;
    }
    
    %token O_ADD O_MINUS O_MULTIPLY O_EQ
    %token <a> INTEGER
    
    %left O_ADD O_MINUS
    %left O_MULTIPLY 
    %type <a> expression
    
    %%
    program:
        |
        program expression O_EQ { printf("result is : %d",$2); }   
    ;
    expression:
    		  INTEGER { $$ = $1;}
    		| expression O_ADD expression {$$ = $1 + $3; }
    		| expression O_MINUS expression {$$ = $1 - $3; }
    		| expression O_MULTIPLY expression {$$ = $1 * $3;}
    ;

    编译与执行

    然后,就可以生成c文件并编译可执行文件了:

    lex cal.l 
    bison -d cal.y 
    gcc cal.tab.c lex.yy.c -o a.out
    ./a.out
    4+3*2=
    
    也可以像这样:
    lex cal.l && bison -d cal.y && gcc cal.tab.c lex.yy.c -o a.out && ./a.out

    附带注释说明的cal.y文件

    %{                                    // %{ ... %}  包含了完整的C语言代码        
    	#include <stdlib.h>           // 这里包含需要的头文件、入口函数main
    	#include <stdio.h>            //    以及一个简答的yyerror函数
    
    
    int main(){
    	yyparse();
    }
    
    void
    yyerror (char const *s)
    {
      fprintf (stderr, "something error: %s\n over", s);
    }
    
    %}
    
    
    %union {                             // 这是一个非常重要的联合体,用于定义
        int a;                           // 各种不同类型的Token所返回的数据
    }                                    // 广泛的被yylex使用,并用于与.yy文件共享数据
                                         // 也就是 YYSTYPE 
    
    %token O_ADD O_MINUS O_MULTIPLY O_EQ
    %token <a> INTEGER                   // 这里表示INTEGER(这是一个被lex识别的token)
                                         // INTEGER(被lex识别的token返回值为YYSTYPE.a
    %left O_ADD O_MINUS                  // 这里定义 + -为左结合律
    %left O_MULTIPLY                     // 这里定义 * 为左结合律,并且优先级高于 + -
    %type <a> expression                 // 这里定义语法规则(grammer rule)expression
                                         // 的返回值为 YYSTYPE.a
    %%
    program:                             // 这是start symbol,所有的program都需要符合该定义
        |
        program expression O_EQ { printf("result is : %d",$2); }   
    ;
    expression:
    		  INTEGER { $$ = $1;}
    		| expression O_ADD expression {$$ = $1 + $3; }
    		| expression O_MINUS expression {$$ = $1 - $3; }
    		| expression O_MULTIPLY expression {$$ = $1 * $3;}
    ;