一.redis简介
- redis就是一个非关系型数据库,数据存在内存中,读写速度非常快
- 另外redis经常用来做分布式锁(redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,多个客户端读redis的连接不存在竞争关系)
- redis提供了多种数据类型来支持不同业务场景
- redis支持事务、持久化、LUA脚本、LRU驱动事件
二.为什么要用redis作为缓存
- 高性能:用户通过访问缓存也即内存的速度比访问数据即硬盘的速度要快的多
- 高并发:直接操作缓存能够承受的请求是远远大于直接访问数据库的,可以把一部分数据库的数据转移到缓存中去
三.redis缓存对比map/guava缓存
- redis缓存被称为分布式缓存,可以用几十G做缓存,Map是本地缓存,JVM最多几个G
- Redis 的缓存可以持久化,Map 是内存对象,程序一重启数据就没了
- Redis 有丰富的 API,Map 就简单太多了
- 多实例的情况下,各实例共用一份缓存数据 ,map则不是
四.redis的线程模型
redis 内部使用文件事件处理器 file event handler
,这个文件事件处理器是单线程的,所以 redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qh0VqZlP-1581770667701)(redis%E6%8C%87%E5%AF%BC.assets/9ea86eb5-000a-4281-b948-7b567bd6f1d8-1581764822343.png)]
文件事件处理器的结构包含 4 个部分 :
- 多个 socket
- IO 多路复用程序
- 文件事件分派器
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
五.redis与memcached区别
- redis支持更丰富的数据类型( List,Set,Zset,Hash, String )memcached只支持String
- redis支持数据的持久化:其中两种持久化策略分别是:RDB快照和AOF日志,即可以把内存中的数据保存在磁盘里,重启的时候可以再次加载进内存使用,但是mencached只能把数据全部存在内存中
- Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。
六.redis常用数据结构以及场景
-
String
-
应用场景:
-
保存单个字符串或者JSON字符串,因为String类型是安全的,所以可以把一个图片文件的内容保存。
2.常规计数,微博数,粉丝数,因为incr的原子性,如果同一时间有多个用户读取了某一个key的值,然后对其进行加1,最后结果也一定是正确的。
语法:
set key value //设置指定key的value值 get key //取得key的value值 getrange key start end //返回key对应value字符串的子串(start ,end都包括) mget key1 key2 //获取一个或多个key的值 setex key seconds value //设置key值并且设置过期时间,单位是秒 setlen key //返回key所存储值的长度 incr key //把key存储的值加1 incrby key increment //把key存储的值加上给定increment decr key //把key存储的值减1 decrby key decrement //把key存储的值减去decrement append key value //如果key已经存在并且是一个字符,那么把value追加到key值之后
-
-
Hash
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MugBKgV3-1581770667703)(redis%E6%8C%87%E5%AF%BC.assets/7bd202a7-93d4-4f3a-a878-af68ae25539a.png)]
应用场景:
存储对象,为什么不用String 的JSON去存储呢?因为读取的时候涉及到序列化和反序列化,这个不属于原子性操作,高并发的时候可能造成错误。
语法:
hdel key field1 field2 //删除一个或者多个哈希表字段 hexists key field //查看哈希表key中指定的字段是否存在 hget key field //获取哈希表指定字段的值 hgetall key //获取哈希表指定key所有的字段和值 hincrby key field increment //为哈希表key中指定字段的值加上增量increment hkeys key //获取哈希表key中所有字段 hlen key //获取哈希表key中字段的数量 hmget key //获取哈希表所有给定字段的值 hmset key field1 value1 field2 value2 //同时将多个filed-value设置到哈希表key中
-
List
-
-
应用场景:
微博的关注列表,粉丝列表,消息列表
语法:
blpop key1 key2 timeout //移出并获取列表的第一个元素,如果列表中没有元素会阻塞到超时或者发现可弹出元素为止 brpop key1 key2 timout //移出并获取列表的最后一个元素,如果列表中没有元素会阻塞到超时或者发现可弹出元素为止 lindex key index //通过index获取列表的元素 llen key //获取列表的长度 lpop key //移出并获得列表的第一个元素 lpush key value1 value2 //将一个或多个value插入到列表头部 lrange key start end //获取列表指定范围的值 lset key index value //通过索引设置列表元素的值
-
set:
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySFvW4bc-1581770667704)(redis%E6%8C%87%E5%AF%BC.assets/cd5fbcff-3f35-43a6-8ffa-082a93ce0f0e.png)]
-
应用场景:
共同关注、共同粉丝、共同喜好
sismember s1 a :查看s1集合中a是否存在,用来验证用户的
srandmember s1 3:随机输出s1中3个成员,用来抽奖
语法:
sadd key member1 member2 //向集合添加一个或者多个元素 scard key //获取集合的成员数 sdiff key1 key2 //返回给定所有集合的差集 sinter key1 key2 //返回给定给定集合的交集 sismember key member //查看member是否是key的成员 smembers key //返回key中所有的成员 srandmember key count //返回集合key中一个或者多个成员 sunion key1 key2 //返回所有给定集合的并集
-
ZSet
应用场景:
直播间在线用户列表,各种礼物排行榜,弹幕消息
语法:
zadd key score1 member1 score member2 //向有序集合添加一个或者多个成员,或者更新已存在成员的分数 zcard key //获取有序集合的成员数 zcount key min max //计算在有序集合中指定区间的成员数 zincrby key increment member //有序集合对指定成员的分数上加上increment zrank key member //返回指定成员的索引 zrem key member1 member2 //移除集合中成员1和成员2 zscore key member //返回指定成员的分数值
七.redis设置键过期事件的必要性
- 安全性 :短信验证码
- 可用性:定期随机删除或者惰性删除
八.redis持久化机制
- RDB(快照持久化)
可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。
2.AOF( 只追加文件 持久化)
AOF持久化 的实时性更好,因此已成为主流的持久化方案。
九.redis事务
1.什么是Redis事务:
redis事务指一次可以执行多个命令(按顺序去执行,执行过程中不允许其他命令插入,也不允许加塞)
2.常用命令:
MULTI:标记一个事务块的开始
EXEC:执行事务块内的所有命令
DISCARD:取消事务,放弃执行事务块内的命令
WATCH:监视一个key,如果执行这个事务之前被其他命令所改动,那么这个事务就不会执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpQsBLEe-1581770667705)(redis%E6%8C%87%E5%AF%BC.assets/image-20200215151316808.png)]
3.一个事务从开始到执行会经历以下阶段:
开始事务-------》命令入队-------------》执行事务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CdtRGVgT-1581770667705)(redis%E6%8C%87%E5%AF%BC.assets/image-20200215140825596.png)]
4.事务的错误处理:
1.如果出现错误事务,那么出现错误的命名不会执行,其他的事务还是会继续执行的,但是不会回滚。类似于去商店买东西,买了一些,发现有一个过期的商品,这个时候不会把所有的商品都丢弃
2.如果队列中的某个命令出现了报告错误,那么执行整个队列都会取消。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Id3zdFg1-1581770667706)(redis%E6%8C%87%E5%AF%BC.assets/image-20200215144446229.png)]
5.事务的应用场景:
秒杀
十.缓存雪崩和缓存穿透
1.什么是缓存雪崩
缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
2.什么是缓存穿透
大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。
十一.Redis其他命令
keys * :取出所有的key
exists key:是否存在指定的key,如果满足返回1,否则返回0
expire key time:设置key的过期时间,默认单位是秒
del key:删除某个key
rename key key2:对key进行重命名
type key:返回key的类型
ttl key:查看key是否过期,-1代表永久有效,-2代表失效
kill -9 pid:对查询的pid强制关闭
select 8:选择第八个数据库
十二.一个简单的论坛系统分析
该系统的功能如下:
- 可以发布文章
- 可以对文章进行点赞
- 可以按文章的发布时间和点赞数进行排名
文章信息:
文章包括标题,作者和点赞数,因此在redis用hash来存储这种数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nAKe8OKU-1581770667707)(redis%E6%8C%87%E5%AF%BC.assets/7c54de21-e2ff-402e-bc42-4037de1c1592.png)]
点赞功能:
当有用户进行点赞时,应对问斩的votes进行加1,还必须记录此用户已经对该文章进行了点赞,因此可以建立已投票用户集合来进行标记,同时为了节约内存,规定当文章发布满一周之后,就不可以进行投票,因此已投票结合就会被删除,我们可以设置一个过期时间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQZgAxf5-1581770667707)(redis%E6%8C%87%E5%AF%BC.assets/485fdf34-ccf8-4185-97c6-17374ee719a0.png)]
对文章进行排序:
为了对发布时间和点赞数进行排序,我们需要建立一个文章发布时间的有序集合和点赞数的有序集合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lc1dF1Cr-1581770667708)(redis%E6%8C%87%E5%AF%BC.assets/f7d170a3-e446-4a64-ac2d-cb95028f81a8.png)]
参考资料
[https://cyc2018.github.io/CS-Notes/#/notes/Redis?id=%e5%8d%81%e5%9b%9b%e3%80%81%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e8%ae%ba%e5%9d%9b%e7%b3%bb%e7%bb%9f%e5%88%86%e6%9e%90](https://cyc2018.github.io/CS-Notes/#/notes/Redis?id=%e5%8d%81%e5%9b%9b%e3%80%81%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e8%ae%ba%e5%9d%9b%e7%b3%bb%e7%bb%9f%e5%88%86%e6%9e%90)