70

Qunar高速发展下数据库的创新与发展 - InnoDB memcached篇

 6 years ago
source link: http://mp.weixin.qq.com/s/BwP1AkeU4DhRGgAtdyl2tQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Qunar高速发展下数据库的创新与发展 - InnoDB memcached篇

Original 孙凯 Qunar技术沙龙 2017-12-15 00:14 Posted on

Image

平台事业部DBA,主要负责支付和金融部门MySQL数据库运维。同时也负责公司dubai平台和高可用中间件的开发工作。

1. InnoDB memcached 背景

一般应用为了降低响应时间,提升性能,往往在 DB 层和业务层增加缓存机制(例如传统 memcached,以及 Redis),从而减轻数据库负载,提高响应速度。如下图所示。

Image

这种架构存在的问题是 RDBMS 和缓存的数据一致性需要应用程序保证。而且如果缓存数据命中率低或者出现故障时,请求可能直接打到 DB 层,导致 DB 过载。此外,因为 Redis 等缓存的存储容量受限于内存,因此在业务要求存储数据量较大时,基于内存的缓存机制往往成本高昂或无法满足业务存储容量需求。我们就是在安全中心业务数据量不断增长(已经将近 100G,并且会持续增长),Redis 已经无法很好的满足存储需求的背景下,开始调研使用 InnoDB memcached。

 MySQL InnoDB MemCached Plugin(IMC),提供了一个集成的,存在于 mysqld 中的 memcached 守护程序 daemonmemcached。它可以直接通过 set,get 命令自动存储或者从 InnoDB 表中检索数据,将 MySQL 服务器变成一个快速的 “键值存储”,从而减少因为 sql 解析和优化造成的性能损失,因为数据可以直接落地到 InnoDB 表中(存储策略为 innodbonly),因此存储容量不再受限于内存大小。此外,IMC 在兼容 MC 协议和 key-value 操作的同时,还可以通过 SQL 访问 InnoDB 表来处理更加复杂的报表、统计查询。其体系架构如下图所示:

2. InnoDB memcached 与现有存储方案比较

在去哪儿的 DBA 团队,主要有三种数据存储方案,分别是 HBase、MySQL 和 Redis。 HBase 主要用来进行大数据量的存储,响应时间较长,这里不在进行比较讨论。 MySQL 是目前公司最主要的存储方案,适用于大部分的业务场景,但因为 MySQL Server 层要对 SQL 语句进行解析和执行方案优化等操作,会耗费一定的时间,不能很好的满足部分对响应时间特别敏感的业务,而 InnoDB memcached 可以直接通过 InnoDB 存储引擎层接口,读取或存储数据,从而降低响应时间。为了对比两者性能差异,编写测试代码读写远程 MySQL 和 InnoDB memcached(key:32 字节,value:128 字节,横轴为线程数,纵轴为 QPS)进行对比:   客户端机器配置:     CPU:2.7 GHz Intel Core i5     内存:8G     操作系统:macOS 10.13.1   服务端配置:     磁盘:3.2T (Shannon 卡)     内存大小:126G     操作系统:CentOS 7.2     服务器型号: HP - ProLiant DL360 Gen9     CPU: Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz(x8664)     CPU 核数:32     innodbbufferpoolsize: 24G     memcached 内存: 16G

  • 100% 读测试

  • 100% 写测试

  • 9:1 读写测试

通过对比可以发现,对于写操作 MySQL 和 IMC 性能基本一致,读性能随着量增加,IMC 的读 QPS 比 MySQL 高出 50%。 对于 Redis,我们公司目前主要用于缓存和存储两种方式,其主要优点为:支持丰富数据类型;支持事务,操作都是原子性;可以持久化其数据;但在应用过程中,有些需要存储大量数据的场景,这种情况使用 Redis 就会耗费大量内存导致成本过高,甚至单机内存无法满足存储需求的情况。性能方面,因为 Redis 读写数据都在内存中,可以达到很高的吞吐量。使用 redis-benchmark 工具测试 Redis 性能情况(配置同上服务端配置,分配内存大小为 16G):(提示:以下代码均可左右滑动)



  1. #操作次数1000000,value大小为1024字节

  2. redis-benchmark -n 1000000 -d 1024

