Pika是一个可持久化的大容量redis存储服务,兼容string、hash、list、zset、set的绝大部分接口(兼容详情),解决redis因为存储数据量巨大而致使内存不够用的容量瓶颈。用户能够不修改任何代码从redis迁移到pika服务。具备良好的兼容性和稳定性,被360公司内部使用超过3000实例,github社区超过3.8K star。因为单机pika容量受限于单块硬盘容量的大小,360公司业务和社区对分布式pika集群的需求愈来愈强烈,所以咱们推出了原生分布式pika集群,发布pika版本v3.4。与pika+codis集群方案相比,codis对pika建立和管理slot操做的支持并不友好,须要运维人员大量介入。而pika原生集群则不须要额外部署codis-proxy模块。git
以3个pika节点的集群为例,集群部署结构如上图所示:github
为了对数据按照业务进行隔离,Pika集群引入table的概念,不一样的业务数据存储在不一样的table中。业务数据按照key的hash值存储到对应的slot上面。每个slot会有多个副本,从而造成一个replication group。replication group中的全部slot副本具备相同的slot ID,其中一个slot副本是leader,其余副本为follower。为了保证数据的一致性,只有leader提供读写服务。可使用pika manager对slot进行调度迁移,使数据和读写压力均匀的分散到整个pika集群中,从而保证了整个集群资源的充分利用而且能够根据业务压力和存储容量的须要进行水平扩容和缩容。redis
pika使用rocksdb做为存储引擎,每一个slot会建立对应的rocksdb。pika中的每一个slot都支持读写redis 5种数据结构。所以数据迁移的时候会特别方便,只需迁移pika中的slot便可。但同时也存在资源占用过多的问题。目前的pika在建立slot的时候会默认建立5个rocksdb,分别来存储5种数据结构。在table中含有大量slot或者建立大量table的时候会使单个pika节点含有多个slot,进而建立过多的rocksdb实例,占用了过多系统资源。在后续版本中一方面会支持建立slot的时候根据业务须要建立一种或多种数据结构,另外一方面会持续对pika中的blackwidow接口层进行优化,减小对rocksdb的使用。后端
咱们把proxy内嵌的pika中,不须要单独部署。与redis cluster相比,客户端不须要感知proxy的存在,只需像使用单机同样使用集群。能够把pika节点的服务端口挂载到LVS中,实现压力在整个集群的负载均衡。数据结构
pika中replication manager模块负责日志的主从同步。为了兼容redis,pika支持非一致日志复制,leader slot直接在db中写入数据而无需等待从follower slot的ack应答。同时也支持raft一致性协议方式的日志复制,须要知足收到大多数副本的ack才写入db。负载均衡
在非一致场景下处理流程以下:运维
在一致性日志复制场景下:异步
咱们在codis-dashboard的基础上二次开发了pika manager(简称PM),做为整个集群的全局控制节点,用来部署和调度管理集群。PM里保存了整个集群的元数据及路由信息。分布式
pika原生集群的推出解决了单机pika受限于磁盘容量的限制,能够按照业务的需求进行水平扩容。但仍然有一些缺陷,如基于raft的内部自动选主功能的缺失,基于range的数据分布,及监控信息的展板等功能。后续版本咱们会一一解决这些问题。优化