redis缓存技术学习.docx

上传人:牧羊曲112 文档编号:3165163 上传时间:2023-03-11 格式:DOCX 页数:20 大小:47.68KB
返回 下载 相关 举报
redis缓存技术学习.docx_第1页
第1页 / 共20页
redis缓存技术学习.docx_第2页
第2页 / 共20页
redis缓存技术学习.docx_第3页
第3页 / 共20页
redis缓存技术学习.docx_第4页
第4页 / 共20页
redis缓存技术学习.docx_第5页
第5页 / 共20页
亲,该文档总共20页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《redis缓存技术学习.docx》由会员分享,可在线阅读,更多相关《redis缓存技术学习.docx(20页珍藏版)》请在三一办公上搜索。

1、redis缓存技术学习1 什么是redis redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

2、2 性能怎么样 Redis是一个高性能的key-value内存数据库。官方性能测试结果: set操作每秒110000次,get操作每秒81000次。 3 可不可以存对象 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作。 4 Redis与memcache的最大区别 Replication data types persistence (snapshot、aof) 很多开发者都认为Redis不可能比Memcach

3、ed快,Memcached完全基于内存,而Redis具有持久化保存特性,即使是异步的,Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因,目前想到的原因有这几方面。 Libevent。和Memcached不同,Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现了自己的epoll event loop(4)。业界不少开发者也建议Redis使用另外一个libevent高性能替代libev,但是

4、作者还是坚持Redis应该小巧并去依赖的思路。一个印象深刻的细节是编译Redis之前并不需要执行./configure。 CAS问题。CAS是Memcached中比较方便的一种防止竞争修改资源的方法。CAS实现需要为每个cache key设置一个隐藏的cas token,cas相当value版本号,每次set会token需要递增,因此带来CPU和内存的双重开销,虽然这些开销很小,但是到单机10G+ cache以及QPS上万之后这些开销就会给双方相对带来一些细微性能差别(5)。 5单台Redis的存放数据必须比物理内存小 Redis的数据全部放在内存带来了高速的性能,但是也带来一些不合理之处。比

5、如一个中型网站有100万注册用户,如果这些资料要用Redis来存储,内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户,1周来访问过1次的也只有15万用户,因此全部100万用户的数据都放在内存有不合理之处,RAM需要为冷数据买单。 这跟操作系统非常相似,操作系统所有应用访问的数据都在内存,但是如果物理内存容纳不下新的数据,操作系统会智能将部分长期没有访问的数据交换到磁盘,为新的应用留出空间。现代操作系统给应用提供的并不是物理内存,而是虚拟内存(Virtual Memory)的概念。 基于相同的考虑,Redis 2.0也增加了VM特性。让Redis数据容量突破了

6、物理内存的限制。并实现了数据冷热分离。 6 Redis的VM实现是重复造轮子 Redis的VM依照之前的epoll实现思路依旧是自己实现。但是在前面操作系统的介绍提到OS也可以自动帮程序实现冷热数据分离,Redis只需要OS申请一块大内存,OS会自动将热数据放入物理内存,冷数据交换到硬盘,另外一个知名的“理解了现代操作系统(3)”的Varnish就是这样实现,也取得了非常成功的效果。 作者antirez在解释为什么要自己实现VM中提到几个原因(6)。主要OS的VM换入换出是基于Page概念,比如OS VM1个Page是4K, 4K中只要还有一个元素即使只有1个字节被访问,这个页也不会被SWAP

7、, 换入也同样道理,读到一个字节可能会换入4K无用的内存。而Redis自己实现则可以达到控制换入的粒度。另外访问操作系统SWAP内存区域时block进程,也是导致Redis要自己实现VM原因之一。 7 用get/set方式使用Redis 作为一个key value存在,很多开发者自然的使用set/get方式来使用Redis,实际上这并不是最优化的使用方法。尤其在未启用VM情况下,Redis全部数据需要放入内存,节约内存尤其重要。 假如一个key-value单元需要最小占用512字节,即使只存一个字节也占了512字节。这时候就有一个设计模式,可以把key复用,几个key-value放入一个key

