全量同步
master 服务器会开启一个后台进程用于将 redis 中的数据生成一个 rdb 文件,与此同时,服
务器会缓存所有接收到的来自客户端的写命令(包含增、删、改),当后台保存进程处理完毕后,会将该 rdb 文件传递给 slave 服务器,而 slave 服务器会将 rdb 文件保存在磁盘并通过读取该文件将数据加载到内存,在此之后 master 服务器会将在此期间缓存的命令通过 redis 传输协议发送给 slave 服务器,然后 slave 服务器将这些命令依次作用于自己本地的数据集上最终达到数据的一致性。
增量同步
从 redis 2.8 版本以前,并不支持部分同步,当主从服务器之间的连接断掉之后,master 服务器和 slave 服务器之间都是进行全量数据同步。
从 redis 2.8 开始,即使主从连接中途断掉,也不需要进行全量同步,因为从这个版本开始融入了部分同步的概念。部分同步的实现依赖于在 master 服务器内存中给每个 slave 服务器维
护了一份同步日志和同步标识,每个 slave 服务器在跟 master 服务器进行同步时都会携带自己的同步标识和上次同步的最后位置。当主从连接断掉之后,slave 服务器隔断时间(默认
1s)主动尝试和 master 服务器进行连接,如果从服务器携带的偏移量标识还在 master 服务器上的同步备份日志中,那么就从 slave 发送的偏移量开始继续上次的同步操作,如果slave
发送的偏移量已经不再 master 的同步备份日志中(可能由于主从之间断掉的时间比较长或者在断掉的短暂时间内 master 服务器接收到大量的写操作),则必须进行一次全量更新。在部分同步过程中,master 会将本地记录的同步备份日志中记录的指令依次发送给 slave 服务器从而达到数据一致。
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同
步,如不成功,要求从机进行全量同步。
RDB
RDB 持久化方式,是将 Redis 某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
RDB 优点:
⚫ RDB 是一个非常紧凑(有压缩)的文件,它保存了某个时间点的数据,非常适用于数据的备份。
⚫ RDB 作为一个非常紧凑(有压缩)的文件,可以很方便传送到另一个远端数据中心 ,非常适用于灾难恢复。
⚫ RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部
由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 redis的性能。
⚫ 与 AOF 相比,在恢复大的数据集的时候,RDB 方式会更快一些。
RDB 缺点:
⚫ Redis 意外宕机时,会丢失部分数据。
⚫ 当 Redis 数据量比较大时,fork 的过程是非常耗时的,fork 子进程时是会阻塞的,在这
期间 Redis 是不能响应客户端的请求的。
AOF
AOF 方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行
一遍。
AOF 优点:
⚫ 使用 AOF 会让你的 Redis 更加持久化。
⚫ AOF 文件是一个只进行追加的日志文件,不需要在写入时读取文件。
⚫ Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写 。 ⚫ AOF 文件可读性高,分析容易。
AOF 缺点:
⚫ 对于相同的数据来说,AOF 文件大小通常要大于 RDB 文件。
⚫ 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。
redis 内部使⽤⽂件事件处理器 file event handler ,这个⽂件事件处理器是单线程的,所以
redis 才叫做单线程的模型。它采⽤ IO 多路复⽤机制同时监听多个 socket,根据 socket 上的事件
来选择对应的事件处理器进⾏处理。
⽂件事件处理器的结构包含 4 个部分:
多个 socket
IO 多路复⽤程序
⽂件事件分派器
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 socket 可能会并发产⽣不同的操作,每个操作对应不同的⽂件事件,但是 IO 多路复⽤程序会监听多个 socket,会将 socket 产⽣的事件放⼊队列中排队,事件分派器每次从队列中取出⼀个事件,把该事件交给对应的事件处理器进⾏处理。
对于 redis 和 memcached 我总结了下⾯四点。现在公司⼀般都是用 redis 来实现缓存,而且 redis自身也越来越强⼤了!
- redis支持更丰富的数据类型(支持更复杂的应⽤场景):Redis不仅仅支持简单的k/v类型的数
据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,
String。 - Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中。
- 集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 redis 目前是原生支持持 cluster 模式的.
- Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。
String
常用命令: set,get,decr,incr,mget 等。
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。 常规key/value缓存应用; 常规计数:微博数,粉丝数等。
Hash
常⽤命令: hget,hset,hgetall 等。
hash 是⼀个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以 hash 数据结构来存储用户信息,商品信息等等。比如下⾯我就用 hash 类型存放了⼀些信息:
key=Redis8220
value={
“id”: 1,
“name”: “GDX”,
“age”: 21,
“location”: “Hangzhou, Zhejiangi”
}
List
常⽤命令: lpush,rpush,lpop,rpop,lrange等
list 就是链表,Redis list 的应⽤场景非常多,也是Redis最重要的数据结构之⼀,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的 list 结构来实现。
Redis list 的实现为⼀个双向链表,即可以⽀持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
另外可以通过 lrange 命令,就是从某个元素开始读取多少个元素,可以基于 list 实现分页查询,这个很棒的⼀个功能,基于 redis 实现简单的⾼性能分页,可以做类似微博那种下拉不断分页的东西。
常⽤命令: sadd,spop,smembers,sunion 等
set 对外提供的功能与list类似是⼀个列表的功能,特殊之处在于 set 是可以自动排重的。
当你需要存储⼀个列表数据,又不希望出现重复数据时,set是⼀个很好的选择,并且set提供了判断某个成员是否在⼀个set集合内的重要接口,这个也是list所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。
比如:在微博应用中,可以将一个用户所有的关注人存在⼀个集合中,将其所有粉丝存在一个集合。
Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程,
具体命令如下:
sinterstore key1 key2 key3 将交集存在key1内
Sorted Set
常⽤命令: zadd,zrange,zrem,zcard等
和set相比,sorted set增加了⼀个权重参数score,使得集合中的元素能够按score进行有序排列。
举例: 在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理
解为按消息维度的消息排行榜)等信息,适合使用 Redis 中的 Sorted Set 结构进行存储。
Redis中有个设置时间过期的功能,即对存储在 redis 数据库中的值可以设置⼀个过期时间。作为⼀个
缓存数据库,这是非常实⽤的。如我们⼀般项目中的 token 或者⼀些登录信息,尤其是短信验证码都是有时间限制的,按照传统的数据库处理方式,⼀般都是自己判断过期,这样无疑会严重影响项目性能。
我们 set key 的时候,都可以给⼀个 expire time,就是过期时间,通过过期时间我们可以指定这个
key 可以存活的时间。
如果假设你设置了⼀批 key 只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?
定期删除+惰性删除。
通过名字大概就能猜出这两个删除方式的意思了。
定期删除:redis默认是每隔 100ms 就随机抽取⼀些设置了过期时间的key,检查其是否过期,
如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想⼀想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载!
惰性删除 :定期删除可能会导致很多过期 key 到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查⼀下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,也是够懒的哈!



