Redis 是一个基于内存的高性能key-value数据库
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘,
所以Redis具有快速和数据持久化的特征,如果数据放在内存中 磁盘I/O速度为严重影响redis的性能
Redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
Redis的持久化有2种方式 1快照 2日志
RDB是快照方式是在一定间隔时间做一次的产生快照
AOF的默认持久化策略是每秒钟fsync一次,fsync是指把缓存中的写指令记录到磁盘中
一、Redis的好处
(1) 速度快,因为数据存在内存中
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
二、redis相比memcached的优势
(1) memcached的值均是简单的字符串,redis支持更为丰富的数据类型
(2) redis的速度比memcached快 (单Memcache使用的libevent库,而Redis则原生使用epoll异步通信模型)
2.1、Redis 单线程模型也能效率比Memcached这么高?
Redis则原生使用epoll异步通信模型 (核心是基于非阻塞的 IO 多路复用机制)
Redis单线程避免了多线程的频繁上下文切换问题
(3) 可以持久化其数据,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
(4) Redis支持数据的备份,即master-slave模式的数据备份
三、常见性能问题和解决方案
(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
Master RDB写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照
(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度
(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象
将no-appendfsync-on-rewrite的配置设为yes可以缓解这个问题,设置为yes表示rewrite期间对新写操作不fsync同步,等rewrite完成后再写入。最好是不 开启Master的AOF备份功能
(4) 单点故障问题,Redis的主从复制还不够成熟,所以存在明显的单点故障问题
为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定
四、最适合的场景
(1) 会话缓存
Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失 也不会带来大的影响
(2) 全页缓存 FPC
除基本的会话token之外,Redis还提供很简便的FPC平台
Magento提供一个插件来使用Redis作为全页缓存后端,此外Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面
(3) 队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用
(4) 排行榜/计数器
集合(Set)和有序集合(Sorted Set)使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构
例:排序ZRANGE, 防止刷单/秒杀活动 INCR
五、Redis的并发竞争问题解决方式
Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争
但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成
2种解决方法:·····························································
(1) 客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,
同时对客户端读写Redis操作采用内部锁synchronized
(2) 服务器角度,利用setnx实现锁
第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;
六、持久化的几种方式
(1) RDB快照
Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb
可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者可以手工调用命令SAVE或BGSAVE
(2) AOF写日志
默认持久化策略是每秒钟fsync一次, 修改配置文件reds.conf: appendonly yes 开启
可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据;
如果日志写入不完整支持redis-check-aof来进行日志修复
AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)
快照模式并不十分健壮,当系统停止,或者无意中Redis被kill掉,最后写入Redis的数据就会丢失
对于要求高可靠性的应用,不是一个合适的选择。AOF文件比RDB文件大,且恢复速度慢
(3) 虚拟内存方式
七、缓存失效策略和主键失效机制
作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略.
有生存期的key被称为volatile。在创建缓存时,要为给定的key设置生存期,当key过期的时候(生存期为0),它可能会被删除
(1) 影响生存时间的一些操作
修改key对应的value或使用相同k v 覆盖旧的数据 则生存时间刷新
对一个 key 执行INCR命令,对一个列表进行LPUSH命令,或者对一个哈希表执行HSET命令,这类操作都不会修改 key 本身的生存时间
使用RENAME对一个 key 进行改名,那么改名后的 key的生存时间和改名前一样。
(2) 如何更新生存时间
对一个已经带有生存时间的 key 执行EXPIRE命令,新指定的生存时间会取代旧的生存时间.主键失效的时间复杂度是O(1)
EXPIRE和TTL命令搭配使用,TTL可以查看key的当前生存时间。设置成功返回 1;当 key 不存在或者不能为 key 设置生存时间时,返回 0
最大缓存配置:
Redis 中,允许用户设置最大使用内存大小,server.maxmemory默认为0,没有指定最大缓存
如果有新的数据添加,超过最大内存,则会使redis崩溃,所以一定要设置
配置最大缓存后,redis 内存数据集大小上升到一定大小的时候,就会实行数据淘汰策略
6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
三种数据淘汰策略:
TTL (将要过期)
Random (随机)
Lru最近最少使用淘汰策略,设计上会对key 按失效时间排序,然后取最先失效的key进行淘汰
八、主要功能
(1) 哨兵(Sentinel)和复制(Replication)
哨兵Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的功能,复制Replication则是负责让一个Redis服务器可以配备多个备份的服务器
(2) 事务
多情况下需要一次执行不止一个命令,而且需要其同时成功或者失败。即支持一次性按顺序执行多个命令的能力,并保证其原子性
(3) LUA脚本
执行更复杂的操作(包含一些逻辑判断)脚本
(4) 持久化
把内存的中的数据写入到硬盘中,在redis重新启动的时候加载这些数据
(5) 集群(Cluster)
通过主从复制,进行读写分离,把一部分CPU和IO的压力转移到从服务器上
有twemproxy和codis两种方案,这两个方案总体上都是依赖proxy来进行分布式的