8、中,value再作为一个set存入,这样同样512字节就会存放10-100倍的容量。 这就是为了节约内存,建议使用hashset而不是set/get的方式来使用Redis 8使用aof代替snapshot Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aof即append only mode,在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建

9、时间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作上,这样就看出aof是一个非常不协调的部分。 其实aof目的主要是数据可靠性及高可用性,在Redis中有另外一种方法来达到目的:Replication。由于Redis的高性能,复制基本没有延迟。这样达到了防止单点故障及实现了高可用。 9Redis是否支持集群 支持 redis主从复制配置和使用都非常简单。通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。下面是关于redis主从复制的一些特点 1.mas

10、ter可以有多个slave 2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构 3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。 4.主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余 5.可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然

11、后只在slave上配置数据持久化。 下面介绍下主从复制的过程 当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同

12、步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。 在多台服务器上简单实现Redis的数据主从复制 Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架构。下面我演示下怎样在多台服务器上进行Redis数据主从复制。这里我假设有两台服务器,一台是Windows操作系统,一台是Linux操作系统,在

13、两个操作系统都安装redis,Windows操作系统使用cygwin工具进行安装,命令为: view sourceprint? 1 $ tarxzf redis-2.2.2.tar.gz 2$ cdredis-2.2.2 3 $ make 可以通过make test”命令判断是否安装成功。 这里我使用1个master以及2个slave,基本流程是: 1. 在Windows服务器上创建两个目录,Demo1,Demo2,其中Demo1用来存放Master服务,Demo2用来存放Slave服务, 在Master服务中的配置文件修改: view sourceprint? 1 bind 192.168.

14、3.82 在Slave服务中的配置文件修改: view sourceprint? 1 port 6381 2 bind 192.168.3.82 3 slaveof 192.168.3.82 6379 2. 在Linux服务器上创建一个目录,Demo,Demo存放Slave服务,在服务中的配置文件修改: view sourceprint? 1 bind 192.168.3.90 2 slaveof 192.168.3.82 6379 这样就完成了所有的配置。 3. 现在运行这3个服务,通过命令: view sourceprint? 1 ./redis-server redis.conf 来启动

15、redis服务。 注意到,当我启动master,然后启动一个slave的时候,可以发现slave上: 会发送一个SYNC请求,从Master上面进行相应,而且它支持自动重连,即当master掉线的情况下,它会处于等待请求的状态。 而Master上: 能够接受Slave的应答,并且开始持久化操作,说明在Slave每次去连接Master的时候,都会去持久化磁盘。 4. 现在开始写一个客户端程序,使用到ServiceStack.Redis.dll的.NET组件: view sourceprint? 01 usingServiceStack.Redis; 02 03 staticvoidMain(st

16、ring args) 04 05 IRedisClientFactory factory = newRedisCacheClientFactory; 06 IRedisClient client = factory.CreateRedisClient(192.168.3.82, 6379); 07 08 client.Set(username, leepy); 09 10 stringusername = client.Get(username); 11 12 client.Save; 13 14 Console.WriteLine(username: 0, username); 15 16

17、Console.ReadLine; 17 运行结果: 数据Set的时候,数据保存在内存中,当调用Save方法时候,将数据保存在磁盘中。 其中你会发现在3个服务目录中,都出现了dump.rdb,说明Master的文件都同步到Slave中去了。 用UE编辑器打开文件查看: 从Redis源码中,可以发现rdb文件采用的是lzf压缩算法进行实现,默认lzf压缩算法是开启的。 10安装与使用 一、下载安装 Wget 二、.安装部署 Redis代码 1. tar zxvf 2. redis-2.2.7.tar.gz 3. cd redis-2.2.7.tar.gz 4. make 可以将redis.con

