目录
一.Redis概述
1.概述
2.官网
二.Redis安装配置和启动
1.安装c语言需要的gcc环境
2.下载并解压缩 Redis 源码压缩包
3.编译 Redis 源码
4.启动redis
三.Redis数据类型
1.redis中key的设计规范
2.string类型
3.hash类型(散列表key field value)
4.list类型(列表)
5.set类型(无序集合)
6.sortedset类型(有序集合)
四.Redis持久化
1.RDB
2.AOF
3.持久化优先级
4.redis的rdb bgsave存储的数据是拷贝给子进程的吗?
5.redis持久化最佳实践
五.Redis过期删除策略
1.设置redis键的过期时间 【EXPIRE key 过期时间】
2.查询redis键的过期时间【TTL key】
3.删除键的过期时间【PERSIST key】
4.过期删除策略
六.Reids实现分布式锁
1.引入依赖
2.配置文件
3.代码示例(推荐使用redisson)
七.Redis使用lua脚本
1.redis使用lua的方式
2.eval命令
3.Lua脚本汇总调用redis命令
4.Linux命令行使用lua脚本
八.布隆过滤器
1.redis安装布隆过滤器
2.使用
九.RedisTemplate常用语法
十.Redis的经典面试题
1.缓存穿透
2.缓存击穿
3.缓存雪崩
1.概述
Redis是一个使用C语言开发的内存数据库,Redis 除了做缓存之外,也经常用来做分布式锁。Redis提供了多种数据类型来支持不同的业务场景,还支持事务、持久化、Lua脚本、多种集群方案。
2.官网
(1)官网:https://redis.io/
(2)中文官网:http://www.redis.cn/
1.安装c语言需要的gcc环境
2.下载并解压缩 Redis 源码压缩包
3.编译 Redis 源码
执行完毕后redis就安装成功啦!
4.启动redis
不推荐直接前台启动,窗口关闭redis也随之关闭了下面介绍后台启动redis
后台启动步骤(守护进程):
(1)修改redis.conf文件
<1>修改daemonize no ---> daemonize yes,目的是为了让redis启动在linux后台运行
<2>修改redis的工作目录:(名称随意)
<3>修改bind地址(不修改可能别的机器连接不上)
ip改为给本机分配的ip
(2)进入bin目录启动服务(如果是src目录重命名为bin)
(3)查看redis是否启动成功
(4)后台启动的关闭方式
进入bin目录执行以下命令
(5)bin目录下命令说明
(6)命令行方式开启客户端
1.redis中key的设计规范
(1)可读性
以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如 业务名:表名:id
(2)简洁性
<1>保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:
<2>不要包含特殊字符,比如空格、换行、单双引号以及其他转义字符。
(3)避免bigkey
<1>为了避免String类型的bigkey,尽量把String类型的大小控制在10KB以下。
<2>为了避免集合类型的bigkey,对应的设计规范是,尽量把集合类型的元素个数控制在1万以下。
2.string类型
string 数据结构是简单的 key-value 类型。
set,get,strlen,exists,decr,incr,setnx
(3)一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等等。
(4)string类型实际应用
单值缓存
set key value
get key
对象缓存
set user:1 value(json格式数据) 【使用 表名:id 作为key】
eg:set user:1 '{"name":"zs","age":23}'
分布式锁
SETNX product:10001 true // 返回1代表获取锁成功
SETNX product:10001 false // 返回0代表获取锁失败
.......执行业务操作
DEL product:10001 // 执行完业务 释放锁
SET product:10001 true ex 10 nx // 防止程序意外终止导致死锁
计数器
INCR article:readcount:101
3.hash类型(散列表key field value)
hash是一个string类型的field和value的映射表,特别适合用于存储对象。比string类型存储对象更节省空间,对于内存和cpu的消耗也更小。
(2)常用命令
hset,hmset,hexists,hget,hgetall,hkeys,hvals 等。
系统中对象数据的存储。
(4)hash类型实际应用
对象操作
key:购物车:用户id
field:商品id
value:商品数量
<1>添加1件商品:hset cart:1001 10088 1
<2>增加1件商品:hincrby cart:1001 10088 1
<3>商品总数: hlen cart:1001
<4> 删除商品:hdel cart:1001 10088
<5>获取购物车所有商品: hgetall cart:1001
4.list类型(列表)
Redis的list的实现为一个双向链表
rpush,lpop,lpush,rpop,lrange、llen 等。
发布订阅或消息队列、慢查询,比如:微博、朋友圈、公众号等,关注的文章列表展示。
(4)list类型实际应用
公众号文章列表展示:key是msg:tangbb:id value是文章id
lpush msg:tangbb:001 10010 从左边存入id为10010的文章
lpush msg:tangbb:001 10011 从左边存入id为10011的文章
lrange msg:tangbb:001 0 1 从左边查询最新的数据start为0end为1
5.set类型(无序集合)
redis中set类似于java中的Hashset,当你想存储一个不重复的列表数据,set是一个很好的选择,并且set可以轻易的实现并集、交集、差集的操作,set是无需的。
sadd,spop,smembers,sismember,scard,sinterstore,sunion 等。
(3)使用场景
需要存放的数据不能重复以及需要获取多个数据源交集和并集等场景。比如共同关注、共同粉丝、共同喜好等功能。
(4)set类型实际应用
微信抽奖小程序
<1>点击参与抽奖 讲参与者id加入集合 [sadd key value1 value2...]
sadd wxward 001 002 003 004 005
<2>查询参与者id [smembers key]
smembers wxward
<3>抽出2名中奖者 [SRANDMEMBER key count] [SPOP key count]
SRANDMEMBER wxward 2 随机选择2个,不会移除数据
SPOP wxward 2 随机选择2个,并移除数据
并集交集差集
set1 [a,b,c]
set2 [b,c,d]
set3 [c,d,e]
交集:SINTER set1 set2 set3 [c]
并集:SUNIOn set1 set2 set3 [a,b,c,d,e]
差集:SDIFF set1 set2 set3 [a]
差集计算方式:set1 - (set2并set3)=[a,b,c]-[b,c,d,e] = [a] 只保留a中单独存在的元素
共同关注A的人:可以用交集来实现
我可能认识的人:可以使用差集来实现,把我关注的人求差集
6.sortedset类型(有序集合)
和 set 相比,sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。
zadd,zcard,zscore,zrange,zrevrange,zrem 等。
需要对数据根据某个权重进行排序的场景。比如排行榜等。
(4)sortedset类型实际应用
百度热搜榜
<1>添加热搜数据 [ zadd key score value ]
zadd hotnews 1 iPhone14或将采用叹号屏
<2>点击新闻为其数值+1 [ zincrby key score value ]
zincrby hotnews 1 iPhone14或将采用叹号屏
<3>展示当日排行前10[ zrevrange key start end]
zrevrange hotnews 0 9
1.RDB
在指定的时间间隔能对你的数据进行快照存储,保存文件的后缀是 .rdb。
(2)RDB的触发
<1> save和bgsave命令都可以生成rdb文件
<2> redis.conf配置自动触发规则
(3)RDB总结
2.AOF
记录每次对服务器写的操作(命令),当服务器重启的时候会重新执行这些命令来恢复原始的数据,文件结尾是 .aof 。(默认不开启)
(2)AOF开启和触发
开启配置redis.conf
触发规则配置redis.conf
(3)AOF原理
AOF执行步骤如下:
3.持久化优先级
如果既有RDB文件又有AOF文件优先加载谁?
答:如果有AOF,优先加载AOF执行备份。如果没有AOF,加载RDB执行备份。
4.redis的rdb bgsave存储的数据是拷贝给子进程的吗?
答:不是拷贝给子进程,(内存使用率超过50%,直接拷贝不就gg了)
是通过写实复制实现的
5.redis持久化最佳实践
混合使用RDB和AOF,内存快照以一定的频率执行,在两次快照之间使用AOF记录这期间的所有命令操作。
1.设置redis键的过期时间 【EXPIRE key 过期时间】
(1)EXPIRE :表示将键 key 的生存时间设置为 ttl 秒。
(2)PEXPIRE :表示将键 key 的生存时间设置为 ttl 毫秒。
(3)EXPIREAT :表示将键 key 的生存时间设置为 timestamp 所指定的秒数时间戳。
(4)PEXPIREAT :表示将键 key 的生存时间设置为 timestamp 所指定的毫秒数时间戳。
2.查询redis键的过期时间【TTL key】
(1)TTL :以秒的单位返回键 key 的剩余生存时间。
(2)PTTL :以毫秒的单位返回键 key 的剩余生存时间。
3.删除键的过期时间【PERSIST key】
PERSIST :表示将key的过期时间移除。
4.过期删除策略
(1)定时删除:在设置某个key的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。
(2)惰性删除:设置该key过期时间后,当需要该key时,再检查其是否过期,如果过期就删掉它,反之返回该key。
(3)定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key。
1.引入依赖
2.配置文件
3.代码示例(推荐使用redisson)
1.redis使用lua的方式
使用eval命令对lua脚本进行求值
2.eval命令
(2)参数解释
(3)eval实例
3.Lua脚本汇总调用redis命令
(1)redis.call(),返回值就是redis命令执行的返回值,如果出错,则返回错误信息,不继续执行
(2)redis.pcall(),返回值就是redis命令执行的返回值,如果出错,则记录错误信息,继续执行
实例
4.Linux命令行使用lua脚本
eval 后面参数是lua脚本文件, .lua 后缀。
不用写 numkeys ,而是使用 , 隔开。注意 , 前后有空格。
(2)实例:使用lua脚本实现将一个数字原子性乘以N倍,且运行过程不会被其他客户端打断。
新建test.lua文件,上传到redis的bin目录下(其他目录也可以,记住就行)
1.redis安装布隆过滤器
插件形式安装
在redis布隆过滤器插件地址下载最新的release源码,在编译服务器进行解压编译
解压插件进行插件的编译
编译得到动态库 启动redis时,如下启动即可加载bloom filter插件
配置文件形式配置
启动命令挂载
2.使用
1.通过redisson实现布隆过滤器代码示例如下(存在返回ture,不存在返回false)
布隆过滤器判断存在,则有可能存在
布隆过滤器判断不存在,则一定不存在
1.redisTemplate.opsForValue();//操作字符串
2.redisTemplate.opsForHash();//操作hash
3.redisTemplate.opsForList();//操作list
4.redisTemplate.opsForSet();//操作set
5.redisTemplate.opsForZSet();//操作有序set
1.缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,造成数据库的压力倍增的情况。
对于数据库中没有的数据我们设置一个默认值,比如id为-1时,我们仍将空值设置到缓存,并给其一个失效时间。
2.缓存击穿
redis的一个key过期后,有大量用户请求这个key的数据,导致这些请求去访问数据库,造成数据库压力倍增,针对一个key而言。
设置热点key永不过期。
3.缓存雪崩
redis中多个key同时过期,这时有大量用户请求这些key的数据,导致这些请求去访问数据库,造成数据库压力倍增,针对多个key而言。