部分测试结果如下:



  1. ====== SET ======

  2.  1000000 requests completed in 9.59 seconds

  3.  50 parallel clients

  4.  1024 bytes payload

  5.  keep alive: 1

  6. 100.00% <= 0 milliseconds

  7. 104231.81 requests per second

  8. ====== GET ======

  9.  1000000 requests completed in 8.83 seconds

  10.  50 parallel clients

  11.  1024 bytes payload

  12.  keep alive: 1

  13. 100.00% <= 0 milliseconds

  14. 113237.45 requests per second

对比 3.3 节 IMC 性能测试,可以发现因为基于内存,Redis 写性能较 IMC innodb_only 存储策略时快很多,读的速度与 IMC 基本一致。 通过上面的讨论对比,可以发现 IMC 属于 MySQL 和 Redis 在性能和存储容量两者间的折中,支持数据类型比较单一,操作简单,读性能较 MySQL 有较大提升,写性能相比于 Redis 较低,存储容量不再受限于内存大小,推荐在数据量较大,读比重高,对响应时间比较敏感的业务使用。

目前因为 Redis 无法很好的满足存储容量需求 (数据量超过 100G),线上有两个业务使用 IMC:安全中心的用户信息存储和研发中心广告用户标签业务。前者业务机器与 IMC 都在 cn1 机房,读写响应时间基本在 1ms 以内;后者业务在 cn5,IMC 在 cn2 机房,响应时间基本在 5ms 以内,监控信息如下图。在实际使用过程中响应时间会有抖动,特别是跨机房时,偶尔会有响应时间超过 10ms 的情况,而且如果在读写数据比较集中时,会因为锁等待导致响应变慢。

  • 广告用户标签(蓝线为QPS,黑线为时间)

3. InnoDB memcached 使用

下面简单介绍下 IMC 的搭建配置,以及我们性能测试情况。

3.1 InnoDB memcached 搭建
  • 初始化daemon_memcached plugin



  1. # MYSQL_HOME 为MySQL安装目录

  2. # 脚本会创建innodb_memcache库,并新建IMC用到的三张配置表

  3. # cache_policies,config_options,containers

  4. # 此外,还会在test库下创建demo_test表作为样例

  5. mysql> source MYSQL_HOME/share/innodb_memcached_config.sql

  • 安装 daemon_memcached plugin



  1. # 安装IMC插件

  2. INSTALL PLUGIN daemon_memcached soname "libmemcached.so";

如果安装正常的话,就可以直接在 shell 下,使用 telnet 命令连接 memcached



  1. # memcached daemon 默认监听11211端口

  2. telnet localhost 11211

  3. Trying 127.0.0.1...

  4. Connected to localhost.

  5. Escape character is '^]'.

  6. # 获取key为AA对应的value(为innodb_memcached_config.sql创建的数据), aaa为表空间名

  7. get @@aaa.AA

  8. VALUE @@aaa.AA 8 12

  9. HELLO, HELLO

  10. END

3.2 InnoDB memcached 配置

通过配置参数和修改配置表数据,可以调整 IMC 的存储策略及其他一些特性。

3.2.1 IMC 主要参数
2.2.2 IMC 配置表

innodbmemcachedconfig.sql 在 innodbmemcache 库里创建了三张配置表:cachepolicies,config_options,containers 。各个表的具体具体功能如下:

  • cache_policies表:



  1. mysql> select * from cache_policies\G;

  2. *************************** 1. row ***************************

  3.  policy_name: cache_policy

  4.   get_policy: innodb_only

  5.   set_policy: innodb_only

  6. delete_policy: innodb_only

  7. flush_policy: innodb_only

通过配置 cache_policies 数据,Innodb Memcached 可以针对不同命令设置不同策略:

innodbonly: 只从 InnoDB 表中获取,存储数据 cacheonly:只从缓存中获取数据 ,memcached 引擎作为数据存储 , 相当于传统 memcached caching: 当缓存不存在 KEY 时则在 InnoDB 表中搜索 KEY,InnoDB 和 memcached 引擎作为数据存储(如果数据量超过 IMC 设置的内存大小,则可能会出现 out of memory storing object 错误) disabled:禁用对应命令

  • containers 表:



  1. mysql> select * from containers\G;

  2. *************************** 1. row ***************************

  3.                  name: aaa          

  4.             db_schema: test

  5.              db_table: demo_test

  6.           key_columns: c1

  7.         value_columns: c2

  8.                 flags: c3

  9.            cas_column: c4

  10.    expire_time_column: c5

  11. unique_idx_name_on_key: PRIMARY