18、f 复制到 /etc/下 Redis代码 1. cp redis.conf /etc/ 2. cp src/redis-server src/redis-cli src/redis-benchmark /usr/local/redis 启动redis Redis代码 1. /usr/local/redis/redis-server redis.conf Port默认端口是 6379 简单的测试: 存值: ./redis-cli set hxaaa 取值: ./redis-cli get hx 要配置参数的意义: daemonize:是否以后台daemon方式运行 pidfile:pid文件位置

19、 port:监听的端口号 timeout:请求超时时间 loglevel:log信息级别 logfile:log文件位置 databases:开启数据库的数量 save * *:保存快照的频率,第一个*表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。 rdbcompression:是否使用压缩 dbfilename:数据快照文件名 dir:数据快照的保存目录 appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。 appendfsync:appendonlyl

20、og如何同步到磁盘 Redis命令总结 Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些command可以在Linux终端使用。在编程时,比如使用Redis 的Java语言包,这些命令都有对应的方法,比如上面例子中使用的sadd方法,就是对集合操作中的SADD命令。下面将Redis提供的命令做一总结。 连接操作相关的命令 󰀀 quit:关闭连接 󰀀 auth:简单密码认证 对value操作的命令 󰀀 exists(key):确认一个key是否存在 󰀀 del(key):删除一个key 󰀀 type(k

21、ey):返回值的类型 󰀀 keys(pattern):返回满足给定pattern的所有key 󰀀 randomkey:随机返回key空间的一个key 󰀀 rename(oldname, newname):将key由oldname重命名为newname,若newname存在则删除newname表示的key 󰀀 dbsize:返回当前数据库中key的数目 󰀀 expire:设定一个key的活动时间 󰀀 ttl:获得一个key的活动时间 󰀀 select(index):按索引查询 b

22、3040; move(key, dbindex):将当前数据库中的key转移到有dbindex索引的数据库 󰀀 flushdb:删除当前选择数据库中的所有key 󰀀 flushall:删除所有数据库中的所有key 对String操作的命令 󰀀 set(key, value):给数据库中名称为key的string赋予值value 󰀀 get(key):返回数据库中名称为key的string的value 󰀀 getset(key, value):给名称为key的string赋予上一次的value 󰀀 m

23、get(key1, key2, key N):返回库中多个string的value 󰀀 setnx(key, value):如果不存在名称为key的string,则向库中添加string,名称为key,值为value 󰀀 setex(key, time, value):向库中添加string同时,设定过期时间time 󰀀 mset(key1, value1, key2, value2,key N, value N):同时给多个string赋值,名称为key i的string赋值value i 󰀀 msetnx(key1, valu

24、e1, key2, value2,key N, value N):如果所有名称为key i的string都不存在,则向库中添加string,名称key i赋值为value i 󰀀 incr(key):名称为key的string增1操作 󰀀 incrby(key, integer):名称为key的string增加integer 󰀀 decr(key):名称为key的string减1操作 󰀀 decrby(key, integer):名称为key的string减少integer 󰀀 append(key, value)

25、:名称为key的string的值附加value 󰀀 substr(key, start, end):返回名称为key的string的value的子串 对List操作的命令 󰀀 rpush(key, value):在名称为key的list尾添加一个值为value的元素 󰀀 lpush(key, value):在名称为key的list头添加一个值为value的 元素 󰀀 llen(key):返回名称为key的list的长度 󰀀 lrange(key, start, end):返回名称为key的list中start至en

26、d之间的元素 󰀀 ltrim(key, start, end):截取名称为key的list,保留start至end之间的元素 󰀀 lindex(key, index):返回名称为key的list中index位置的元素 󰀀 lset(key, index, value):给名称为key的list中index位置的元素赋值为value 󰀀 lrem(key, count, value):删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count0从头至尾删除count个值为v

