Gearman使用Redis 做数据持久化

安稳与你 提交于 2019-12-07 12:17:30

2014年的时候,老大说数据持久化,当时听的一愣一愣的,不知道啥是持久化;讲了一堆Gearman使用 Redis 和MySQL的东西,表示听不懂;然后他自己在那搞;左后搞出来了,还在launchpad.net 报告了一个bug,当时确实是第一个报告那种使用情况下bug的第一人微笑

    队列,很多流量大的网站都会使用。对于数据,是否需要考虑数据的可靠性,对于一般不重要的数据丢失也没关系;但是对于订单和钱后关系的这类数据是需要高可靠性的。

    当时老大设计的系统几乎就是准备跑在缓存上的一个平台系统(当然,不使用缓存一样运行),还有个队列Gearman。内存,数据都在内存上,丢失咋办;先写数据库(持久化)在改内存,这样就没啥意思了。所有的写操作都是先到缓存,判断缓存操作是否成功,失败写日志记录;然后使用队列Gearman写到数据库,那如果缓存中的数据加入到了队列的Job, 还没来得及Worker 消费数据,服务器出现故障,内存数据全部丢失,与之相关操作全部出错。

   解决方案:使用Redis 做数据的持久化,即使memcached 数据丢失,在Redis 上还有持久化的数据,当服务器可用后, Gearman 再从Redis 消费数据,持久化到数据库MySQL

   毕业后,自己动手配置过该环境,当时虽然配置出来了,但是没有做记录,当再次遇到这个问题时,发现已经有人做过了http://www.longlong.asia/2015/03/07/gearman-redis.html ,这片文章记录的问题,具体如何安装Gearman 和Redis自行百度吧


数据持久化支持:

Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操作的。

1)RDB快照

Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。我们可以通过Redis的save指令来配置RDB快照生成的时机,比如配置10分钟就生成快照,也可以配置有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的。

2)AOF日志

AOF日志的全称是append only file,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。只有那些会导致数据发生修改的命令才会追加到AOF文件。每一条修改数据的命令都生成一条日志,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。

AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的流程。在Redis中对AOF调用write写入后,通过appendfsync选项来控制调用fsync将其写到磁盘上的时间,下面appendfsync的三个设置项,安全强度逐渐变强。

  • appendfsync no 当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
  • appendfsync everysec 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
  • appednfsync always 当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。

对于一般性的业务需求,建议使用RDB的方式进行持久化,原因是RDB的开销并相比AOF日志要低很多,对于那些无法忍数据丢失的应用,建议使用AOF日志。


另附老大报告的bug: https://bugs.launchpad.net/gearmand/+bug/1390672


此文章只是作为自己的一个笔记记录!!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!