目录
- 为什么基于MySQL又出现Redis?Redis的优点?
- Redis支持的基本命令
- Redis支持的数据结构
- 1 String
- 2 List
- 3 Set
- 4 Sorted Set
- 5 Hash
- 6 Stream 消息队列
- 7 Geospatial 地理空间
- 8 Bitmap 位图
- 9 Bitfield 位域
- 10 HyperLogLog
- Redis是单线程还是多线程?
- 发布订阅模式
- Redis中的事务与关系型数据库中的事务的区别?
- 持久化的两种方式RDB和AOF有什么区别?用哪个更好?
- RDB快照(Redis Database)
- AOF日志(Append-Only File)
- 主从复制
- Sentinel 哨兵模式
- Redis集群
- 集群中如何进行数据分区?
- 节点取余分区
- 一致性哈希分区
- 虚拟槽分区
- 集群的伸缩?
- 如何保证缓存数据和数据库数据的一致?
- 如何保证本地缓存和分布式缓存的一致?
- 如何处理热key和大key?
- Redis的管道?
为什么基于MySQL又出现Redis?Redis的优点?
-
MySQL是基于磁盘IO的,Redis是基于内存的。
内存的读写速度比磁盘IO的读写速度快很多,可以大大提高性能。 -
优点:基于内存所以性能高,支持的数据类型很丰富,支持所有主流的编程语言如python Java等,支持数据持久化(ROB AOF机制),支持主从复制,支持集群模式,支持哨兵模式。
-
Redis是key-value形式的非关系型数据库
Redis支持的基本命令
- SET 添加键值对
- GET 获取键值对
- EXISTS 查询键值对
- DEL 删除键值对
- FLUSHALL 删除所有键
- KEYS * 查询所有键
- TTL 查看键过期时间
- EXPIRE 设置键的过期时间
Redis支持的数据结构
1 String
- Redis默认用String进行存储
- String所有的命令都与基本命令一致
2 List
- 底层数据结构是双端队列
- 命令以L开头
- 独有命令:LPUSH(左边入队)LPOP(左边出队)LRANGE(从左边输出队列)LLEN(队列长度)LTRIM(从左边数保留队列的部分元素)RPUSH(右边入队)…
3 Set
- 无序去重集合
- 命令以S开头
- 独有命令:SADD(添加元素)SREM(删除元素)SISMEMBER(查询元素)
- 支持集合运算,交集并集等
4 Sorted Set
- 有序去重集合
- 命令以Z开头
- Zset中的每个元素都会关联一个浮点类型的分数,然后根据分数从小到大排序元素
- Zset中的元素是唯一的,但元素的分数可以是重复的
- 独有命令:ZRANGE key 0 -1 WITHSCORES(输出所有成员+分数)ZRANK(查看成员从小到大的排名)
5 Hash
- 命令以H开头
- Redis本身就是键值对,相当于键值对中的value又是键值对
6 Stream 消息队列
- 命令以X开头
- 独有命令:XREAD COUNT count BLOCK ms STREAMS key 0(从头一次从队列中读count条消息,如果没有消息就阻塞多少ms,可以重复读取。把0改成#可以读最新消息)XGROUP(创建消费者组和创建消费者)XINFO(查看消费者组的信息)
7 Geospatial 地理空间
- Redis3.2版本的新特性
- 一种专门用来存储地理位置信息的数据结构
- 命令以GEO开头
- 支持地理位置的计算操作
- 独有命令:GEOPOS(查找城市经纬度)DEODIST(计算城市直线距离)GEOSEARCH(查询以某城市为中心,在某范围内的城市)
8 Bitmap 位图
- 一个01数组,下标表示偏移量
- 命令以BIT开头
- 支持位运算
- 适用场景:记录用户签到情况,在线状态,是否点赞
9 Bitfield 位域
- 命令以BITFIELD开头
- 适用场景:记录游戏玩家信息
10 HyperLogLog
- 一种做基数统计的算法,即计算集合中的不重复元素个数
- 命令以PF开头
- 原理:随机算法
- 优点:占用内存小
- 缺点:有误差
- 适用场景:对精确度要求不高,但数据量很大的统计工作,如统计某词的搜索次数
Redis是单线程还是多线程?
- Redis一直倾向于使用单线程,避免了频繁的线程切换,是它的优点之一
- 4.0之前完全是单线程
- 4.0之后主线程是单线程,同时还有后台线程(处理脏数据、释放无用链接、删大key等)
- 6.0之后执行命令是单线程,同时还有其他线程(处理数据读写、解析协议)
发布订阅模式
- publish命令,将消息发送到指定频道
- subscribe命令,订阅指定频道
- 缺点:消息无法持久化,无法记录历史消息
Redis中的事务与关系型数据库中的事务的区别?
- 事务是一系列命令的集合,事务开启后,所有命令放到队列中,打包到一起发起执行事务的请求,可以在一次请求中执行多个命令
- MULTI命令开启事务
- EXEC命令执行事务
- 关系型事务为原子操作,所有命令要么全部执行成功,要么全部失败
- 非关系型事务不是原子操作,任何一个命令执行失败都不会妨碍下一个命令继续执行
持久化的两种方式RDB和AOF有什么区别?用哪个更好?
RDB快照(Redis Database)
- 每隔一个固定的时间间隔,将内存中的数据快照写入磁盘,即ROB保存的是某个时间点内数据的完整副本
- 优点:恢复速度快,适合备份
- 缺点:如果服务器突然宕机,最后一次快照之后的数据会丢失,做不到实时持久化
- 触发方式:1. 自动触发 2. save命令,在执行save命令期间,redis不能干其他事情 3. bgsave命令,创建一个子进程专门来拍快照,创建子进程期间redis不能干其他事情,但拍快照期间可以干其他
AOF日志(Append-Only File)
- 执行命令时一边将命令写到内存中,一边写到AOF中,Redis重启时利用AOF中的命令重建数据库,即AOF是一个保存着执行过的所有命令的日志
- 优点:做到了实时持久化
- 缺点:文件很大,恢复速度慢,启动效率低
各有优点,混合持久化最好,即ROB+增量AOF的形式,AOF文件只保存最后一次快照到此刻的执行命令,Redis重启时,先加载ROB文件,再重放增量AOF文件,即避免了ROB无法实时持久化,也避免了AOF文件过大。
主从复制
- 将一台redis主服务器的数据复制到其它redis从服务器
- 低级的redis集群模式
- 一个主节点可以有多个从节点,一个从节点只有一个主节点
- 数据单向复制,只能从主到从,主写从读
- 数据同步的方式可以全量复制,也可以部分复制
- 优点:数据热备份,故障恢复,负载均衡(读写分离可以分担服务器负载),高可用基石(哨兵模式和集群的基础)
- 缺点:主节点故障需人工干预(哨兵模式可解决),主节点的写能力受限制(分布式可解决)
Sentinel 哨兵模式
- 自动故障转移,主从复制过程中主节点故障无需人工干预
- 以独立进程的形式运行在redis集群中,监控服务器们运行,若发现某节点有问题,通过发布订阅模式通知其他节点,主节点故障会将一个从节点升级成新的主节点,再通知其他从节点更换了主节点。
- 主观下线和客观下线 主观下线就是哨兵节点认为某个节点有问题,客观下线就是超过一定数量的哨兵节点认为主节点有问题。
- 如何选新的主节点?拿到节点列表,先过滤不健康节点,再选择优先级最高的节点们,再选复制偏移量最大的节点们(说明数据最完整),再选runid最小的节点(说明启动最早)
- 哨兵节点是一个进程,也有可能故障,所以一般用3个哨兵,选举一个领导哨兵干活,领导挂了后重新选一个领导哨兵
Redis集群
- 数据分区/分片:集群最核心的功能。集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加;另一方面 每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。
- 高可用: 集群支持主从复制和主节点的 自动故障转移 (与哨兵类似),当任一节点发生故障时,集群仍然可以对外提供服务。
集群中如何进行数据分区?
- 即拿到一个key(数据)应该把它放到集群中的哪个节点上?
- 数据分区是在创建集群的时候完成的
- 节点数量至少为6个才能保证组成完整高可用的集群
节点取余分区
- 对key或用户ID对hash值取余,来确定数据映射到哪一个节点上。
- 缺点:当节点数量变化时,如扩容或收缩节点,所有数据节点映射关系需要重新计算,会导致数据的重新迁移
一致性哈希分区
- 将整个 Hash 值空间组织成一个虚拟的圆环,然后对集群节点的 IP 地址或主机名做 Hash 取值后,放置在圆环上。当我们拿到一个key时,先对这个 key 做同样的Hash 取值,确定在环上的位置,然后按照顺时针方向在环上“行走”,遇到环上的第一个节点,将key放入。
- 优点:加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响
- 缺点:当节点在圆环上分布不平均时,部分缓存节点的压力会较大。当某个节点故障时,这个节点承担的所有数据访问都会被顺移到下一个节点上,会对下一个节点造成压力。
虚拟槽分区
- Redis 集群使用的便是该方案
- 在一致性哈希分区的基础上,引入了虚拟节点,称为槽(slot)。在使用了槽的一致性哈希分区中,一个节点被分割成了多个槽,槽是数据管理和迁移的基本单位。
- 槽解耦了数据和实际节点之间的关系,增加或删除节点对系统的影响很小。当删除某个节点时,该节点下的多个槽可以带着数据较平均地分配到剩余的多个节点上,避免了该节点所有数据堆积到下一个节点上的问题。
集群的伸缩?
- 扩容:为新节点分配一定数量的槽和数据
- 缩容:将槽和数据分配给其他节点,再将要删除的节点下线