27、alue的元素,count0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对key i+1开始的list执行pop操作。 󰀀 brpop(key1, key2, key N, timeout):rpop的block版本。参考上一命令。 󰀀 rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部 对Set操作的命令 󰀀 sadd(key, member):向名称为key的set中添加元素member 󰀀 srem(key,

28、 member) :删除名称为key的set中的元素member 󰀀 spop(key) :随机返回并删除名称为key的set中一个元素 󰀀 smove(srckey, dstkey, member) :将member元素从名称为srckey的集合移到名称为dstkey的集合 󰀀 scard(key) :返回名称为key的set的基数 󰀀 sismember(key, member) :测试member是否是名称为key的set的元素 󰀀 sinter(key1, key2,key N) :求交集 󰀀

29、; sinterstore(dstkey, key1, key2,key N) :求交集并将交集保存到dstkey的集合 󰀀 sunion(key1, key2,key N) :求并集 󰀀 sunionstore(dstkey, key1, key2,key N) :求并集并将并集保存到dstkey的集合 󰀀 sdiff(key1, key2,key N) :求差集 󰀀 sdiffstore(dstkey, key1, key2,key N) :求差集并将差集保存到dstkey的集合 󰀀 smembers(key)

30、 :返回名称为key的set的所有元素 󰀀 srandmember(key) :随机返回名称为key的set的一个元素 对zset操作的命令 󰀀 zadd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。 󰀀 zrem(key, member) :删除名称为key的zset中的元素member 󰀀 zincrby(key, increment, member) :如果在名称为key的zset中已经存在元素member,

31、则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment 󰀀 zrank(key, member) :返回名称为key的zset中member元素的rank,若没有member元素,返回“nil” 󰀀 zrevrank(key, member) :返回名称为key的zset中member元素的rank,若没有member元素,返回“nil” 󰀀 zrange(key, start, end):返回名称为key的zset中的index从start到end的所有元素 󰀀 zrevrang

32、e(key, start, end):返回名称为key的zset中的index从start到end的所有元素 󰀀 zrangebyscore(key, min, max):返回名称为key的zset中score = min且score = min且rank = min且score = max的所有元素 󰀀 zunionstore / zinterstore(dstkeyN, key1,keyN, WEIGHTS w1,wN, AGGREGATE SUM|MIN|MAX):对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的sc

33、ore,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。 对Hash操作的命令 󰀀 hset(key, field, value):向名称为key的hash中添加元素fieldvalue 󰀀 hget(key, field):返回名称为key的hash中field对应的value 󰀀 hmget(key, fiel

34、d1, ,field N):返回名称为key的hash中field i对应的value 󰀀 hmset(key, field1, value1,field N, value N):向名称为key的hash中添加元素field ivalue i 󰀀 hincrby(key, field, integer):将名称为key的hash中field的value增加integer 󰀀 hexists(key, field):名称为key的hash中是否存在键为field的域 󰀀 hdel(key, field):删除名称为key的hash中

35、键为field的域 󰀀 hlen(key):返回名称为key的hash中元素个数 󰀀 hkeys(key):返回名称为key的hash中所有键 󰀀 hvals(key):返回名称为key的hash中所有键对应的value 󰀀 hgetall(key):返回名称为key的hash中所有的键及其对应的value 持久化 󰀀 save:将数据同步保存到磁盘 󰀀 bgsave:将数据异步保存到磁盘 󰀀 lastsave:返回上次成功将数据保存到磁盘的Unix时戳 󰀀 shun

36、down:将数据同步保存到磁盘,然后关闭服务 远程服务控制 󰀀 info:提供服务器的信息和统计 󰀀 monitor:实时转储收到的请求 󰀀 slaveof:改变复制策略设置 󰀀 config:在运行时配置Redis服务器 在192.168.134.96 上安装了redis的master 在192.168.134.97 上安装了slave 绑定了192.168.134.96 11 redis事务 redis对事务的支持目前还比较简单。redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client

37、的命令。由于redis是单线程来处理所有client的请求的所以做到这点是很容易的。一般情况下redis在接受到一个client发来的命令后会立即处理并返回处理结果,但是当一个client在一个连接中发出multi命令有,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一个队列中。当从此连接受到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给client.然后此连接就结束事务上下文。下面可以看一个例子 redis multi OK redisincr a QUEUED redisincrb QUEUED redis exec

