Redis 是C语言开发的一个开源高性能键值对的内存数据库,可以用来做数据库、缓存、消息中间件等场景,是一种NoSQL(not-only sql,非关系型数据库)的数据库
官网
中文文档
linux安装Redis7
版本号第二位如果是奇数,则为非稳定版本 如2.7、2.9、3.1
版本号第二位如果是偶数,则为稳定版本 如2.6、2.8、3.0、3.2
当前奇数版本就是下一个稳定版本的开发版本,如2.9版本是3.0版本的开发版本
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个双端链表,最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,集合对象的编码可以是 intset 或者 hashtable。
Redis 中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)
zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。
zset集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32 - 1
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,包括
添加地理位置的坐标。
获取地理位置的坐标。
计算两个位置之间的距离。
根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。
说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis命令手册
set:从2.6.12版本开始,redis为SET命令增加了一系列选项:
(1)EX seconds – 设置键key的过期时间,单位时秒
(2)PX milliseconds – 设置键key的过期时间,单位时毫秒
(3)NX – 只有键key不存在的时候才会设置key的值
(4)XX – 只有键key存在的时候才会设置key的值
(5)KEEPTTL – 获取 key 的过期时间
get
mset:批量设置,例如mset name zhangsan age 15
mget
setrange key_name offset value:从偏移量 offset 开始, 用 value 参数覆盖键 key 储存的字符串值。
一定要是数字才可以加减
应用场景:点赞。
lpush:头插
rpush:尾插
lpop
rpop
lindex: 按照索引下标获取某值
llen
lrem:删除前 count 个值等于 element 的元素
ltrim :截取指定范围内的值再赋值给key
lset key index value
linset :在list某个已有值的前后再添加具体值
应用场景:微信公众号订阅的消息。
应用场景:早期购物车设计
新增商品 → hset shopcar:uid1024 334488 1
新增商品 → hset shopcar:uid1024 334477 1
增加商品数量 → hincrby shopcar:uid1024 334477 1
商品总数 → hlen shopcar:uid1024
全部选择 → hgetall shopcar:uid1024
应用场景:
微信小程序抽奖
微信朋友圈查看共同赞的朋友
QQ可能认识的人
应用场景:根据商品销售对商品进行排序显示。
思路:定义商品销售排行榜(sorted set集合),key为goods:sellsort,分数为商品销售数量。
redis-geo
基数统计。统计某个网站独立访客(一般理解为客户端IP),用户搜索网站关键词的数量,统计每天搜索不同词条的个数。
去重复统计功能的基数估计算法就是hyperloglog
由0和1表示的二进制位的bit数组。可用于打卡,签到统计等。用String类型作为底层数据结构实现的一种统计二值状态的数据类型。位图本质是数组。
了解即可
redis版的消息中间件+阻塞队列。
redis stream
Redis 一共有 2 种持久化方式,分别是 RDB 和 AOF
RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照。就是把某一时刻的数据和状态以文件的形式写到磁盘上。
修改配置文件 redis.conf
save 3600 1 # 每3600秒钟里redis数据库有1条数据被修改则触发RDB
save 300 100 # 每300秒钟里redis数据库有100条数据被修改则触发RDB
save 60 10000 # 每60秒钟里redis数据库有10000条数据被修改则触发RDB
dbfilename "dump6380.rdb" # 持久化文件名称
dir "/myredis" # 持久化数据文件存放的路径
除了上述配置文件中 save < secends > < changes > 自动触发外,还支持手动触发。Redis提供了save和bgsave两个命令生成rdb文件。
bgsave:会创建一个子进程专门去把内存中的数据库状态写入RDB文件里。但子进程基本是复制的父进程,这等于两个相同大小的redis进程在系统上运行,会造成内存使用率的大幅增加。
与RDB的保存整个redis数据库状态不同,AOF是通过保存对redis服务端的写命令(如set、sadd、rpush)来记录数据库状态的,即保存你对redis数据库的写操作,以下就是AOF文件的配置内容
dir "/myredis" # 持久化数据文件存放的路径
appendonly yes #开启AOF持久化,默认关闭
appendfilename "appendonly6380.aof" #AOF文件名称(默认)
appendfsync no #AOF持久化策略
auto-aof-rewrite-percentage 100 #触发AOF文件重写的条件(默认)
auto-aof-rewrite-min-size 64mb #触发AOF文件重写的条件(默认)
reids开启AOF后,服务端每执行一次写操作(如set、sadd、rpush)就会把该条命令追加到一个单独的AOF缓冲区的末尾,这就是命令追加;然后把AOF缓冲区的内容写入AOF文件里。
而何时进行文件同步则是根据配置的appendfsync来进行:
appendfsync有三个选项:always、everysec和no。默认的AOF 持久化策略是每秒钟fsync 一次。
2、配置成everysec的话服务端每执行一次写操作(如set、sadd、rpush)也会把该条命令追加到一个单独的AOF缓冲区的末尾,并将AOF缓冲区写入AOF文件,然后每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,这个模式兼顾了效率的同时也保证了数据的完整性,即使在服务器宕机也只会丢失一秒内对redis数据库做的修改;
3、将appendfsync配置成no则意味redis数据库里的数据就算丢失你也可以接受,它也会把每条写命令追加到AOF缓冲区的末尾,然后写入文件,但什么时候进行文件同步真正把数据写入AOF文件里则由系统自身决定,即当内存缓冲区的空间被填满或者是超过了设定的时限后系统自动同步。这种模式下效率是最快的,但对数据来说也是最不安全的,如果redis里的数据都是从后台数据库如mysql中取出来的,属于随时可以找回或者不重要的数据,那么可以考虑设置成这种模式。
RDB优点:如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB 方式要比AOF 方式更加的高效。
RDB缺点:如果你对数据的完整性非常敏感,那么RDB 方式就不太适合你,因为即使你每5 分钟都持久化一次,当Redis 故障时,仍然会有近5 分钟的数据丢失。
AOF 优点:我们通过一个场景再现来说明。某同学在操作Redis 时,不小心执行了FLUSHALL,导致Redis 内存中的数据全部被清空了,这是很悲剧的事情。只要Redis 配置了AOF 持久化方式,且AOF文件还没有被重写(rewrite),我们就可以用最快的速度暂停Redis 并编辑AOF文件,将最后一行的FLUSHALL 命令删除,然后重启Redis,就可以恢复Redis的所有数据到FLUSHALL 之前的状态了。这就是AOF 持久化方式的好处之一。但是如果AOF 文件已经被重写了,那就无法通过这种方法来恢复数据了。
AOF缺点:在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF 方式的恢复速度也要慢于RDB 方式
如果redis开启了AOF持久化功能,那么当redis服务重启时会优先使用AOF文件来还原数据库。
RDB是每隔一段时间触发持久化,因此数据安全性低,AOF可以做到实时持久化,数据安全性较高
RDB文件默认采用压缩的方式持久化,AOF存储的是执行指令,所以RDB在数据恢复的时候性能比AOF要好
推荐使用方式:RDB和AOF混合使用。
Redis事务是将一系列命令按顺序串行化执行,期间不会被其他客户端的指令插队。。
Redis事务的三大命令
如下图,通过multi,当前客户端就会开启事务,后续的指令都会按序存到队列中。当用户键入exec后,这些指令都会按顺序执行。若开启multi后输入若干指令,在键入discard,则之前的指令通通取消执行。
分别有组队时错误和执行命令时错误两种情况
组队时错误
在组队时输入错误的指令,redis所有指令都会失效,因为这是一个问题队列。
执行命令时错误
按序处理所有指令,遇到错误就按正常流程处理继续执行下去。
为什么组队时出错和运行时出错会出现两种不同的情况呢?
redis 是 C/S 模式,即客户端 + 服务端。
如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统IO,发送网络请求,同时需要redis调用多次read()和write()系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好。
redis 提供了 pipeline 解决方案,可以按批次进行查询和响应。
pipeline 与原生命令的区别
Redis 的发布与订阅
就是主从复制,master以写为主,slave以读为主。当master数据发生改变时,自动将新的数据异步同步到其他slave数据库。
master如果配置了requirepass参数,需要密码登录,那slave 就要配置masterauth来设置master校验密码,否则master会拒绝slave连接。
slave配置文件加上
replicaof 192.168.208.101 6380 # 主节点
masterauth 123456 #主节点密码
常用命令:
(1)复制延时, 信号衰弱。由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
(2)由于主从模式是读写分离的,如果主节点(master)挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点(slave)进行数据同步了。
它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。俗称无人值守运维。
Redis Sentinel架构:3个哨兵(自动监控和维护集群,不存放数据), 一主二从(同6.1.1)
步骤:
修改配置文件
启动三个哨兵
测试
(1)两个概念
当主节点被判断客观下线后,各个哨兵节点会选举产生新的master节点。选举算法为Raft算法。
(2)sentinel选举步骤
参考:
高手过招, 为什么 Redis Cluster 是16384个槽位?
Redis集群搭建及原理,肝了
哨兵模式的缺点:
(1)当master挂掉的时候,sentinel 会选举出来一个 master,选举的时候是没有办法去访问Redis的,会存在访问瞬断的情况
(2)哨兵模式对外只有master节点可以写,slave节点只能用于读。尽管Redis单节点最多支持10W的QPS,但是在电商大促的时候,写数据的压力全部在master上。
(3)Redis的单节点内存不能设置过大,若数据过大在主从同步将会很慢;在节点启动的时候,时间特别长;(从节点上有主节点的所有数据)
Redis Cluster 是 在 3.0 版本正式推出的高可用集群方案,相比Redis Sentinel,Redis Cluster方案不需要额外部署Sentinel集群,而是通过集群内部通信实现集群监控,故障时主从切换;同时,支持内部基于哈希实现数据分片,支持动态水平扩容
根据官方推荐,集群部署至少要3台以上的master节点,最好使用3主3从六个节点的模式。
将整个数据集按照一定规则分配到多个节点上,称为数据分片,Redis Cluster采用的分片方案是哈希分片
基本原理如下:
Redis Cluster首先定义了编号0 ~ 16383的区间,称为槽,所有的键根据哈希函数映射到0 ~ 16383整数槽内,计算公式:slot = CRC16(key) % 16384。每一个节点负责维护一部分槽以及槽所映射的键值数据
SpringBoot集成Redis