一、Redis数据结构
(1)string(字符串)
可以是保存字符串、整数和浮点数。
(2)list(列表)
它是一个链表,它的每一个节点都包含一个字符串。
(3)set(集合)
它是一个收集器,但是是无需的,在它里面每一个元素都是一个字符串,而且是独一无二的,各不相同的。
(4)hash(哈希散列表)
它类似于Java语言中的Map,是一个键值对应的无序列表。
(5)zset(有序集合)
它是一个有序的集合,可以包含字符串、整数、浮点数、分值(score),元素的排序是依据分值的大小来决定的。Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
(6)HyperLogLog(基数)
它的作用是计算重复的值,已确定存储的数量。在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
基数:比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
二、Redis的基础事务
开始事务是multi命令,而执行事务是exec命令,事务回滚是discard命令。
Redis事务机制:multi到exec命令之间的Redis命令将采取进入队列的形式,直至exec
命令的出现,才会一次性发送队列的命令去执行,而在执行这些命令的时候其他客户端就不能再插入任何命令了。
Redis在执行事务的过程中,并不会阻塞其他连接的并发,而只是通过比较watch监控的键值对去保证数据的一致性(采用CAS),Redis多个事务完全可以在非阻塞的多线程环境中并发执行,而且Redis的机制是不会产生ABA问题的,保证数据一致的基础上,提高高并发系统的数据读/写性能。
三、Redis备份持久化
快照(snapshotting):备份当前瞬间Redis在内存中的数据记录。如果当前Redis的数据量大,备份可能造成Redis卡顿,但是恢复重启是比较快速的。
只追加文件(Append-Only File,AOF):当Redis执行写命令后,在一定的条件下将执行过的写命令依次保存在Redis的文件中,将来就可以依次执行那些保存的命令恢复Redis的数据了。这种方式的备份只是追加写入命令,所以备份一般不会造成Redis卡顿,但是恢复重启要执行更多的命令,备份文件可能也很大,使用者使用的时候要注意。
以上备份方式Redis允许使用其中一种、两种同时使用或者两种都不用。用户可以通过配置决定。
使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。有以下同步选项:
选项 | 同步频率 |
always | 每个写命令都同步 |
everysec | 每秒同步一次 |
no | 让操作系统来决定何时同步 |
- always 选项会严重减低服务器的性能;
- everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
- no 选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。
随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。
Redis执行快照备份(save)命令的时候,将禁止写入命令。
Redis使用bgsave 异步执行快照备份(另一个线程执行备份)
四、Redis超时命令
Redis的key超时不会被其自动回收,它只会标识哪些键值对超时了。
这样做的好处在于,如果一个很大的键值对超时,比如一个列表或者哈希结构,存在数以百万个元素,要对其回收需要很长的时间。如果采用超时回收,则可能产生停顿。当然坏处也很明显,这些超时的键值对会浪费比较多的空间。
Redis提供两种方式回收这些超时键值对,它们是定时回收和惰性回收。
- 定时回收是指在确定的某个时间触发一段代码,回收超时的键值对。
- 惰性回收则是当一个超时的键,被再次用get命令访问时,将触发Redis将其从内存中清空。
- 定期删除:每隔一段时间,对 expires 字典进行检查,删除里面的过期键。
定时回收可以完全回收那些超时的键值对,但是确定也很明显,如果这些键值对比较多,则Redis需要运行较长的时间,从而导致停顿。所以系统设计者一般会选择在没有业务发生的时刻触发Redis的定时回收,以便清理超时的键值对。对于惰性回收而言,它的优势是可以指定回收超时的键值对,它的缺点是要执行一个莫名其妙的get操作,或者在某些时候,我们也难以判断哪些键值对已经超时。
Redis使用定期删除加惰性删除策略回收超时键值对。
五、Redis内存回收策略
当Redis的内存达到规定的最大值时,允许配置6种策略中的一种进行淘汰键值,并且将一些键值对进行回收。
策略 | 描述 |
volatile-lru | 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 |
volatile-ttl | 从已设置过期时间的数据集中挑选将要过期的数据淘汰 |
volatile-random | 从已设置过期时间的数据集中任意选择数据淘汰 |
allkeys-lru | 从所有数据集中挑选最近最少使用的数据淘汰 |
allkeys-random | 从所有数据集中任意选择数据进行淘汰 |
noeviction | 禁止驱逐数据 |
注意:LRU算法或者TTL算法都不是很精确算法,而是一个近似的算法。Redis不会通过对全部的键值对进行比较来确定最精确的时间值,从而确定删除那个键值对,因为浙江消耗太多的时间,到时回收垃圾执行时间太长,造成服务器停顿。
六、复制、主从同步
主从同步基础:读写分离,设置一个主服务器,主服务器负责写,数据通过同步机制写入从服务器。从服务器负责读,返回数据给应用。
Redis主从同步配置:从服务器在配置文件(redis.conf)中配置格式 -- slaveof server (主服务器IP)port(端口)。在实际开发中还需配置bind 0.0.0.0 (允许所以IP访问)
连接过程
1.主服务器创建快照文件,发送给从服务器,并在发送期间使用缓冲区记录执行的写命令。快照文件发送完毕之后,开始向从服务器发送存储在缓冲区中的写命令;
2.从服务器丢弃所有旧数据,载入主服务器发来的快照文件,之后从服务器开始接受主服务器发来的写命令;
3.主服务器每执行一次写命令,就向从服务器发送相同的写命令。
主从链
随着负载不断上升,主服务器可能无法很快地更新所有从服务器,或者重新连接和重新同步从服务器将导致系统超载。为了解决这个问题,可以创建一个中间层来分担主服务器的复制工作。中间层的服务器是最上层服务器的从服务器,又是最下层服务器的主服务器。
七、哨兵模式
Redis可以存在多台服务器,并且实现了主从复制的功能。哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,他会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵有两个作用:
- 通过发送命令,让Redis服务器返回监测其运行状态,包括主服务器和从服务器。
- 当哨兵监测到master宕机,会自动将slave切换为master,然后通过发布订阅模式通知到其他的从服务器,修改配置文件,让它们切换主机。
每一台服务器都可以配置哨兵,在哨兵配置文件sentinel.cof中配置当多少个或以上哨兵投票认可当前主服务器不可用后,才会进行故障切换,这样可以降低因出错而切换主服务器的概率。
各服务器启动顺序(不可改变)----主机的Redis服务进程—>从机的服务进程—>最后启动一个或多个哨兵进程