OpenSSL与yaSSL性能对比

摘要

MySQL可以使用OpenSSL或yaSSL/wolfSSL进行编译,这两者都支持基于OpenSSL API的加密连接。在5.7版本,我们知道默认情况下MySQL Community Edition用的SSL库是yaSSL,而在8.0版本,MySQL Community Edition用的是OpenSSL。那么SSL加密对性能有什么影响呢?这两个SSL库在性能上又到底有多大差别呢?我们接下来进行一些测试并进行分析。

测试内容

MySQL有两个功能使用到了SSL库,一个是SSL连接,通过在数据库服务器与客户端应用程序之间强制实施SSL连接,可以加密服务器与应用程序之间的数据流,有助于防止“中间人”攻击;还有一个是透明加密,通过对存储的数据进行加密,来保证数据的安全。因此我们测试采用两个测试组来分别对这两个功能进行测试。测试采用sysbench执行oltp系列场景对应脚本。

测试环境

1 SSL连接测试组

2 透明加密测试组

1 SSL连接测试组测试步骤

  1. 安装并初始化mysql,将数据目录设定在测试的SSD盘上;
  2. 主备机按照异步备方式连接; 密钥生成说明:本次测试使用openssl生成长度为2048的非对称密钥(rsa-2048),生成方式如下: #生成根密钥 $ openssl genrsa 2048 > ca-key.pem #生成根证书 $ openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem #生成服务器证书请求,用以生成服务器密钥、证书 $ openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem #生成服务器密钥(私钥) $ openssl rsa -in server-key.pem -out server-key.pem #生成服务器证书(公钥,x509格式封装) $ openssl x509 -req -in server-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem #生成客户端证书请求,用以生成服务器密钥、证书 $ openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem #生成客户端密钥(私钥) $ openssl rsa -in client-key.pem -out client-key.pem #生成客户端证书(公钥,x509格式封装) $ openssl x509 -req -in client-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
  3. 启动mysqld服务;
  4. 分别对oltp_delete、oltp_insert、oltp_point_select、oltp_read_only、oltp_read_write、oltp_update_index、oltp_update_non_index、oltp_write_only、 select_random_points、select_random_ranges这11个测试模型运行以下命令: $ export LD_LIBRARY_PATH=/***/***/lib $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --time=300 oltp_delete --mysql-password=root --mysql-host=***.***.***.*** prepare $ date $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --time=300 oltp_delete --mysql-password=root --mysql-host=***.***.***.*** run $ date $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --time=300 oltp_delete --mysql-password=root --mysql-host=***.***.***.*** cleanup
  5. 执行以下命令收集sysbench执行run过程中的io数据、cpu数据、perf数据以及堆栈信息; $ iostat -t 2 -c -d -x /dev/*** > iostat.log $ perf top -p mysqld_process_id $ pt-pmp -p mysqld_process_id > ptpmp.log
  6. 不启用SSL时,在配置文件中添加如下配置并重启mysqld; skip_ssl=on
  7. 短连接测试。运行N个进程,每个进程独立执行M次mysql命令,每个命令都是建立连接-运行-断开连接模式。由于sysbench不支持该模型,用shell脚本编写上述测试模型进行测试,脚本自动生成日志,记录连接成功与否、记录perf record信息。脚本在nossl执行后立即切换到ssl状态继续执行,一共执行2次:第一次是20个进程,每个进程执行10000次insert && select count(*)语句,配置参数max_connections设置为150(默认);第二次是100个进程,每个进程执行1000次mysql连接,不执行任何语句,每次短连接运行脚本,配置参数max_connections设置为10000。第一次短连接运行脚本为: $ mysql -e "use sbtest;insert into connectTest values(a);select count(*) from connectTest;"

2 透明加密测试组

  1. 安装并初始化mysql,将数据目录设定在测试的SSD盘上;
  2. 启动mysqld服务;
  3. 依次测试oltp_delete、oltp_insert、oltp_point_select、oltp_read_only、oltp_read_write、oltp_update_index、oltp_update_non_index、oltp_write_only、select_random_points、select_random_ranges、bulk_insert这11个场景,执行以下命令测试性能: $ export LD_LIBRARY_PATH=******** $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --mysql-socket=/***/mysql.sock --time=300 oltp_delete prepare $ mysql -uroot -S /***/mysql.sock -e "alter table sbtest1 encryption='Y'" sbtest #加密场景需额外执行该SQL命令将所有测试表进行加密。 $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --mysql-socket=/***/mysql.sock --time=300 oltp_delete run $ sysbench --tables=100 --table-size=4000000 --threads=50 --mysql-db=sbtest --mysql-user=root --mysql-socket=/***/mysql.sock --time=300 oltp_delete cleanup
  4. 执行以下命令收集sysbench执行run过程中的io数据、cpu数据、perf数据以及堆栈信息。 $ iostat -t 2 -c -d -x /dev/*** > iostat.log $ perf top -p mysqld_process_id $ pt-pmp -p mysqld_process_id > ptpmp.log

测试结果及分析

1 SSL连接测试组

下表是部分场景中TPS性能上面的差别。

在大部分场景中(oltp_delete,oltp_insert,oltp_update_index,oltp_update_non_index, oltp_write_only, select_random_points, select_random_ranges),配置yaSSL与不配置SSL的性能在TPS表现差别不大,性能差别在5%以内,不作为关注的重点;在部分测试场景(oltp_point_select、oltp_read_only、oltp_read_write)配置SSL对性能影响较大,分别有26.03%,43.29%,29.18%的性能下降。

具体原因分析:

对txsql进行perf分析,发现oltp_point_select、oltp_read_only、oltp_read_write这三个场景导致性能下降的热点是加解密过程,以性能下降最为明显的oltp_read_only场景为例,下图所示perf热点分析对比:

带SSL的热点主要在以下两个函数:

TaoCrypt::AES::encrypt(unsigned char const*, unsigned char const*, unsigned char*) const
TaoCrypt::SHA::Transform()

经过对sysbench脚本分析,只有oltp_point_select、oltp_read_only、oltp_read_write这三个场景用到了execute_point_selects() 这个测试模型,而且性能差异明显的oltp_read_only场景中,仅仅跑了oltp_read_only这一个模型。这个模型仅调用”SELECT c FROM sbtest%u WHERE id=?” ,客户端在查询后立即执行,因此数据库对每次查询都是立即返回,不会做batch,数据库返回数据次数增加,增多对小数据的加密,增加加密次数,因此性能差异明显体现。

对比OpenSSL和yaSSL的数据(仅测试3个SSL影响较大的场景),总体上看OpenSSL比yaSSL性能高一点。oltp_select_point场景有点异常,性能低很多。

查看perf对比数据:

很明显加密后出现一个热点。使用pt-pmp工具查看对应的堆栈:

    Mon Jul 23 14:24:07 CST 2018
    28 pthread_rwlock_rdlock(libpthread.so.0),native_rw_rdlock(thr_rwlock.h:79),inline_mysql_rwlock_rdlock(thr_rwlock.h:79),openssl_lock(thr_rwlock.h:79),openssl_lock_function(thr_rwlock.h:79),int_thread_get_item(libcrypto.so.10),ERR_get_state(libcrypto.so.10),get_error_values(libcrypto.so.10),SSL_get_error(libssl.so.10),ssl_should_retry(viossl.c:133),vio_ssl_read(viossl.c:133),net_read_raw_loop(net_serv.cc:672),net_read_packet_header(net_serv.cc:756),net_read_packet(net_serv.cc:756),my_net_read(net_serv.cc:899),Protocol_classic::read_packet(protocol_classic.cc:808),Protocol_classic::get_command(protocol_classic.cc:965),do_command(sql_parse.cc:965),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    10 __io_getevents_0_4,LinuxAIOHandler::collect(os0file.cc:2500),LinuxAIOHandler::poll(os0file.cc:2646),os_aio_linux_handler(os0file.cc:2702),os_aio_handler(os0file.cc:2702),fil_aio_wait(fil0fil.cc:5906),io_handler_thread(srv0start.cc:311),start_thread(libpthread.so.0),clone(libc.so.6)
    8 pread64(libpthread.so.0),execute(os0file.cc:2179),os_file_io(os0file.cc:2179),os_file_pread(os0file.cc:5644),os_file_read_page(os0file.cc:5644),os_file_read_func(os0file.cc:6076),os_aio_func(os0file.cc:6076),pfs_os_aio_func(os0file.ic:261),fil_io(os0file.ic:261),buf_read_page_low(buf0rea.cc:183),buf_read_page(buf0rea.cc:183),buf_page_get_gen(buf0buf.cc:4196),btr_cur_search_to_nth_level(btr0cur.cc:1107),btr_pcur_open_with_no_init_func(btr0pcur.ic:521),row_search_mvcc(row0sel.cc:5091),ha_innobase::index_read(ha_innodb.cc:8770),handler::index_read_idx_map(handler.cc:7503),handler::ha_index_read_idx_map(handler.cc:3082),read_(handler.cc:3082),join_read_const_table(handler.cc:3082),JOIN::extract_func_dependent_tables(sql_optimizer.cc:5579),JOIN::make_join_plan(sql_optimizer.cc:5043),JOIN::optimize(sql_optimizer.cc:368),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    3 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),srv_worker_thread(srv0srv.cc:2528),start_thread(libpthread.so.0),clone(libc.so.6)
    3 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),buf_flush_page_cleaner_worker(buf0flu.cc:3496),start_thread(libpthread.so.0),clone(libc.so.6)
    2 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),rw_lock_x_lock_func(sync0rw.cc:795),pfs_rw_lock_x_lock_func(sync0rw.ic:705),btr_search_x_lock(sync0rw.ic:705),btr_search_info_update_slow(sync0rw.ic:705),btr_search_info_update(btr0sea.ic:81),btr_cur_search_to_nth_level(btr0sea.ic:81),btr_pcur_open_with_no_init_func(btr0pcur.ic:521),row_search_mvcc(row0sel.cc:5091),ha_innobase::index_read(ha_innodb.cc:8770),handler::index_read_idx_map(handler.cc:7503),handler::ha_index_read_idx_map(handler.cc:3082),read_(handler.cc:3082),join_read_const_table(handler.cc:3082),JOIN::extract_func_dependent_tables(sql_optimizer.cc:5579),JOIN::make_join_plan(sql_optimizer.cc:5043),JOIN::optimize(sql_optimizer.cc:368),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    2 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),rw_lock_s_lock_spin(sync0rw.cc:425),rw_lock_s_lock_func(sync0rw.ic:433),pfs_rw_lock_s_lock_func(sync0rw.ic:433),btr_search_drop_page_hash_index(sync0rw.ic:433),buf_LRU_free_page(buf0lru.cc:2062),buf_LRU_free_from_common_LRU_list(buf0lru.cc:1078),buf_LRU_scan_and_free_block(buf0lru.cc:1078),buf_LRU_get_free_block(buf0lru.cc:1353),buf_page_init_for_read(buf0buf.cc:5145),buf_read_page_low(buf0rea.cc:149),buf_read_page(buf0rea.cc:149),buf_page_get_gen(buf0buf.cc:4196),btr_cur_search_to_nth_level(btr0cur.cc:1107),btr_pcur_open_with_no_init_func(btr0pcur.ic:521),row_search_mvcc(row0sel.cc:5091),ha_innobase::index_read(ha_innodb.cc:8770),handler::index_read_idx_map(handler.cc:7503),handler::ha_index_read_idx_map(handler.cc:3082),read_(handler.cc:3082),join_read_const_table(handler.cc:3082),JOIN::extract_func_dependent_tables(sql_optimizer.cc:5579),JOIN::make_join_plan(sql_optimizer.cc:5043),JOIN::optimize(sql_optimizer.cc:368),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    1 ut_delay(libc.so.6),rw_lock_s_lock_spin(sync0rw.cc:355),rw_lock_s_lock_func(sync0rw.ic:433),pfs_rw_lock_s_lock_func(sync0rw.ic:433),btr_search_drop_page_hash_index(sync0rw.ic:433),buf_LRU_free_page(buf0lru.cc:2062),buf_LRU_free_from_common_LRU_list(buf0lru.cc:1078),buf_LRU_scan_and_free_block(buf0lru.cc:1078),buf_LRU_get_free_block(buf0lru.cc:1353),buf_page_init_for_read(buf0buf.cc:5145),buf_read_page_low(buf0rea.cc:149),buf_read_page(buf0rea.cc:149),buf_page_get_gen(buf0buf.cc:4196),btr_cur_search_to_nth_level(btr0cur.cc:1107),btr_pcur_open_with_no_init_func(btr0pcur.ic:521),row_search_mvcc(row0sel.cc:5091),ha_innobase::index_read(ha_innodb.cc:8770),handler::index_read_idx_map(handler.cc:7503),handler::ha_index_read_idx_map(handler.cc:3082),read_(handler.cc:3082),join_read_const_table(handler.cc:3082),JOIN::extract_func_dependent_tables(sql_optimizer.cc:5579),JOIN::make_join_plan(sql_optimizer.cc:5043),JOIN::optimize(sql_optimizer.cc:368),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    1 trx_commit_low(trx0trx.cc:2095),trx_commit(trx0trx.cc:2199),trx_commit_for_mysql(trx0trx.cc:2418),innobase_commit_low(ha_innodb.cc:4296),innobase_commit(ha_innodb.cc:4296),ha_innobase::external_lock(ha_innodb.cc:15748),handler::ha_external_lock(handler.cc:7892),unlock_external(lock.cc:667),mysql_unlock_tables(lock.cc:416),mysql_unlock_some_tables(lock.cc:431),JOIN::optimize(sql_optimizer.cc:412),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)

大部分连接在等待一个读锁,这个锁是openssl1.1.0之前的版本所要求的,由MySQL实现后通过调用api传入。我们使用openssl1.1.0h版本源码重编译一个静态库,并重新编译txsql测试这个场景。此时查看到pt-pmp工具输出堆栈为:

    Tue Jul 24 15:49:41 CST 2018
    12 pread64(libpthread.so.0),execute(os0file.cc:2179),os_file_io(os0file.cc:2179),os_file_pread(os0file.cc:5644),os_file_read_page(os0file.cc:5644),os_file_read_func(os0file.cc:6076),os_aio_func(os0file.cc:6076),pfs_os_aio_func(os0file.ic:261),fil_io(os0file.ic:261),buf_read_page_low(buf0rea.cc:183),buf_read_page(buf0rea.cc:183),buf_page_get_gen(buf0buf.cc:4196),btr_cur_search_to_nth_level(btr0cur.cc:1107),btr_pcur_open_with_no_init_func(btr0pcur.ic:521),row_search_mvcc(row0sel.cc:5091),ha_innobase::index_read(ha_innodb.cc:8770),handler::index_read_idx_map(handler.cc:7503),handler::ha_index_read_idx_map(handler.cc:3082),read_(handler.cc:3082),join_read_const_table(handler.cc:3082),JOIN::extract_func_dependent_tables(sql_optimizer.cc:5579),JOIN::make_join_plan(sql_optimizer.cc:5043),JOIN::optimize(sql_optimizer.cc:368),st_select_lex::optimize(sql_select.cc:1009),handle_query(sql_select.cc:164),execute_sqlcom_select(sql_parse.cc:5247),mysql_execute_command(sql_parse.cc:2851),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    10 poll(libc.so.6),vio_io_wait(viosocket.c:834),vio_socket_io_wait(viosocket.c:105),vio_ssl_read(viossl.c:196),net_read_raw_loop(net_serv.cc:672),net_read_packet_header(net_serv.cc:756),net_read_packet(net_serv.cc:756),my_net_read(net_serv.cc:899),Protocol_classic::read_packet(protocol_classic.cc:808),Protocol_classic::get_command(protocol_classic.cc:965),do_command(sql_parse.cc:965),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    10 __io_getevents_0_4,LinuxAIOHandler::collect(os0file.cc:2500),LinuxAIOHandler::poll(os0file.cc:2646),os_aio_linux_handler(os0file.cc:2702),os_aio_handler(os0file.cc:2702),fil_aio_wait(fil0fil.cc:5906),io_handler_thread(srv0start.cc:311),start_thread(libpthread.so.0),clone(libc.so.6)
    3 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),srv_worker_thread(srv0srv.cc:2528),start_thread(libpthread.so.0),clone(libc.so.6)
    3 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),buf_flush_page_cleaner_worker(buf0flu.cc:3496),start_thread(libpthread.so.0),clone(libc.so.6)
    2 read(libpthread.so.0),sock_read,BIO_read,ssl3_read_n,ssl3_get_record,ssl3_read_bytes,ssl3_read,SSL_read,vio_ssl_read(viossl.c:186),net_read_raw_loop(net_serv.cc:672),net_read_packet_header(net_serv.cc:756),net_read_packet(net_serv.cc:756),my_net_read(net_serv.cc:899),Protocol_classic::read_packet(protocol_classic.cc:808),Protocol_classic::get_command(protocol_classic.cc:965),do_command(sql_parse.cc:965),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    2 rand_bytes,tls1_enc,do_ssl3_write,ssl3_write_bytes,SSL_write,vio_ssl_write(viossl.c:225),net_write_raw_loop(net_serv.cc:500),net_write_packet(net_serv.cc:500),net_flush(net_serv.cc:222),net_send_ok(protocol_classic.cc:369),Protocol_classic::send_eof(protocol_classic.cc:668),THD::send_statement_status(sql_class.cc:4714),dispatch_command(sql_parse.cc:1925),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    2 pthread_rwlock_unlock(libpthread.so.0),CRYPTO_THREAD_unlock,rand_bytes,tls1_enc,do_ssl3_write,ssl3_write_bytes,SSL_write,vio_ssl_write(viossl.c:225),net_write_raw_loop(net_serv.cc:500),net_write_packet(net_serv.cc:500),net_flush(net_serv.cc:222),net_send_ok(protocol_classic.cc:369),Protocol_classic::send_eof(protocol_classic.cc:668),THD::send_statement_status(sql_class.cc:4714),dispatch_command(sql_parse.cc:1925),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    1 write(libpthread.so.0),sock_write,BIO_write,ssl3_write_pending,do_ssl3_write,ssl3_write_bytes,SSL_write,vio_ssl_write(viossl.c:225),net_write_raw_loop(net_serv.cc:500),net_write_packet(net_serv.cc:500),net_flush(net_serv.cc:222),net_send_ok(protocol_classic.cc:369),Protocol_classic::send_eof(protocol_classic.cc:668),THD::send_statement_status(sql_class.cc:4714),dispatch_command(sql_parse.cc:1925),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)

此时大部分线程都在读写过程中,perf数据:

可见之前的瓶颈已经降低很多了。测试得到oltp_point_select的TPS为336229.14,性能下降30.95%,与yaSSL的性能下降值26.03%相比略高。下表是短连接测试数据:

不启用SSL大约为用OpenSSL库启用SSL每秒访问数的4.5倍,而yaSSL这个数字则为7.6倍,显然OpenSSL的性能在这种场景下比yaSSL有很大提高。

2 透明加密测试组

下表为透明加密测试数据:

总体看,启用yaSSL透明加密时TPS都会下降。oltp_delete、oltp_insert、oltp_update_index、oltp_update_non_index、oltp_write_only场景比不加密情况性能大约低40%,oltp_point_select、oltp_read_only场景比不加密情况性能大约低20%。其中oltp_read_write场景、select_random_points场、select_random_ranges场景与bulk_insert场景加密与不加密相比差距不大。需要具体分析原因。

首先查看oltp_read_write场景的CPU利用率和IO情况,如下图:

从CPU利用率看,加密比不加密使用率有大幅提高,但依然没到100%。从IO看两者速度虽有差异,但利用率都接近100%,IO应该处于压满状态,变化不大。执行命令pt-pmp -p得到数据:

    Tue Jul  3 12:48:48 CST 2018
    7 __io_getevents_0_4,LinuxAIOHandler::collect(os0file.cc:2500),LinuxAIOHandler::poll(os0file.cc:2646),os_aio_linux_handler(os0file.cc:2702),os_aio_handler(os0file.cc:2702),fil_aio_wait(fil0fil.cc:5906),io_handler_thread(srv0start.cc:311),start_thread(libpthread.so.0),clone(libc.so.6)
    6 pthread_cond_wait,native_cond_wait(thr_cond.h:140),my_cond_wait(thr_cond.h:140),inline_mysql_cond_wait(thr_cond.h:140),Stage_manager::enroll_for(thr_cond.h:140),MYSQL_BIN_LOG::change_stage(binlog.cc:8655),MYSQL_BIN_LOG::ordered_commit(binlog.cc:9056),MYSQL_BIN_LOG::commit(binlog.cc:8330),ha_commit_trans(handler.cc:1795),trans_commit(transaction.cc:239),mysql_execute_command(sql_parse.cc:4354),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    5 pthread_cond_wait,native_cond_wait(thr_cond.h:140),my_cond_wait(thr_cond.h:140),inline_mysql_cond_wait(thr_cond.h:140),Stage_manager::enroll_for(thr_cond.h:140),MYSQL_BIN_LOG::change_stage(binlog.cc:8655),MYSQL_BIN_LOG::ordered_commit(binlog.cc:9125),MYSQL_BIN_LOG::commit(binlog.cc:8330),ha_commit_trans(handler.cc:1795),trans_commit(transaction.cc:239),mysql_execute_command(sql_parse.cc:4354),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    4 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),wait(ut0mutex.ic:89),spin_and_try_lock(ut0mutex.ic:89),enter(ut0mutex.ic:89),enter(ut0mutex.ic:89),buf_LRU_buf_pool_running_out(ut0mutex.ic:89),row_ins_sec_index_entry_low(row0ins.cc:3168),row_ins_sec_index_entry(row0ins.cc:3420),row_ins_index_entry(row0ins.cc:3451),row_ins_index_entry_step(row0ins.cc:3451),row_ins(row0ins.cc:3451),row_ins_step(row0ins.cc:3451),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1749),row_insert_for_mysql(row0mysql.cc:1873),ha_innobase::write_row(ha_innodb.cc:7630),handler::ha_write_row(handler.cc:7976),write_record(sql_insert.cc:1871),Sql_cmd_insert::mysql_insert(sql_insert.cc:769),Sql_cmd_insert::execute(sql_insert.cc:3103),mysql_execute_command(sql_parse.cc:4945),Prepared_statement::execute(sql_prepare.cc:3935),Prepared_statement::execute_loop(sql_prepare.cc:3543),mysqld_stmt_execute(sql_prepare.cc:2549),dispatch_command(sql_parse.cc:1437),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    3 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),TTASEventMutex::wait(ut0mutex.ic:89),spin_and_try_lock(ib0mutex.h:850),enter(ib0mutex.h:850),PolicyMutex<TTASEventMutex<GenericPolicy>(ib0mutex.h:850),buf_page_io_complete(buf0buf.cc:5831),fil_aio_wait(fil0fil.cc:5940),io_handler_thread(srv0start.cc:311),start_thread(libpthread.so.0),clone(libc.so.6)

显然瓶颈在提交binlog上,将binglog日志关闭(注释掉log-bin),重启mysqld测试发现TPS提升约10%。再执行pt-pmp -p察看数据,此时瓶颈在执行读写操作时涉及到的insert buffer页面锁。设置innodb_change_buffering=none,关闭此功能,重启mysqld再次执行发现性能下降25%左右。此时发现瓶颈都是IO了。总体来看这个场景瓶颈在于IO,不加密状态CPU本身使用率并不高,加密后只是将CPU利用率提高了,并没有改变瓶颈,所以加密状态的TPS变化不大。

其次分析select_random_points场景的CPU利用率和IO情况,如下图:

从IO可以看出,主要执行过程中基本没有IO进行,怀疑操作过程中可能一直使用的buffer中的数据,在执行过程中使用命令查看buffer命中情况:

$ mysql> show engine innobase status;

查看到具体信息:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 8795455488
Dictionary memory allocated 315349
Buffer pool size   524224
Free buffers       2969
Database pages     515364
Old database pages 190077
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 5433583, not young 935378889
0.00 youngs/s, 0.00 non-youngs/s
Pages read 70941635, created 32975923, written 55885804
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 515364, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

确认了该场景使用的buffer数据,没有进行IO读取。CPU使用率基本没有变化,一直是压满了。根据透明加密设计原理,这个场景不会有加解密的操作。总体上应该不会对TPS有影响。

select_random_ranges这个场景与select_random_points的情况一样,总体上应该不会对TPS有影响。

bulk_insert这个场景的CPU利用率和IO情况,如下图:

这个场景CPU是压满的,io在加密和不加密都基本一样,也是满负荷了。察看perf数据:

执行pt-pmp -p命令数据如下:

    Mon Jul  2 17:33:00 CST 2018
    17 ut_delay(libc.so.6),rw_lock_x_lock_func(sync0rw.cc:751),pfs_rw_lock_x_lock_func(sync0rw.ic:705),btr_search_x_lock(sync0rw.ic:705),btr_search_update_hash_on_insert(sync0rw.ic:705),btr_cur_optimistic_insert(btr0cur.cc:3272),row_ins_clust_index_entry_low(row0ins.cc:2604),row_ins_clust_index_entry(row0ins.cc:3319),row_ins_index_entry(row0ins.cc:3449),row_ins_index_entry_step(row0ins.cc:3449),row_ins(row0ins.cc:3449),row_ins_step(row0ins.cc:3449),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1749),row_insert_for_mysql(row0mysql.cc:1873),ha_innobase::write_row(ha_innodb.cc:7630),handler::ha_write_row(handler.cc:7976),write_record(sql_insert.cc:1871),Sql_cmd_insert::mysql_insert(sql_insert.cc:769),Sql_cmd_insert::execute(sql_insert.cc:3103),mysql_execute_command(sql_parse.cc:4945),mysql_parse(sql_parse.cc:5740),dispatch_command(sql_parse.cc:1503),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    10 __io_getevents_0_4,LinuxAIOHandler::collect(os0file.cc:2500),LinuxAIOHandler::poll(os0file.cc:2646),os_aio_linux_handler(os0file.cc:2702),os_aio_handler(os0file.cc:2702),fil_aio_wait(fil0fil.cc:5906),io_handler_thread(srv0start.cc:311),start_thread(libpthread.so.0),clone(libc.so.6)
    7 ut_delay(libc.so.6),rw_lock_x_lock_func(sync0rw.cc:751),pfs_rw_lock_x_lock_func(sync0rw.ic:705),btr_search_x_lock(sync0rw.ic:705),btr_search_update_hash_node_on_insert(sync0rw.ic:705),btr_cur_optimistic_insert(btr0cur.cc:3270),row_ins_clust_index_entry_low(row0ins.cc:2604),row_ins_clust_index_entry(row0ins.cc:3319),row_ins_index_entry(row0ins.cc:3449),row_ins_index_entry_step(row0ins.cc:3449),row_ins(row0ins.cc:3449),row_ins_step(row0ins.cc:3449),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1749),row_insert_for_mysql(row0mysql.cc:1873),ha_innobase::write_row(ha_innodb.cc:7630),handler::ha_write_row(handler.cc:7976),write_record(sql_insert.cc:1871),Sql_cmd_insert::mysql_insert(sql_insert.cc:769),Sql_cmd_insert::execute(sql_insert.cc:3103),mysql_execute_command(sql_parse.cc:4945),mysql_parse(sql_parse.cc:5740),dispatch_command(sql_parse.cc:1503),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    5 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),rw_lock_x_lock_func(sync0rw.cc:795),pfs_rw_lock_x_lock_func(sync0rw.ic:705),btr_search_x_lock(sync0rw.ic:705),btr_search_update_hash_on_insert(sync0rw.ic:705),btr_cur_optimistic_insert(btr0cur.cc:3272),row_ins_clust_index_entry_low(row0ins.cc:2604),row_ins_clust_index_entry(row0ins.cc:3319),row_ins_index_entry(row0ins.cc:3449),row_ins_index_entry_step(row0ins.cc:3449),row_ins(row0ins.cc:3449),row_ins_step(row0ins.cc:3449),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1749),row_insert_for_mysql(row0mysql.cc:1873),ha_innobase::write_row(ha_innodb.cc:7630),handler::ha_write_row(handler.cc:7976),write_record(sql_insert.cc:1871),Sql_cmd_insert::mysql_insert(sql_insert.cc:769),Sql_cmd_insert::execute(sql_insert.cc:3103),mysql_execute_command(sql_parse.cc:4945),mysql_parse(sql_parse.cc:5740),dispatch_command(sql_parse.cc:1503),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)
    5 pthread_cond_wait,wait(os0event.cc:165),wait_low(os0event.cc:165),os_event_wait_low(os0event.cc:165),sync_array_wait_event(sync0arr.cc:475),rw_lock_x_lock_func(sync0rw.cc:795),pfs_rw_lock_x_lock_func(sync0rw.ic:705),btr_search_x_lock(sync0rw.ic:705),btr_search_update_hash_node_on_insert(sync0rw.ic:705),btr_cur_optimistic_insert(btr0cur.cc:3270),row_ins_clust_index_entry_low(row0ins.cc:2604),row_ins_clust_index_entry(row0ins.cc:3319),row_ins_index_entry(row0ins.cc:3449),row_ins_index_entry_step(row0ins.cc:3449),row_ins(row0ins.cc:3449),row_ins_step(row0ins.cc:3449),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1749),row_insert_for_mysql(row0mysql.cc:1873),ha_innobase::write_row(ha_innodb.cc:7630),handler::ha_write_row(handler.cc:7976),write_record(sql_insert.cc:1871),Sql_cmd_insert::mysql_insert(sql_insert.cc:769),Sql_cmd_insert::execute(sql_insert.cc:3103),mysql_execute_command(sql_parse.cc:4945),mysql_parse(sql_parse.cc:5740),dispatch_command(sql_parse.cc:1503),do_command(sql_parse.cc:1023),handle_connection(connection_handler_per_thread.cc:309),pfs_spawn_thread(pfs.cc:2188),start_thread(libpthread.so.0),clone(libc.so.6)

发现场景的瓶颈主要是在锁上。这个锁是innodb的一个功能Adaptive Hash Index。关闭innodb_adaptive_hash_index参数或者设置innodb_adaptive_hash_index_parts=64,测试可以发现TPS增长到685541.92。此时可以发现瓶颈为将小事务日志写入重做日志缓冲区时的加锁(log_sys->mutex)过程。加密过程引起的降低不是主要瓶颈,所以最后表现为加密和不加密在这个场景的TPS变化不大。

对比OpenSSL与yaSSL的情况,总体上OpenSSL相对yaSSL来说都有较大幅度的性能提升。oltp_delete、oltp_insert、oltp_update_index、oltp_update_non_index、oltp_write_only场景OpenSSL加密相比yaSSL加密性能大约能提升40%,oltp_point_select、oltp_read_only、oltp_read_write场景OpenSSl加密相比yaSSL大约能提升20%性能,其他场景则差别不大。

select_random_points、select_random_ranges、bulk_insert场景已分析过,使用OpenSSL或者yaSSL都跟不使用加密TPS相差不大;oltp_read_write场景之前分析的瓶颈主要是在binlog、insert buffer页面锁以及io上,加解密应该影响不大,但数据显示使用OpenSSL加密的性能明显比使用yaSSL以及不使用加密的情况高,需要再分析下。

通过pt-pmp工具输出堆栈,可以确认两者在堆栈上没有明显区别,基本上都在读取数据页面。查看perf数据,不加密情况:

OpenSSL加密情况:

显然,OpenSSL加密情况下,降低了锁冲突,最后性能反而有所提升。

总结

总体上看SSL加密会导致性能损失,使用yaSSL库会导致性能有较大下降,而使用OpenSSL库性能下降幅度远低于yaSSL,与不使用SSL的性能差别不大,同时使用OpenSSL 1.1版本的库又比使用OpenSSL 1.0版本的库性能要高一些。

在SSL连接测试组中,大部分场景中,配置yaSSL或OpenSSL进行SSL连接与不配置SSL的性能在TPS表现差别不大;在部分测试场景(oltp_point_select、oltp_read_only、oltp_read_write、短连接)中,配置yaSSL或OpenSSL进行SSL连接性能下降较大。大多数情况(oltp_read_only、oltp_read_write、短连接)OpenSSL优于yaSSL;oltp_point_select场景下OpenSSL1.0版本性能明显低于yaSSL,但OpenSSL1.0版本性能与yaSSL相差不大。

在透明加密测试组中,大部分场景(oltp_delete、oltp_insert、oltp_update_index、oltp_update_non_index、oltp_write_only)配置yaSSL加密比不加密情况性能大约低40%,oltp_point_select、oltp_read_only场景yaSSL加密比不加密情况性能大约低20%;少部分场景(oltp_read_write、select_random_points、select_random_ranges、bulk_insert)yaSSL加密与不加密相比差距不大;配置OpenSSL加密比不加密情况总体差别不大,甚至还略有上升,尤其是oltp_read_write场景;总体上看配置OpenSSL加密比配置yaSSL加密性能有大幅提升。

原文发布于微信公众号 - 腾讯数据库技术(gh_83eebc796d5d)

原文发表时间:2018-11-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mathor

HackingLab的一套渗透测试题

 Hackinglab是一个在线网络信息安全攻防平台,里面有很多题,我随便做里面一套题,算是这两天学渗透的一个总结,题目地址

6034
来自专栏玄魂工作室

CTF实战23 木马攻击技术

值得注意的是,木马屠城记并非于古希腊诗人荷马的两部著作伊利亚特与奥德赛里记载,而是在罗马帝国时期的诗人维吉尔所写的史诗《埃涅阿斯纪》中, 才第一次被记载

1422
来自专栏Web 开发

iOS开发者证书-2015年中文版

我们都知道,制作一款iOS的App需要iOS的开发者证书。在Apple的开发者网站上面,有一个栏目是‘Certificates, Identifiers & P...

750
来自专栏FreeBuf

快速读懂无线安全

* 本文原创作者:icecolor不疯不魔不成活,本文属FreeBuf原创奖励计划,未经许可禁止转载 About channel: ? 1.每个协议都有不同的工...

33910
来自专栏黑白安全

短信轰炸剖析

在互联网中,由于越来越多的平台在注册会员,找回密码,以及手机支付的时候,为了防止他人冒用,恶意盗号,资金的安全往往都会使用短信验证码来验证,从而提升帐号的安全性...

1.4K4
来自专栏FreeBuf

“奇幻熊”(APT28)组织最新攻击

近日腾讯御见威胁情报中心在监测Fancy Bear“奇幻熊”组织的攻击活动过程中,发现了其使用的最新攻击样本。下文将详细披露该组织的攻击手法,和各企业一起共同抵...

2768
来自专栏散尽浮华

Linux下防御DDOS攻击的操作梳理

DDOS的全称是Distributed Denial of Service,即"分布式拒绝服务攻击",是指击者利用大量“肉鸡”对攻击目标发动大量的正常或非正常请...

1.5K8
来自专栏编程思想之路

Android7.1.1系统设置默认值大全

1,是否有默认值 在寻找一个开关的默认值时,首先要明白一点,该开关是否存在默认值,以及该开关状态是否有状态保存(一般状态存储在settings的db中)。 ...

66010
来自专栏FreeBuf

深入了解VoWiFi安全性

T-mobile开创了智能手机嵌入原生无缝支持WiFi调用的技术。这种集成WiFi调用功能的技术与当今大部分智能手机供应商所采用的方案一样。T-mobile在2...

21410
来自专栏嵌入式程序猿

不仅仅是一个S

超级Plus长假就要结束了,不管你假期过得怎么样,明天都要收拾行囊上路,友情提醒,早点出门,避开高峰,注意安全. 不但我们要注意安全,http也要注意安全。 不...

3537

扫码关注云+社区

领取腾讯云代金券