Redis 基础二
redis 高效原因
- redis 完全基于内存的,使用的是单进程单线程的模型,数据结构有使用的是KEY-VALUE类型,绝大部分的操作都是纯粹的内存操作,数据都在内存中,所以查询起来非常快.
- redis的数据结构是专门设计的,其数据结构简单,对数据的操作也简单.
- redis 采用单线程单进程模型,避免了不必要的上下文切换和竞争条件,也避免了多线程,多进程切换消耗CPU,也不存在各种锁导致效率底下的问题.
- redis 使用的底层模型不同,redis构建了自己的virtual memory 模型并未使用OS提供的 vm机制,其原因redis作者也进行了说明.
- redis 使用了多路I/O复用模型,非阻塞IO.
redis四种部署模式及特点
-
单机模式(Standalone)
最简单的部署模式,直接部署在单一机器上,有点在于成本低,没有备用节点,性能高,无数据同步,数据一致性高,缺点是抗风险能力低,有宕机分享,处理能力过分依赖与机器的CPU性能. -
主从模式(Master Slave)
主从模式分为主节点(master) 与从节点(slave),一个master节点可以挂多个slave节点,当主节点宕机后slave中产生新的master节点,数据备份从master单向复制到slave节点,优点在于当master宕机slave可以随时顶替,并且很大程度分担了master读数据的压力,缺点在于数据的读写能力受master节点控制,主节点宕机后从节点顶替应用方需要更改主节点地址,需要人工干预.配置: vim redis.conf # 以守护进程的方式运行 daemonize yes port 6379 # 绑定的主机地址 bind 0.0.0.0 # 指定当本机为slave服务时,设置master服务的IP地址及端口,在redis启动的时候他会自动跟master进行数据同步 slaveof <masterip> <masterport> # 当master设置了密码保护时,slave服务连接master的密码 masterauth <master-password> # 设置redis连接密码,如果配置了连接密码,客户端在连接redis是需要通过AUTH<password>命令提供密码,默认关闭 requirepass footbared
-
哨兵模式(Sentinel)
简单理解哨兵(sentinel)模式就是为了解决主从模式中master节点出现问题后slave节点变为主节点需要应用端更改主节点地址的问题,所以哨兵模式的基础是主从模式,sentinel还有其他功能,比如:主节点存活检测、主从运行情况检测、主从切换.哨兵模式由两部分组成:一个或多个sentinel节点成为哨兵节点,该节点不做数据储存,每一个master节点和slave节点称为数据节点,用来储存数据.每个Sentinel以 每秒钟 一次的频率,向它所有的 主服务器、从服务器 以及其他Sentinel实例 发送一个PING 命令,如果一个 实例(instance)距离最后一次有效回复 PING命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel标记为 主观下线。如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有 Sentinel 节点,要以 每秒一次 的频率确认 该主服务器是否的确进入了 主观下线 状态。如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的 Sentinel(至少要达到配置文件指定的数量)在指定的 时间范围 内同意这一判断,那么这个该主服务器被标记为 客观下线。在一般情况下, 每个 Sentinel 会以每 10秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送 INFO 命令。当一个 主服务器 被 Sentinel标记为 客观下线 时,Sentinel 向 下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从10秒一次改为 每秒一次。Sentinel和其他 Sentinel 协商 主节点 的状态,如果 主节点处于 SDOWN`状态,则投票自动选出新的主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。当没有足够数量的 Sentinel 同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向 Sentinel的PING命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。
相关配置: # 哨兵 sentinel 监控的 redis 主节点的 # sentinel monitor <master-name> <ip> <redis-port> <quorum> # 这个2代表,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。 sentinel monitor mymaster 10.201.12.66 6380 2 # 当在Redis实例中开启了requirepass <foobared>,所有连接Redis实例的客户端都要提供密码。 sentinel auth-pass mymaster test@123456 # 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒 # Default is 30 seconds. sentinel down-after-milliseconds mymaster 30000 # 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。 # sentinel parallel-syncs <master-name> <numslaves> sentinel parallel-syncs mymaster 1 # 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面: ## 1. 同一个sentinel对同一个master两次failover之间的间隔时间。 ## 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。 ## 3. 当想要取消一个正在进行的failover时所需要的时间。 ## 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout mymaster 180000
-
集群模式(Cluster Mode)
哨兵模式模式解决了主从模式故障自动恢复问题,但是无法解决主从模式中单节点的储存与访问能力上线问题,集群模式就是把数据进行分片存储,当一个分片数据达到上限的时候,就分成多个分片,集群的键空间被分割为16384个slots(即hash槽)为什么是16384个slots?,通过hash的方式将数据分到不同的分片上的.每个节点负责一部分slots的读写(取模运算).redis cluster mode:
redis 持久化机制
redis数据主要在内存中读写,但是系统故障等情况会导致内存中数据丢失,为了重用数据或防止系统故障,redis提供了数据持久化功能,将内存中的数据写入到磁盘中,redis提供两种数据持久化方式RDB(redis database) AOF(append only file).
-
RDB 数据备份
RDB持久化机制是对redis中数据进行周期性持久化,每次的RDB生成的备份文件代表某一时刻redis的数据,所以想恢复对应时间点的数据可以选取对应时间的RDB快照文件进行恢复,RDB默认备份周期是5分钟(可设置),这就意味着最后一次备份到故障点的时间段数据丢失,RDB机制对redis性能影响很小,因为数据备份时是通过fork一个只线程进行备份的,而且数据恢复也比较快. -
AOF 数据备份
AOF是一秒一次去通过一个后台的线程fsync操作,AOF在对日志文件进行操作的时候是以append-only的方式去写的,他只是追加的方式写数据,自然就少了很多磁盘寻址的开销了,写入性能惊人,文件也不容易破损。AOF文件只有一份文件比较大,数据恢复起来很慢.
实际项目选择文件备份:
如果比较重要的数据,可以考虑两种方式一起做数据备份,如果出现故障,使用RDB文件快速恢复,然后在用AOF文件补全数据.
Redis的过期策略和内存淘汰策略
- 三种常见的过期策略
- 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
- 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
- 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
redis 同时使用惰性过期与定期过期策略.
-
内存淘汰机制
查看redis配置文件可以发现两个配置"maxmemory" 与 "maxmemory-policy",前者指redis占用最大内存数,后者为redis的内存淘汰机制提供六种配置noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外) allkeys-lru:从所有key中使用LRU算法进行淘汰 volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰 allkeys-random:从所有key中随机淘汰数据 volatile-random:从设置了过期时间的key中随机淘汰 volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰 注意:当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误