Skip to content
SongZhao edited this page May 25, 2016 · 20 revisions

Q1: 为什么要开那么多线程?比如purge,搞个定时任务不就好了。难道编程框架不支持定时器?

A1: pika有一些比较耗时的任务,如删binlog,扫描key,备份,同步数据文件等等,为了不影响正常的用户请求,这些任务都是放到后台执行的,并且将能并行的都放到不同线程里来最大程度上提升后台任务的执行速度;你说的变成框架是pink吗?pink是支持定时器的,每一个workerthread只要用户定义了cronhandle和频率,就会定时执行要执行的内容,不过这时候worker是被独占的,相应不了用户请求,所以占时的任务最好还是单独开线程去做,redis的bio也是这个原因

Q2: heartbeat让sender做不就好了?或者说sender有必要那么多线程吗?

A2: 这主要有两个原因,第一为了提高同步速度,sender只发不收,receiver只收不发,心跳是又单独的线程去做,如果心跳又sender来做,那么为了一秒仅有一次的心跳还要去复杂化sender和receiver的逻辑;第二其实前期尝试过合并在一起来进行连接级别的存活检测,当写入压力过大的时候会心跳包的收发会延后,导致存活检测被影响,slave误判master超时而进行不必要的重连

Q3: nemo存储hash的实际key,第一个字节是?header?一个类型标记?是说他是个hash类型?

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用的

Q4: list数据结构里面的curr_seq是个什么东西?

A4: list的实现是完全基于kv实现的list,通过seq来实现list类似prev和next指针,cur_seq是在meta信息里的,也就是当前已经用到那个seq了,新来的节点从这个seq开始递增接着用

Q5: binlog里面存储的是转化后的put,delete?还是存储的原生redis命令?

A5: 存的是redis的命令

Q6: rsync的deamon模式,这个rsync是linux上的rsync命令?

A6: 是的,pika前期为了更快的实现全同步的功能,此处是直接调用rsync命令来完成数据文件的收发,也是由它来进行文件的续传校验等

Q7: dump db文件是rocksdb本身就带的功能?具体怎么搞的?

A7: rocksdb提够对当前db快照备份的功能,我们基于此,在dump时先对pika阻住用户的写,然后记录当前的binlog偏移量并且调用rocksdb的接口来拿到当前db的元信息,这个时候就可以放开用户写,然后基于这个元信息来进行快照数据的后台拷贝,阻写的时间很短

Q8: 先写binlog再执行,如果这时候挂了,命令还没执行,但是写入到binlog里面了怎么办?

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重启后进行全同步即可

Q9: BinlogBGWorker线程之间还是要按照binlog顺序执行,这块并发能提高多少性能?

A9: 之前主从同步的差异是由主的多个worker写入而从只有一个worker写入带来的,现在的做法提高了从写db的速度,不过协议解析还是有一个线程来做,还是有瓶颈,不过这样的优化主从同步的性能提高了3~5倍左右,如果key很少的话,优化不明显,因为slave这面是通过key的hash值来sharding到其中一个worker上的

Q10: 秒删,每次put都要去查询key的最新版本?也就是说每次写避免伴随一次读?

A10: pika多数据结构的实现主要是“meta key + 普通key”来实现的,所以对于多数据结构的读写,肯定都是对rocksdb进行2次及以上的读写次数,你说的版本信息我们是存在meta_key中的,和其他meta信息一起被读出来,其实并没有因为版本号而额外增加读写次数

Clone this wiki locally