应用场景
在很多业务场景比如反欺诈、广告定向推荐、数字身份验证等,这些场景都有一些共同的特点:
- 读多于写
- 随机读
- 延迟低
数据量不大时,有很多优秀的框架可以使用,比如单机的redis、Cassandra等,它们不但满足上述需求而且还有着易于运维、管理方便的优点,但随着业务规模扩大,不可预测的大流量、查询延时低效都成为了比较难解决的痛点。
Aerospike在2012年作为分布式KV数据库出现后,以稳定性和延迟低的特点让不少公司开始试水,到如今4.0版本发布,6年时间里Aerospike已经积累了不少在不同行业的成功案例。
数据模型
我理解在Aerospike的Data model其实和Hbase中的namespace/table/row/column family非常类似。
- namespace
- namespace是最高层级的一个容器概念,决定了这个容器中的数据的存储方式,有着如下的配置
- 如何存储,可以选择全部存储到DRAM或者SSD上
- replica复制因子,决定了这个namespace的高可用性
- expire TTL
- sets
- sets是可选项,数据存储时可以指定set也可以不指定,在set中可以设置基于set的二级索引
- records
- record就是一行记录了,包括:
- key
- metadata(版本号(version), ttl, last-update-time(lut))
- bins
- record就是一行记录了,包括:
- bins
- 包括name和value(类似列名和值)
查询索引
Aerospike中的查询索引分为两种,一级索引和二级索引,两种索引的用途各不相同。
- 一级索引(Primary-Index)
- Primary-Index是Aerospike默认存在的,作用是加速查询和防止数据倾斜,具体原理是取每一个key做hash后,前12bit作为partitionID,所以partition的个数是固定的,4096个。
- 二级索引(Secondary-Index)
- Secondary-Index和关系型数据库中的索引类似,基于bin而存在,但其索引后的值是当前节点的partitionId列表,也就是说,即使命中了二级索引,还是要scan相应partition list中的每一行记录,效率并不高。需要注意的是,在生成Secondary-Index的过程,Aerospike需要扫描所有的数据,所以要在low load的时候做这样的操作。
一致性和高可用分析
我们假设在单namespace的情况下,当前Aerospike集群为4个节点,每个节点有1024个partition,replica复制因子为1,探讨常见的以下几种场景:
- 在一个节点宕机的情况下,其replica的节点从replica变成了master,并开始寻找新的replica节点,数据不会发生丢失。
- 在两个节点宕机的情况下,如果两个节点正好是partition的replica和master,数据丢失,可靠性无法保证。
- 在一个节点宕机后重启时,由于在内存中的index丢失,需要重新scan整个SSD来重建索引(非常耗时),整个集群开始重新rebalance,相应partition的数据从其他节点复制到新节点中,直到新节点ready之后再加入集群,数据不会丢失。
选型建议
KV数据库有很多,但大多数都是在Speed和Scale上来做取舍,根据别人的一些选型经验,总结出了其他几个存储和Aerospike对比的一些劣势。
- MongoDB、Redis这种需要内存的代价过高,无法做到低成本地快速Scale,且无法应对高峰流量。
- Couchbase性能很好,但是不支持udf。
- Cassandra在大数据量下无法保证低延迟。
不足之处
虽然Aerospike有稳定性好、延迟低、性价比高的特点,但是也有一些不足的地方需要注意的:
- Aerospike Rolling Start时间过长(scan整个SSD重建索引)
- 无法支持复杂的数据类型,例如hyperloglog
- 每个record不能超过1MB
- 在做rebalance过程中,响应会有所抖动