每一次操作之前都会记录日志,防止中断造成数据丢失。
操作如下:
A 记录日志
B redis 计数+1
C 清除日志
1、如果执行完A中断,启动之后检查日志,可以再次执行操作B,数据不丢失。
2、如果执行完b就中断,那么日志恢复之后就会多执行一次b,数据虽然不丢失,但是造成重复数据。
题目原本是断电,后来可能都围绕断电回答了,其实断电概率还是挺小的,主要是应用执行的时候突然被用户终止运行,或者程序崩溃等等造成的数据丢失。
看评论还有人抬扛的。
实际上,很多数据库都有类似的机制防止突然中止造成数据丢失。。
1、比如 leveldb :log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据。因为在将记录写入内存的Memtable之前,会先写入Log文件,这样即使系统发生故障,Memtable中的数据没有来得及Dump到磁盘的SSTable文件,LevelDB也可以根据log文件恢复内存的Memtable数据结构内容,不会造成系统丢失数据,在这点上LevelDb和Bigtable是一致的。
相关文章:https://www.cnblogs.com/haipp...
2、还有elasticsearch:
如果没有用 fsync 把数据从文件系统缓存刷(flush)到硬盘,我们不能保证数据在断电甚至是程序正常退出之后依然存在。为了保证 Elasticsearch 的可靠性,需要确保数据变化被持久化到磁盘。
相关文章:https://www.elastic.co/guide/...
3、还有rabbitmq的防止丢消息和重复消费:
一般情况确实不需要考虑断点和宕机造成数据丢失的问题。但如果对一致性要求非常严格的时候还是应该考虑,比如银行转账、淘宝微信等的收付款、软件升级(只升级一半是有可能导致程序无法启动的)等。
遇到这种情况记日志是肯定需要的,而如何防止你说的第二个重复执行的问题,我觉得重点不是防止重复执行,而是重复执行不会带来副作用。比如替换文件就是一个没有副作用的操作,你用A替换原来的B,无论你拷贝粘贴多少次,结果都是一样的,最终的文件都是A。而直接给账户加钱和扣钱就是有副作用的,你的例子里给计数加1也是有副作用的。这种时候必须对操作进行修改,通常是拆分成更多的步骤,每个步骤必须没有副作用,然后给每个步骤加日志。
比如你的例子,我可以这样拆分:
由于锁的存在,整个操作是原子性的。假如中间有任何一步出现问题,下次恢复执行的时候就可以检查出来。如果是第二步出问题,那么只需要简单地重新来一遍即可。如果是第三步出问题,第四步还没来得及执行,那么将只会在第二步有日志,重新执行之后,读入当前的redis计数,如果与日志记录的相同,则重新从第三步开始执行,如果比日志记录的大1,则说明第三步已经执行过了,从第四步开始执行即可。