containers 表主要配置 memcached 与表的映射关系,每增加一个表,就要在 containers 表中插入一条数据,配置映射的表空间名以及列信息:

name: 表空间名,用户通过表空间名将操作映射到不同表 get @@tablespace.key(例如 2.1 节的 get @@aaa.AA) flags: 可以用来标记信息,只能是整数类型 , 如果 value 映射多列,可以通过 flags 指定 incr, prepend 命令操作的列 keycolumns: memcached 强制要求 key 不能超过 250 个字符,对应列必须为 non-null char 或者 varchar valuecolumns: 必须是 char,varchar,blob 类型,没有长度限制,可以为 null,可以映射多列,memcached 存储数据时会依据 configoptions 表中的 separator 将 value 值划分到表的对应列。 cascolumn: 相当于一个版本号,每次写操作都会更新这个版本号 expiretimecolumn: 超时时间,单位为秒,设置为 0 时表示不超时 uniqueidxnameonkey: key 列对应的索引名

  • config_options 表:



  1. mysql> select * from config_options;

  2. +---------------------+-------+

  3. | name                | value |

  4. +---------------------+-------+

  5. | separator           | |     |

  6. | table_map_delimiter | .     |

  7. +---------------------+-------+

  config_options 表设置与 memcached 相关的选项:

spearator:当 memcached 的 value 对应表的多列时,字符串会以 spearator 为分隔符,将 value 划分到不同列 tablemapdelimiter:表空间名和 key 值分隔符,例如 @@t1.some_key

注意: 对这三个表修改后,只有重新安装 memcached 插件后才能生效



  1. UNINSTALL PLUGIN daemon_memcached;

  2. INSTALL PLUGIN daemon_memcached soname "libmemcached.so";

3.3 InnoDB memcached 性能测试

使用 memcached 测试工具 memslap 进行性能测试 测试环境与第 2 章中服务端配置相同

  • 100% SET 测试,key: 20字节,value: 1024字节

  • 100% GET 测试,key: 20字节,value: 1024字节(innodbonlySSD为测试前重启实例,避免数据缓存在内存中,innodbonlybuffer为数据缓存在内存中的情况)

  • 针对安全中心业务的使用场景进行读写混合测试(读写比9:1,key:32字节,value:128字节)

对比以上测试结果可以发现,IMC 的 cacheonly 策略性能优于传统 memcached,而 caching,innodbonly 存储策略因为要将数据落盘,性能下降较大,但依然可以达到很高的 qps,可以满足大部分业务需求。而且读取的数据如果为热点数据的话,即使是 innodbonly 存储策略,数据也会缓存在 innodb buffer 中,基本可以达到与 cacheonly 相似的性能。适用于传统缓存无法满足存储量,而关系型数据库响应速度又无法达到业务需求(特别是读操作比重较多)的应用场景。

4. InnoDB memcached 高可用

IMC 可以通过设置 innodbapienable_binlog=1,使 IMC 的写操作产生对应的 binlog,进而可以通过 MySQL 复制来实现备份和高可用。IMC 集群高可用架构与去哪儿 QMHA 架构类似,架构如下:

IMC 集群由一个主节点,至少一个从节点组成,主节点对外提供 memcached 服务,从节点只作为备份以及 failover 使用。哨兵集群由五台分布在各个机房的节点组成,五个节点同时监控 MySQL 实例的状态,如果超过半数节点检测到 MySQL 实例挂掉,则哨兵修改配置中心数据,标记该节点 problem,之后哨兵更新 zk 集群状态,java 客户端监测到 zk 变化后从配置中心读取更新后的节点信息,如果写节点发生变化,则新建对新节点的连接,并关闭旧节点的连接。连接数为 10 时,测试 switchover 时间为 2s 左右,failover 时间为 9s 左右。

Image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK