一、Redis支持的类型:
String,List,Set,Zset,Map
String类型的对象:
对应的对象编码:
int:long长度范围内的整数。
embstr:长度小于40的数字和字符。一次分配,内存连续,访问速度快。
raw:两次分配,内存不连续,访问速度不快,对内存要求不高。
常用命令:
set no_1 muse //保存
get no_1/del no_1 //获取删除
expire no_1 10 //设置过期时间为10s
ttl no_1 //查看还有多长时间过期
setex no_1 10 muse //保存并设置过期时间
setnx no_1 muse no_1 //不存在才能set成功
strlen no_1 //获取no_1长度
incr no_1 //将no_1+1
incrby no_1 10 //+10
mset no_1 muse no_2 bob //插入多个
mget no_1 no_2 //获取多个
object encoding no_1 //获取key对应value的类型
List类型的对象
对应的对象编码:
ziplist:所有元素长度都小于65个字节,列表中元素个数小于512个;连续存储
linkedlist:否则;双向链表
常用命令:
lpush/rpush msg_queue msg1 msg2 //插入
lpop/rpop msg_queue //弹出
lrang msg_queue 0 -1 //查看整个list的值
llen msg_queque //查看长度
lindex msg_queue 1 //查询对应下标的元素
ltrim msg_queue 0 1 //只保存对应范围的数据其他删除
ltrim msg_queue 1 0 //start>end所有都删除
Set类型对象
对应的对象编码:
intset:纯数字,并且列表中元素个数不超过512个
ht:否则
常用命令:
添加的是字符类型,输出乱序;添加的是数字类型,升序存储
sadd user bob muse muse //会去重
smembers user //查看所有的数据
sismember user muse //查看是否有对应值
scard user //查看元素个数
spop user //随机弹出
del user //删除
zset类型的对象(带分数)
对应的对象编码:
ziplist:所有元素长度都小于65个字节,列表中元素个数小于128个;连续存储
skiplist:否则
常用命令:
zadd score 111 muse 140 bob 90 muse //后边赋值同一个会覆盖
zscore score muse //查muse的分数
zrange score 0 -1 //根据分数正序输出
zrangebyscore score -inf +inf withscores//正序输出 带分数
zrevrange score 0 -1 //降序输出
zrangebyscore score (100 120 //输出指定分数范围,不包含100
zcard score //查个数
zrem score muse //删除指定元素
Hash类型的对象
对应的对象编码:
ziplist: key和value的长度都不超过64,且键值对小于52个
ht:否则
二、Redis数据结构
1.SDS简单动态字符串
优点:可以直接返回长度;采用空间预分配和惰性空间释放
2.list双向链表:
3.hash
4.dict 字典
包含hash表
5.skiplist跳表
三、Redis持久化
RDB持久化:
产生的是一个经过压缩的二进制文件dump.rdb,保存在磁盘上,也可以用它来还原数据库的数据。分为手工执行和服务器定期执行。
1.手工执行RDB保存的命令:
save:阻塞redis服务器进程,RDB文件生成之前不能处理其他redis命令
bgsave:fork一个子进程生成RDB文件,不会阻塞。bgsave执行条件检测器servercron,servercron默认每100毫秒执行一次条件验证,符合条件执行bgsave
900秒之内修改一次/300秒10次/60秒10000次 满足任一执行bgsave
2.RDB加载:
只要Redis启动时检测到RDB文件的存在,就会自动加载,加载过程处于阻塞状态。
AOF更新频率比RDB高,只要服务器开启了AOF就优先加载AOF文件。
AOF持久化:
通过保存Redis执行命令来记录数据库数据变更。
AOF需要在配置文件中通过appendonly yes命令打开
1.持久化流程:
文件事件负责先执行写指令,再保存写命令到aof_buf缓冲区的末尾(文件写入)然后再同步到磁盘AOF文件中(文件同步)。
当每次一个事件循环结束之前,都会调用 flushAppendOnlyFile函数,来判断是否需要 将aof_buf缓冲区中的内容写入和同步到AOF 文件中,flushAppendOnlyFile函数的行为由 appendfsync配置决定。appendfsync的值如下:
always:写入并同步,最慢最安全
everysec:写入,同步操作距离上一次超过1秒则子线程同步
no:写入不同步,同步由OS决定,最快不安全
操作系统提供了fsync和fdatasync两个同步函数,它们可以强制让操作系统立即 将缓冲区中的数据写入到磁盘里,从而确保写入数据的安全性。
2.加载流程
创建一个伪客户端执行aof文件中的写命令,恢复关闭前的数据
3.重写
会有对同一数据的增加删除操作,会有冗余的语句,针对最终redis数据库进行aof重写
重写相关配置:auto-aof-rewrite-percentage 100比上一次aof文件大一倍
auto-aof-rewrite-min-size 64mb aof文件大于64
子进程执行aof重写的时候,进行的redis数据操作暂时存入aof重写缓存区。当aof重写执行完毕给父进程发送信号,阻塞服务器此时不能操作数据库,然后将aof重写缓存区的数据补充刷到aof文件中。然后新aof文件覆盖旧aof文件
四、Redis特殊的数据类型
1.geospatial地理位置:
查询两地之间距离,方圆几里存在的位置等。zset存储
命令:
geoadd city 116 40 beijing //添加经纬度城市
geodist city beijing shanghai km //北京上海距离多少千米
geohash city beijing //北京的经纬度转换为hash
geopos city beijing //北京经纬度
georadius city 116 40 5000 km withcoord withdist asc//116 40 距离5000以内的城市经纬度和距离
georadiusbymember city beijing 100 km//北京方圆100km
2.hyperloglog预估集合的基数:
用于非精准性的统计计数,例如商品浏览量,只需要12kb内存,自动去重
命令:
pfadd user muse tony bob//添加
pfcount user//查数量
pfmerge alluser user1 user2//合并两个集合
3.bitmap位图:
利用二进制0或1,实现是或否的操作。比如记录每个用户当天是否打卡,占用空间特别小。
setbit muse 5 1 //muse 第五天打卡
bitcount muse //muse几个1
getbit muse 5//第五天的值
五、事务管理
保证指令的原子性,中间不被其他命令加塞
multi//开始事务
exec//执行事务
discard//放弃事务
watch acount//事务前执行监视acount在事务中不被其他改变否则事务不生效,时效1次,事务开始之前需要再watch一遍
事务中异常的处理:
语法错误:整个事务执行中断
操作错误:该条指令失败,不影响其他
六、订阅发布
发布者发布一条消息到channel中,所有订阅了这个channel的订阅者都能收到这条信息
七、Redis主从复制
将一台Redis服务器的数据复制到其他Redis服务器,主写从读
用处:数据冗余,故障恢复,负载均衡,高可用(哨兵)
命令配置从节点:slaveof host port
断开主节点:slaveof no one
配置文件配置从节点:replicaof host port
sync阶段:从节点启动后发送sync命令给主节点,要求全量同步。主执行bgsave生成rdb发送给从
command propagate阶段:
后续主接收到增删改,从也需要接收同步
psync:网络断同步失败再同步的时候,确定执行全量重同步还是分量重同步。从节点的复制偏移量在复制积压缓冲区中找到相应待同步数据,不是第一次同步就分量重同步
主发给从n,主节点偏移量+n,从接收n,从节点偏移量+n。从把节点偏移量定期发给主。
复制积压缓冲区是由主节点维护的一个固定长度(默认1MB)的队列。它存储了每个字节值与对应的复制偏移量。因为复制积压缓冲区的大小是固定的,所以它保存的是主节点近期执行的写命令。
节点id来判断是不是第一个连接,连接成功主把节点id给从,断开重连的时候从给主发节点id。
八、Redis哨兵
解决主挂掉,从变为主的问题(修改配置文件)实际就是一个redis实例
原理:哨兵是一个独立的进程通过发送命令,等待Redis服务器响应,监控运行的多个Redis实例
多哨兵模式:由于担心哨兵挂掉,会配置多个哨兵,哨兵之间也会互相监控
判断主是否下线:
主观下线:一个哨兵判断为下线
客观下线:哨兵通知其他判断,超过半数认为下线
选新主流程:选择slave-priority最高,选择复制偏移量offset最大,选择run_id(最先开启)最小的
九、Redis Cluster
redis默认数据库16个
去中心化分片集群,代替主从+哨兵的,多主多从,将数据分片,分散到多个主节点(不同主机),突破了单机内存限制,至少3主3从,每个节点都和其他节点互连。
分片方式:
1.哈希取模
只要hash计算出来的值够散列,key就可以均匀分布到n个节点,缺点扩容缩容需要重新计算
2.一致性哈希
将整个哈希值空间组织成一个虚拟的圆环,0~2^32-1,对key计算hash值,确定在环上的位置,沿着环顺时针走到第一个节点
3.虚拟节点+一致性哈希
一个集群包含16384个虚拟节点(槽位),数据到虚拟节点,虚拟节点到实际节点
redis-cli --cluster check 172.17.0.2:6379//
reids-cli --cluster fix 172.17.0.2:6379 //配置完集群报错,检查分配槽位
十、常见面试题
1.缓存穿透(查不到数据)
缓存没命中,查到DB
解决方案:
1》当数据库中也查不到数据时,将返回的空对象也缓存起来,同时设置一个过期时间。之后再访问这个数据就从缓存中获取
2》布隆过滤器:可以判断某个数据一定不存在,但是无法判断一定存在
是一个很长的二进制向量和很多hash函数。
存一个数据x,会把x传入每个函数散列到二进制向量中。
2.缓存击穿
缓存中的热点key突然过期,就会访问数据库
解决方案:
设置热点key永不过期;加互斥锁,过期后保证对每个热点key同时只有一个线程去查询db,并将热点数据添加到缓存
3.缓存雪崩
缓存大批量失效或者Redis宕机
解决方案:
配置Redis集群;限流降级,控制操作数据库的线程数量;数据预热,分散过期时间