-
Notifications
You must be signed in to change notification settings - Fork 1.2k
FAQ
A1: pika有一些比较耗时的任务,如删binlog,扫描key,备份,同步数据文件等等,为了不影响正常的用户请求,这些任务都是放到后台执行的,并且将能并行的都放到不同线程里来最大程度上提升后台任务的执行速度;你说的变成框架是pink吗?pink是支持定时器的,每一个workerthread只要用户定义了cronhandle和频率,就会定时执行要执行的内容,不过这时候worker是被独占的,相应不了用户请求,所以占时的任务最好还是单独开线程去做,redis的bio也是这个原因
A2: 这主要有两个原因,第一为了提高同步速度,sender只发不收,receiver只收不发,心跳是又单独的线程去做,如果心跳又sender来做,那么为了一秒仅有一次的心跳还要去复杂化sender和receiver的逻辑;第二其实前期尝试过合并在一起来进行连接级别的存活检测,当写入压力过大的时候会心跳包的收发会延后,导致存活检测被影响,slave误判master超时而进行不必要的重连
A3: 的确是一个header,不过不是为了标记它是hash,因为nemo底下已经将string,hash,list,zset,set这五个数据结构分成的5个库,互不影响,之所以有header是因为一个hash有一个meta key和一堆field key,meta key对应的value记录的是这个hash的基础信息,如hash的size等等,这个header也是区分meta key和field key用的
A4: list的实现是完全基于kv实现的list,通过seq来实现list类似prev和next指针,cur_seq是在meta信息里的,也就是当前已经用到那个seq了,新来的节点从这个seq开始递增接着用
A5: 存的是redis的命令
A6: 是的,pika前期为了更快的实现全同步的功能,此处是直接调用rsync命令来完成数据文件的收发,也是由它来进行文件的续传校验等
A7: rocksdb提够对当前db快照备份的功能,我们基于此,在dump时先对pika阻住用户的写,然后记录当前的binlog偏移量并且调用rocksdb的接口来拿到当前db的元信息,这个时候就可以放开用户写,然后基于这个元信息来进行快照数据的后台拷贝,阻写的时间很短
A8: master是先写db再写binlog,之前slave只用一个worker来同步会在master写入压力很大的情况下由于slave一个worker写入太慢而造成同步差距过大,后来我们调整结构,让slave通过多个worker来写提高写入速度,不过这时候有一个问题,为了保证主从binlog顺序一致,写binlog的操作还是只能又一个线程来做,也就是receiver,所以slave这边是先写binlog在写db,所以slave存在写完binlog挂掉导致丢失数据的问题,不过redis在master写完db后挂掉同样会丢失数据,所以redis采用全同步的办法来解决这一问题,pika同样,默认使用部分同步来继续,如果业务对数据十分敏感,此处可以强制slave重启后进行全同步即可
A9: 之前主从同步的差异是由主的多个worker写入而从只有一个worker写入带来的,现在的做法提高了从写db的速度,不过协议解析还是有一个线程来做,还是有瓶颈,不过这样的优化主从同步的性能提高了3~5倍左右,如果key很少的话,优化不明显,因为slave这面是通过key的hash值来sharding到其中一个worker上的
A10: pika多数据结构的实现主要是“meta key + 普通key”来实现的,所以对于多数据结构的读写,肯定都是对rocksdb进行2次及以上的读写次数,你说的版本信息我们是存在meta_key中的,和其他meta信息一起被读出来,其实并没有因为版本号而额外增加读写次数
因为 Redis 所有的操作都是对于内存的操作,因此理论上 Redis 的每次操作很短的。
目前没有对数据进行分片,你可以理解成和单机 Redis 类似,支持 master-slave 的架构,因此单个 pika 实例存储的大小的限制是磁盘大小的限制。
pika 支持所有的 Redis 客户端,因为 pika 设计之初就考虑到了用户的迁移成本,因此各种语言的客户端都支持。pipelining 是客户端来做的,因此我们是支持 pipelining 的。
我们开始做 pika 的时候,Redis cluster shard 还不完善,而且 Redis cluster 定位的场景和 pika 还是有区别。目前我们内部还没大范围使用 Redis cluster。
我们暴露给用户的 ip 是我们 LVS 的 ip。在 Redis 前面 LVS 是为了方便主从切换,这样可以做到用户完全不感知。这里 LVS 下面挂的多个 Redis 实例,都是 master-slave 结构的。
我们公司内部有业务部门用 ssdb,目前除了游戏大部分的 ssdb 已经迁移到 pika上来。我觉得 pika 的优势在于我们代码实现的比较细,性能会比较好。
存储引擎上我们在 LevelDB,RocksDB 上面做过对比。LevelDB,RocksDB 在数据量比较小的时候性能差异不大,但是在数据量比较大的情况下,比如 200G 的时候,RocksDB 的性能会比 LevelDB 要来得好。但是 RocksDB 也有他的缺点,就是代码没有 LevelDB 来的那么优雅,我一直觉得一个好的 c++ 程序员看 LevelDB 代码和 effective c++ 就好了。
是的。所以目前内部的 pika 的架构是支持一主多从、多机房自洽的方案。目前线上最多一个主 14 个从这样的结构。DBA 可以很容易的slaveof 给一个主挂上slave,然后进行数据的全同步过程。
这里大家可以看到,这个测试结果是 pika work thread 开了 18 个。
在多数据结构的接口里面 kv 的结构的性能是最好的,而多数据结构的接口比如 hash、zset 等等就算开了 18 个线程,性能依然不如 Redis 要来得好。因为 hash、zset 等数据结构需要有抢占多数据结构元数据锁的开销,因此性能很容易下来。但是 kv 接口基本没有锁的开销。唯一的锁开销就是 RocksDB 为了实现线程安全增加的锁,因此这个结果也是可以理解了。
其实我们在 bada 里面增加了多数据结构的接口,并且兼容了 Redis 的协议,但是后来用户的使用中,发现其实使用多数据结构接口的用户数据量其实不是特别大。单机 1T 的盘基本都能够承受下来。但是还是因为 Hash 分布式切片不均衡,导致我们的维护成本增加,因此我们去实现了 m-s 架构方案。
目前 bada 的方案也是和 pika 并存的方案,我们会根据用户具体的使用场景推荐使用的存储方案。我一直觉得肯定不是一套存储方案解决公司内部的所有需求,一定是某一个方案更适用于某一种存储方案。
Pika 目前并没有使用类似 Redis 的 sentinel,pika 前面是挂 LVS 来负责主从切换。目前也没有使用 Codis 这样的 proxy 方案。
一主 14 从的场景是用户的写入都是晚上定期的灌数据,读取的话从各个从库进行读取。因此这个数据一致性是用户可以接受的场景。
##### 如果您有其他问题,请联系 邮箱:songzhao@360.cn
- 安装使用
- 支持的语言和客户端
- 当前支持的Redis接口以及兼容情况
- 配置文件说明
- 数据目录说明
- info信息说明
- 部分管理指令说明
- 差异化命令
- PikiwiDB Sharding Tutorials
- PikiwiDB 订阅
- 配合sentinel(哨兵)实现pikiwidb自动容灾
- 如何升级到PikiwiDB3.0
- 如何升级到PikiwiDB3.1或3.2
- PikiwiDB多库版命令、参数变化参考
- PikiwiDB分片版本命令
- 副本一致性使用说明
- PikiwiDB内存使用
- PikiwiDB最佳实践
- 整体架构
- 线程模型
- 全同步
- 增量同步
- 副本一致性
- 快照式备份
- 锁的应用
- nemo存储引擎数据格式
- blackwidow存储引擎数据格式
- PikiwiDB源码学习--pikiwidb的通信和线程模型
- PikiwiDB源码学习--pikiwidb的PubSub机制
- PikiwiDB源码学习--pikiwidb的命令执行框架
- PikiwiDB源码学习--pikiwidb和rocksdb的对接
- pikiwiDB-NoSQL原理概述
- pikiwidb在codis中的探索
- Pikiwidb 笔记
- pikiwidb 主从同步原理