作者回复: Redis启动后本身是一个进程,它的主体工作(接收请求、服务请求读写数据)也是在这个进程中完成的,咱们有些同学称Redis为主进程是可以的。 同时,Redis这个进程属于单线程的进程,也就是说进程主体工作没有用多个线程来运行,所以我一般把它也称为主线程,突显它的单线程模式。 有的程序启动后,会在进程中启动多个线程来处理工作,这个时候我就不会称它为主线程了,因为没有一个线程是单独做主要工作的。 希望能解答了你的问题。
作者回复: 除了考虑了内存风险,还考虑了CPU风险。赞!先置个顶 :D 关于绑核的操作,后面再和Kaito同学聊聊,绑核也有些值得探讨的地方的。
作者回复: 子进程读到的是主线程修改前的数据。 我在文章中介绍写时复制时,说法上有点偏它能达到的效果了,可能让大家理解有误了,抱歉! 我再解释下,文章中说“这块数据就会被复制一份,生成该数据的副本”,这个操作在实际执行过程中,是子进程复制了主线程的页表,所以通过页表映射,能读到主线程的原始数据,而当有新数据写入或数据修改时,主线程会把新数据或修改后的数据写到一个新的物理内存地址上,并修改主线程自己的页表映射。所以,子进程读到的类似于原始数据的一个副本,而主线程也可以正常进行修改。 希望能解答你的疑惑。
作者回复: 可以看下第10讲的答疑,有对COW的底层机制做了更加详细的介绍。 第5讲介绍COW时,有点偏于介绍COW的效果了。实际上,fork本身这个操作执行时,内核需要给子进程拷贝主线程的页表。如果主线程的内存大,页表也相应大,拷贝页表耗时长,会阻塞主线程。 bgsave保存RDB时,如果有写请求,主线程会把新数据写到新的物理地址,此时的阻塞会来自于主线程申请新内存空间以及复制原数据。 如果是子进程做复制,而主线程直接改数据的话,会有问题:1. 如果子进程还没有把一块数据写入RDB时,主线程就修改了数据,那么就快照完整性就被破坏了;2. 子进程复制数据时,也需要加锁,避免主线程同时修改,如果此时,主线程正好有写请求要处理,主线程同样会被阻塞。
作者回复: 非常赞!考虑到了根据不同的QPS进行分析。 我再提一个维度,你可以考虑下,就是修改的键值对的范围,也就是说写操作是针对一小部分键值对,还是针对大部分键值对的。你觉得这个维度会有影响么?
作者回复: 如果服务挂了,我们可以让Redis实例自动重启。此时,如果没有数据备份的话,再启动时,所有的数据都需要重新写入,这个过程会比较耗时。而如果有备份的话,Redis再启动后,可以直接读入备份数据,对于这些数据的读写操作就可以很快服务了。不知道有没有解答你的疑惑。 愿意提出来的问题都是好问题哈 :)
作者回复: 可以自动执行。Redis配置文件中的save选项是用来配置bgsave的触发条件的,例如 save 60 10000 如果60s内有至少10000个键值对的修改,就会自动触发bgsave了。
作者回复: 学习时把知识贯通起来理解是个好方法!
作者回复: 分析的不错,这种情况下,内存的潜在压力风险比较大。 另外,Kaito同学还分析了CPU资源的风险,也可以看看。
作者回复: 不错,不错!可以再想想看,在问题里的云主机上,哪怕我们先不考虑快照频率问题,单就做一次快照本身,是否可能还会有其他问题?:)