38、 1. (integer) 1 2. (integer) 1 从这个例子我们可以看到incr a ,incr b命令发出后并没执行而是被放到了队列中。调用exec后俩个命令被连续的执行,最后返回的是两条命令执行后的结果 我们可以调用discard命令来取消一个事务。接着上面例子 redis multi OK redisincr a QUEUED redisincrb QUEUED redis discard OK redis get a 1 redis get b 1 可以发现这次incr a incr b都没被执行。discard命令其实就是清空事务的命令队列并退出事务上下文。 虽说redi

39、s事务在本质上也相当于序列化隔离级别的了。但是由于事务上下文的命令只排队并不立即执行,所以事务中的写操作不能依赖事务中的读操作结果。看下面例子 redis multi OK redis get a QUEUED redis get b QUEUED redis exec 1. 1 2. 1 发现问题了吧。假如我们想用事务实现incr操作怎么办?可以这样做吗? redis get a 1 redis multi OK redis set a 2 QUEUED redis exec 1. OK redis get a, 2 结论很明显这样是不行的。这样和 get a 然后直接set a是没区别的。

40、很明显由于get a 和set a并不能保证两个命令是连续执行的(get操作不在事务上下文中)。很可能有两个client同时做这个操作。结果我们期望是加两次a从原来的1变成3. 但是很有可能两个client的get a,取到都是1,造成最终加两次结果却是2。主要问题我们没有对共享资源a的访问进行任何的同步 也就是说redis没提供任何的加锁机制来同步对a的访问。 还好redis 2.1后添加了watch命令,可以用来实现乐观锁。看个正确实现incr命令的例子,只是在前面加了watch a redis watch a OK redis get a 1 redis multi OK redis s

41、et a 2 QUEUED redis exec 1. OK redis get a, 2 watch 命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key.这样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视. redis的事务实现是如此简单,当然会存在一些问题。第一个问题是redis只能保证事务的每个命令连续执行,但是如果事务中的一个命令失败了,并不回滚

42、其他命令,比如使用的命令类型不匹配。 redis set a 5 OK redislpushb 5 (integer) 1 redis set c 5 OK redis multi OK redisincr a QUEUED redisincrb QUEUED redisincr c QUEUED redis exec 1. (integer) 6 2. (error) ERR Operation against a key holding the wrong kind of value 3. (integer) 6 可以看到虽然incr b失败了,但是其他两个命令还是执行了。 最后一个十分罕

43、见的问题是当事务的执行过程中,如果redis意外的挂了。很遗憾只有部分命令执行了,后面的也就被丢弃了。当然如果我们使用的append-only file方式持久化,redis会用单个write操作写入整个事务内容。即是是这种方式还是有可能只部分写入了事务到磁盘。发生部分写入事务的情况下,redis重启时会检测到这种情况,然后失败退出。可以使用redis-check-aof工具进行修复,修复会删除部分写入的事务内容。修复完后就能够重新启动了。 12 redis的持久化 redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化。redis支持两种持久化

44、方式,一种是 Snapshotting也是默认方式,另一种是Append-only file的方式。下面分别介绍 Snapshotting 快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置 save 900 1 #900秒内如果超过1个key被修改,则发起快照保存 save 300 10 #300秒内容如超过10个key被修改,则发起快照保存 save 60 10000 下面介绍详细的快照保存过程

45、1.redis调用fork,现在有了子进程和父进程。 2. 父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制 appendonly yes /启用aof持久化方式 # appendfsync always /每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用 appendfsynceverysec /每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐 # appendfsync no /完全依赖os,性能最好,持久化没保证 aof的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命

46、令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。具体过程如下 1. redis调用fork ,现在有父子两个进程 2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令 3.父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。 4.当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。 5.现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。 需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号