学习目标:
一、redis是什么?
1.redis是一个内存高速缓存数据库。它不是一个关系型数据库,redis是一个key-value存储系统,Redis是单线程的,基于事件驱动的;
二、redis有什么特点?
1.redis 以内存作为数据存储的截止,读写的效率很高
2.存储在redis中的数据是持久化的,断电之后,数据不会丢失。redis的存储分为内存存储,磁盘存储和log文件,重启后,redis可以从磁盘重新将数据加载到内存中,这个可以通过配置文件进行配置,来实现redis的持久化。
3.redis支持主从模式,配置redis集群,便于支撑更大型的项目。
4.它具有丰富的数据类型,string,list,set,zset(sorted set),hash。
5.redis的所有操作都是原子性的,要么成功执行,要么失败完全不执行。单个操作是原子性的。多个操作也支持事物。
6.redis有着更为复杂的数据结构,并且提供对他们的原子性操作,不同于其他数据库,redis的数据类型基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
7.redis运行在内存中,但是可以持久化到磁盘,所以在对不同数据进行高速读写的时候需要权衡内存,数据量不能大于硬件内存。在内存中的一个优点是,相比在磁盘上复杂的数据结构,内存中操作起来就比较简单。
三、redis的应用场景
众多语言都支持redis,因为redis交换数据比较快,所以在服务其中常用来存储一些需要频繁调取的书记,这样可以大大节省系统直接读取磁盘来获得数据的i/o开销,可以极大提升速度。
拿大型网站来举个例子,比如某网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销
四、redis的数据类型
1.string 是 redis 最基本的类型,而且 string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。从内部实现来看其实 string 可以看作 byte 数组,最大上限是 1G 字节。下面是 string 类型的定义。
set key value 设置 key 对应的值为 string 类型的 value,返回 1 表示成功,0 失败 setnx key value 同上,如果 key 已经存在,返回 0 。nx 是 not exist 的意思 get key 获取 key 对应的 string 值,如果 key 不存在返回 nil getset key value 原子的设置 key 的值,并返回 key 的旧值。如果 key 不存在返回 nil mget key1 key2 ... keyN 一次获取多个 key 的值,如果对应 key 不存在,则对应返回 nil。
2.list 类型实质是一个每个元素都是string类型的双向链表,所以push和pop命令的算法时间复杂度都是O(1),另外list还会记录链表的长度,所以llen操作也是O(1)。链表的最大长度是(2的32次方-1)。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。这使得list既可以用作栈,也可以用作队列。有意思的是list的 pop 操作还有阻塞版本的。当我们[lr]pop一个list对象是,如果list是空,或者不存在,会立即返回nil。但是阻塞版本的b[lr]pop 可以则可以阻塞,当然可以加超时时间,超时后也会返回nil。
lpush key string 在 key 对应 list 的头部添加字符串元素,返回 1 表示成功,0 表示 key 存在且不是 list类型 rpush key string 同上,在尾部添加 lpop key 从 list 的头部删除元素,并返回删除元素。如果 key 对应 list 不存在或者是空返回 nil,如果 key 对应值不是 list 返回错误 rpop key 同上,但是从尾部删除 llen key 返回 key 对应 list 的长度,key 不存在返回 0,如果 key 对应类型不是 list 返回错误 lrange key start end 返回指定区间内的元素,下标从 0 开始,负值表示从后面计算,-1 表示倒数第一个元素 ,key 不存在返回空列表 ltrim key start end 截取 list,保留指定区间内元素,成功返回 1,key 不存在返回错误
3.redis 的 set 是 string 类型的无序集合。 set 元素最大可以包含(2 的 32 次方-1)个元素。 set 的是通 过 hash table 实现的,所以添加,删除,查找的复杂度都是 O(1)。 hash table 会随着添加或者删除自 动的调整大小。需要注意的是调整 hash table 大小时候需要同步(获取写锁)会阻塞其他读写操作。
sadd key value 添加一个 string 元素到,key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0,key 对应的 set 不存在返回错误 srem key value 从 key 对应 set 中移除给定元素,成功返回 1,如果 value 在集合中不存在或者key 不存在返回 0,如果 key 对应的不是 set 类型的值返回错误 spop key 删除并返回 key 对应 set 中随机的一个元素,如果 set 是空或者 key 不存在返回 nil srandmember key 同 spop,随机取 set 中的一个元素,但是不删除元素 smove srckey dstkey value 从 srckey 对应 set 中移除 value 并添加到 dstkey 对应 set 中,整个操作是原子的。成功返回 1,如果 value 在 srckey 中不存在返回 0,如果 key 不是 set 类型返回错误 scard key 返回 set 的元素个数,如果 set 是空或者 key 不存在返回 0 sismember key value 判断 value 是否在 set 中,存在返回 1, 0 表示不存在或者 key 不存在
smembers key 返回 key 对应 set 的所有元素,结果是无序的
4.zset 和 set 一样, sorted set 也是 string 类型元素的集合,不同的是每个元素都会关联一个 double 类型 的 score ,元素顺序有score决定。 sorted set 的实现是 skip list 和 hash table 的混合体。 当元素被添加到集合中时,一个元素到 score 的映射被添加到 hash table 中,所以给定一个元素获取 score 的开销是 O(1),另一个 score 到元素 的映射被添加到 skip list 并按照 score 排序,所以就可以有序的获取集合中的元素。
zadd key score member 添加元素到集合,元素在集合中存在则更新对应 score,当该member已存在时,返回0,并更新该member的score值 zrem key member 删除指定元素, 1 表示成功,如果元素不存在返回 0 zincrby key n member 增加对应 member 的 score 值,然后移动元素并保持 skip list 保持有序。返回更新后的 score 值 zrank key member 返回指定元素在集合中的排名(下标) ,集合中元素是按 score 从小到大排序的 zrevrank key member 同上,但是集合中元素是按 score 从大到小排序 zrange key start end 类似 lrange 操作从集合中去指定区间的元素。返回的是有序结果 zrevrange key start end 同上,返回结果是按 score 逆序的 zrangebyscore key min max 返回集合中 score 在给定区间的元素 zcount key min max 返回集合中 score 在给定区间的数量 zcard key 返回集合中元素个数 zscore key element 返回给定元素对应的 score zremrangebyrank key min max 删除集合中排名在给定区间的元素 zremrangebyscore key min max 删除集合中 score 在给定区间的元素
5.redis hash 是一个 string 类型的 field 和 value 的映射表。它的添加,删除操作都是 O(1) (平均).hash特别适合用于存储对象。相较于将对象的每个字段存成单个 string 类型。将一个对象存储在 hash 类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是新建一个 hash 对象时开始是用 zipmap(又称为 small hash)来存储的。这个 zipmap 其实并不是 hash table,但是 zipmap 相比正常的 hash 实现可以节省不少 hash 本身需要的一些元数据存储开销。尽管 zipmap 的添加,删除,查找都是 O(n),但是由于一般对象的 field 数量都不太多。所以使用 zipmap 也是很快的,也就是说添加删除平均还是 O(1)。如果 field 或者 value 的大小超出一定限制后, redis 会在内部自动将 zipmap替换成正常的 hash 实现. 这个限制可以在配置文件中指定。
hset key field value 设置 hash field 为指定值,如果 key 不存在,则先创建 hget key field 获取指定的 hash field hmget key filed1....fieldN 获取全部指定的 hash filed hmset key filed1 value1 ... filedN valueN 同时设置 hash 的多个 field hincrby key field integer 将指定的 hash filed 加上给定值 hexists key field 测试指定 field 是否存在 hdel key field 删除指定的 hash field hlen key 返回指定 hash 的 field 数量 hkeys key 返回 hash 的所有 field hvals key 返回 hash 的所有 value hgetall key 返回 hash 的所有 filed 和 value
五、什么是Redis缓存穿透,缓存雪崩?
缓存穿透就是查询一个一定不存在的数据时,由于缓存中不存在,每次请求总是穿过缓存,从数据库中查询,造成缓存穿透。
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
六、redis主从复制?
主从复制
Redis主从复制配合和使用比较简单,通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。
master可以拥有多个salve server,多个slave可以连接同一个master外,还可以连接到其他slave。主从复制不会阻塞master,同步数据时,master可以继续处理client,提高系统伸缩性。
Redis主从复制过程:
- Salve与master建立连接,发送sync同步命令。
- Master会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令缓存。
- 后台完成保存后,就将此文件发送给slave。
- slave将此文件保存到硬盘上。
Redis环境说明:
window下Redis服务作为master主机,window的IP为192.168.1.100,虚拟机下linux下的Redis作为slave,linux的IP为192.168.1.150。
在redis从机(linux环境)的redis.conf配置文件中加入以下配置:
主机写入2条记录到数据库,然后从从机中读取,注意:总计无法更新值,只能读取。
master主机 slave从机
七、reids的事物管理?
事务处理
Redis对事务的支持还比较简单,redis只能保证一个client发起的事务中的命令可以连续执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务的上下文,连接后续命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。
在事务处理中使用discard可以取消事务的处理。redis在事务中如果发生错误时事务退出,但是在该错误之前的操作无法回滚。
八、redis的持久化?
九、redis发布、订阅消息?
发布订阅(pub/sub)是一种消息通知模式,主要的目的是截除消息发布者和消息订阅者之间的耦合,Redis作为一个pub/sub的server,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的信息时,订阅该信息类型的全部client都会收到此消息。
第一个redis客户端订阅changnel1,第二个redis客户端订阅channel1和channel2,第三个redis客户端负责产生channel1和channel2消息,然后观察第一个和第二个redis客户端是否收到了订阅消息。
十、AOF和RDB持久化
AOF持久化日志,RDB持久化实体数据,AOF优先级大于RDB。
1.AOF持久化
机制:通过定时事件将aof缓冲区内的数据定时写到磁盘上。
2.AOF重写
为了减少AOF大小,Redis提供了AOF重写功能,这个重写功能做的工作就是创建一个新AOF文件代替老的AOF,并且这个新的AOF文件没有一条冗余指令。(例如对list先插入A/B/C,后删除B/C,再插入D共6条指令,最终状态为A/D,只需1条指令就可以)
实现原理就是读现有数据库的状态,根据状态反推指令,跟之前的AOF无关。同样,为了避免长时间耗时,重写工作放在子进程进行。
3.RDB持久化
SAVE和BGSAVE两个命令都是用于生成RDB文件,区别在于BGSAVE会fork出一个子进程单独进行,不影响Redis处理正常请求。
定时和定次数后进行持久化操作。
简而言之,RDB的过程其实是比较简单的,满足条件后直接去写RDB文件就结束了。