1. xcache是什么
xcache是由喜马拉雅系统架构团队基于开源项目codis,redis和pika深度定制开发的一套分布式KV持久化存储系统。该系统主要有以下几个特点:
- 完全支持redis协议,用户不需要修改任何代码,就可以将服务迁移至xcache
- 数据存储在磁盘上,解决了redis由于存储数据量巨大而导致内存容量瓶颈的问题
- 集群化部署,支持高并发,高可用,弹性伸缩容
PS:由于xcache对数据做了分片,所以有些redis原生的命令无法支持,具体请参考《xcache不支持命令列表》。
ps: pika使用手册(用户篇)
2. xcache整体架构
xcache的整体架构和codis-redis架构保持一致,最主要的区别是将codis-server组件替换成了pika组件,如下图:
在pika组件中,我们引入了一个缓存层(MEM-cache,该模块是基于redis实现),当存在冷热数据时,可以缓存热key到内存中,从而提高QPS以及降低命令延时。整体的命令调用流程如下:
3. xcache有什么特点
3.1 支持大value存储
xcache底层存储引擎支持string数据类型的kv分离存储,在value较大时,可以有效降低LSM的写放大问题,从而降低磁盘IO,减少命令延时。下图是我们对线上存储大value服务优化的效果。
kv分离存储前
kv分离存储后
优化前每天有10w左右的300ms超时报警,优化后每天1000左右,降低99%以上。
3.2 支持缓存热key
早期xcache的数据都是存储在磁盘上,这样就造成了内存的浪费。本着对资源充分利用的目的,xcache引入了一个缓存层,该模块是基于redis实现,支持动态开关。测试缓存命中时,可以大大提升QPS,并且降低访问延时,吞吐量测试数据如下:
缓存命中时,QPS大概提升了50%左右。
3.3 新增ehash数据类型
ehash是一种可为field设置过期时间的hash类型数据结构。支持和redis hash一样丰富的数据接口,极大地提高了hash数据结构的灵活性,简化了很多场景下的业务开发工作。
主要特性:
- field支持单独设置过期时间
- field过期后支持高效删除
- 使用语法和原生redis hash数据类型类似
3.4 支持zset数据元素个数限长
xcache支持设置zset存储的最大元素个数,当超过用户设置的最大元素个数时,可以自动清理zset中不需要的数据,非常适合只保存定量历史数据的业务场景。
主要特性:
- 支持设置zset保存的最大元素个数
- 支持头部和尾部删除策略
- 支持动态设置执行删除任务周期,错峰删除,避免影响线上业务
- 支持手动执行删除任务
3.5 支持快慢命令分离
xcache支持将快命令和慢命令分离执行,这样可以有效降低命令之间的相互影响,避免执行较慢的命令阻塞执行较快的命令。下图是测试set和zadd命令,设置set为快命令,zadd为慢命令。set命令QPS为1w,zadd命令QPS为2w。
set命令延时
zadd命令延时
可以看出快慢命令分离前,set和zadd的延时毛刺都差不多,因为zadd和set命令在相同的执行队列中,zadd会阻塞set命令的执行。快慢命令分离后,zadd命令不会阻塞set命令,所以set的延时毛刺降低了很多,从200ms降低到了20ms左右,降低了90%。
4. xcache和redis性能对比
4.1 配置
CPU: 48核,Intel(R) Xeon(R) Gold 6126 CPU @ 2.60GHz
内存:128G
磁盘:1.5T(NVMe SSD)
OS:CentOS Linux release 7.7.1908 (Core)
4.2 测试过程
key长度:20字节
value长度:100字节(随机字符串)
redis数据容量大小:20G (string,list,hash,zset各5G)
xcache数据容量大小:400G(string,list,hash,zset各100G)
PS:考虑到pika底层hash结构和set结构存储协议一致,所以没有测试set数据类型。
4.3 测试结果
正常压力(每种命令测试1小时,并进行限速)
redis | xcache | ||||
操作 | QPS | tp9999 | tp100 | tp9999 | tp100 |
GET | 10w | <10ms | <30ms | <25ms | <40ms |
SET | 5w | <12ms | <25ms | <40ms | <60ms |
GET和SET混合 | get:8w set:2w | <30ms | <40ms | <40ms | <100ms |
HGET | 10w | <15ms | <40ms | <30ms | <40ms |
HSET | 5w | <12ms | <30ms | <60ms | <150ms |
LINDEX | 10w | <12ms | <35ms | <25ms | <40ms |
LRANGE | 5w | <15ms | <35ms | <30ms | <45ms |
LPOP | 5w | <10ms | <25ms | <40ms | <180ms |
LPUSH | 5w | <12ms | <30ms | <40ms | <100ms |
ZRANGE | 5w | <20ms | <35ms | <20ms | <38ms |
ZRANGEBYSCORE | 5w | <20ms | <35ms | <20ms | <40ms |
ZADD | 2w | <25ms | <25ms | <90ms | <300ms |
最大吞吐量测试
操作 | Redis 最大QPS | Xcache 最大QPS |
GET | 15w | 20w |
SET | 13w | 25w |
HGET | 14w | 20w |
HSET | 13w | 15w |
LINDEX | 15w | 20w |
LRANGE | 13w | 14w |
LPOP | 9.5w | 14w |
LPUSH | 10w | 19w |
ZRANGE | 10w | 20w |
ZRANGEBYSCORE | 10w | 18w |
ZADD | 9.5w | 12w |
4.4 结论
- 正常压力下,redis的tp9999在10ms左右,xcache的tp9999在30ms左右。
- xcache的tp100有延时抖动,可能会出现300ms左右的毛刺(测试1个小时,出现4条超过300ms以上延时毛刺),但redis比较稳定,没有超过40毫秒的延时。
- 单实例redis的最大QPS在10w左右,xcache的最大QPS可以达到20w左右,比redis高出50%
5. xcache适用场景
- 大数据容量(数据超过百GB,甚至TB级别)。目前xcache在喜马拉雅线上部署了上百个实例,承载的数据总量约20TB。
- 高并发。xcache底层是多线程实现,相比redis有着更高的吞吐量,测试一般情况下,QPS比redis高出一倍。
- 对延时要求不是特别高。xcache数据是存储在磁盘上的,读命令时会去读磁盘,有可能会产生延时毛刺,但写命令会直接写内存,速度较快。测试xcache的tp9999大概在30ms左右,tp100有可能产生上百毫秒延时抖动。
- 大value存储。对于string数据类型,xcache支持KB级别的value存储,并且有较好的性能表现。
- 存在冷热数据。xcache可以将热数据缓存到内部的多个redis db中,相当于redis的多线程版本,在读多写少的场景下,对性能有较高的提升。
- 对数据库有定制化需求。目前xcache为业务的小伙伴定制了ehash数据类型,zset限长功能以及业务垃圾数据清理工具,在提升业务吞吐量的同时,大大简化了业务小伙伴的开发成本。
- 不想陷入繁琐的DBA运维,避免客户端进行sharding。xcache是一站式的分布式KV存储解决方案,支持命令自动路由,数据节点弹性伸缩容,高可用等,并且还有一套完善的监控体系。
6. 如何从redis迁移到xcache
6.1 开发需要做的
客户端从jedis切换到jodis,其它不需要做任何事情,看DBA干活就好。
6.2 DBA需要做的
- 使用迁移工具将redis的数据迁移到xcache
- 同步实时数据,保证redis数据和xcache的数据最终一致
- 主从切换,将新的请求路由到xcache服务
7. 联系我们
- 杨力,邮箱:[email protected]
- 董道光,邮箱:[email protected]
- github地址:https://github.com/XimalayaCloud/xcache