redis小结

1. Redis简介

​ redis全称 Remote Dictionary Service(远程字典服务)。Redis存储的都是K-V对,Redis里存放的任何一条数据都有唯一的key作为名称。Redis中,所有的key都存储在一个很大的字典中。一个Redis实例有多个库(database),可用过配置文件里的"databases"配置,库索引从0到databases-1,可以使用指令SELECT 切换到不通的库。

注意:在Redis命令行,Redis的指令不区分大小写,但是key区分大小写。

2. Redis基础数据结构

​ Redis有五种基础的数据结构:string、list、hash、set、zset。其中list、hash、set、zset称为容器型数据结构,容器型数据结构有两条通用规则:

复制代码
如果容器不存在,就创建一个,再进行操作。
如果容器里没有数据了,就立即删除,回收内存。

2.1 string(字符串)

string是Redis最简单的数据结构,一个key对应一个value。Redis的string实际上是使用数组实现的。

string基本指令有:

复制代码
SET:设置一个kv对,示例:SET name lily
GET:获取一个key对应的的value,示例:GET name
MSET:设置一个或多个kv对,示例:MSET name lily age 18
MGET:获取一个或多个key对应的value,示例:MGET name age
SETNX:设置一个kv对,如果该key不存在,设置成功;如果改成存在,设置失败,示例:SETNX name lilei
INCR:如果 value 是整数,还可以进行原子加一操作,示例:INCR age
DECR:如果 value 是整数,还可以进行原子减一操作,示例:DECR age

2.2 list(列表)

​ Redis的list是链表实现的,所以其插入删除操作非常快,时间复杂度都是O(1),但是索引定位很慢,时间复杂度是O(n)。当list中没有元素了,该数据结构会自动删除,内存被回收。

list的基本指令有:

复制代码
LPUSH:从左边插入元素,可以插入多个。示例:LPUSH students lily lilei zhangsan
LPOP:从左边删除元素,默认删除一个元素。可以指定需要删除的个数,示例:LPOP students 5
RPUSH:从右边插入元素,用法同LPUSH
RPOP:从右边删除元素,用法同LPOP
LRANGE:列出指定范围里的元素(不会删除元素),示例:LRANGE students 0 -1
LINDEX:(时间复杂度O(n))获取指定位置的元素,示例:LINDEX students 1
LTRIM:(时间复杂度O(n))删除指定范围的元素,示例:LTRIM students 1 2

list常用场景:

复制代码
队列/消息队列

从list的一边push数据,从另一边pop数据,就可以作为队列或者消息队列使用。如果list里面没有数据,LPOP和RPOP不会阻塞,都会立即返回空。如果用作消息队列,消费者需要处理LPOP或RPOP立即返回空的情况,一般的做法是如果返回为空,等待一段时间,再次获取,但是等待时间不好确定,等待时间太短会拉高CPU,造成浪费;等待时间太长会降低QPS,影响性能。Redis为list设计了阻塞读指令:BLPOP、BRPOP,指令用法是BLPOP key1 [key2 ...] timeout,这里BLPOP/BRPOP里的B是blocking的意思。阻塞读在list没有数据的时候,会立即休眠,一旦有数据到了,则立刻醒过来。

栈

在list的同一边push和pop数据,就可以作为栈使用

消息队列

LPOP或者RPOP操作不会阻塞,如果list里面没有数据,LPOP和RPOP都会立即返回空,如果

2.3 hash(字典)

​ Redis的hash的值只能是字符串。

hash的基本指令:

复制代码
HMSET:写入数据,支持批量。示例: HMSET 001 name lily age 18,其中 001 是该条hash的key,name、age 是hash里面的field。
HMGET:获取指定hash的某个field的value。示例:HMGET 001 name
HGETALL:获取指定hash的所有数据。示例:HGETALL 001
HINCRBY :如果hash内部的value是整型,可以使用HINCRBY进行原子加减操作(只需讲操作数设置为负数就是减法操作),示例:HINCRBY 001 age 1,HINCRBY 001 age -1

2.4 set(集合)

​ Redis的set是无序的。

set的基本指令:

复制代码
SADD:加入集合。示例:SADD students lily lilei
SMEMBERS:列出集合内成员。示例:SMEMBERS students
SISMEMBER:查询某个成员是否存在。示例:SISMEMBER students lily
SREM:删除某个成员。示例:SREM students lily
SCARD:获取集合长度。示例:SCARD students
SPOP:弹出成员,可以指定需要弹出的个数(不知道默认是1)。示例:SPOP students 5

2.5 zset(有序集合)

​ Redis的zset是一个很有特色的数据结构,一方面它是一个set,保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。它的内部实现采用的是"跳跃列表(skiplist)"。

zset基本指令:

复制代码
ZADD:增加成员。示例:ZADD students 95 lily 85 lilei 70 zhangsan 55 lisi
ZRANGE:正序获取指定个数的成员。示例:ZRANGE students 0 -1
ZREVRANGE:倒序获取指定个数的成员。示例:ZREVRANGE statuents 0 -1
ZRANGEBYSCORE:根据score范围获取成员,正序排列。示例:ZRANGEBYSCORE students 0 60
ZREVRANGEBYSCORE:根据score范围获取成员,倒叙排列。示例:ZREVRANGEBYSCORE students 100 0
ZREM:删除指定成员。示例:ZREM students zhangsan
ZREMRANGEBYSCORE :按score范围删除成员。示例:ZREMRANGEBYSCORE students 0 60
ZSCORE:获取成员score。示例:ZSCORE students lilei
ZCARD:获取zset长度。示例:ZCARD students

3. Redis通用指令

3.1 EXPIRE

EXPIRE指令用于设置超时,某个key超时后会自动删除。示例:EXPIRE students 10,10秒后students将被自动删除。

超时相关指令有:

复制代码
TTL:查看剩余过期时间,单位是秒。示例:TTL students
PTTL:查看剩余过期时间,单位是豪秒。示例:PTTL students

3.2 KEYS

KEYS获取当前库所有的或者特定的key列表,支持通配符"*"。示例:KEYS *查询全部key。

3.3 SCAN

​ KEYS可以获取key列表,但是有两个明显的缺点:

复制代码
没有 offset、limit 参数,一次性返回所有满足条件的key。

KEYS算法是遍历算法,复杂度是O(n),如果当前库中key很多,使用KEYS会导致Redis卡顿。

​ Redis提供了SCAN指令,SCAN相比KEYS有一下特点:
    复杂度虽然也是O(n),但是它是通过游标分步进行的,不会阻塞线程。
    提供limit参数,可以控制每次返回结果的最大条数。
    提供模式匹配功能。
    服务器不需要为游标保存状态,游标的唯一状态就是SCAN返回给客户端的游标整数。
    返回的结果可能会有重复,需要客户端去重。
    遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的。
    单词返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零。

SCAN用法: SCAN cursor [MATCH pattern] [COUNT count] [TYPE type],示例:scan 0 match s* count 5 type string。SCAN有四个参数,第一个是cursor整数值(相当于offset),第二个是key的正则模式,第三个是count(相当于limit),第四个是key的类型。第一次遍历时cursor值为0,然后将返回结果中的第一个整数值作为下一次遍历的cursor,一直遍历到返回的cursor值为0时结束。需要注意的是,每次SCAN返回的个数不一定是count,因为这个count不是限定返回结果的数量,而是限定服务器单次遍历的字典槽位数量,只要返回的cursor不是0,就表示遍历还没结束。

4. Redis进阶篇

4.1 持久化

​ Redis提供了两种持久化机制:一种是RBD(Redis Database),即快照;另一种是AOF(Append Only File)日志追加。RBD是一次全量备份,AOF日志是连续的增量备份。RBD是内存数据的二进制序列化形式,在存储上非常紧凑,而AOF日志记录的是内存数据修改的指令记录文本。AOF日志会慢慢变大,所以需要定期进行AOF重写,给AOF日志进行瘦身。

4.1.1 RBD

​ Redis使用操作系统的多进程COW(Copy On Write,写时复制)机制来实现快照持久化。Redis在持久化时fork一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,和父进程共享内存里面的代码段和数据段,当父进程接收到客户端请求需要修改数据时,会利用COW机制将需要修改的页复制一份进行修改,不会改变原来的页,所以子进程看到的还是它自己产生的那一瞬间的数据(这就是叫这种持久化机制为"快照"的原因),可以安心的遍历数据进行持久化。

4.1.2 AOF

​ AOF日志存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录。Redis恢复的时候,只需要根据AOF日志"重放"就行了。

​ Redis在长期运行过程中,AOF日志会越变越大,所以需要对AOF日志进行瘦身。Redis提供了bgrewirteaof指令用于对AOF日志进行瘦身。其原理就是开辟一个子进程对内存进行遍历转换成一系列Redis的操作指令,序列化到一个新的AOF日志文件中。序列化完毕后再将操作期间发生的增量AOF日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF日志文件,瘦身工作就完成了。

​ 当Redis对AOF日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将脏数据刷回到磁盘。Redis提供了不同的刷盘策略:

复制代码
定时刷盘,时间间隔可配。(如果需要开启持久化,一般采用这种方式。)
来一个指令就刷盘一次。(会影响性能)
永不主动刷盘,让操作系统决定何时刷盘。(很不安全)

4.1.3 混合持久化

​ 将RDB文件的内容和增量的AOF日志文件存在一起,这里的AOF日志不是全量的日志,而是自快照持久化开始到持久化结束的这段时间发生的增量AOF日志。Redis重启的时候,先加载RBD的内容,再重放增量AOF日志。

相关推荐
学编程的小程31 分钟前
从“单模冲锋”到“多模共生”——2026 国产时序数据库新物种进化图谱
数据库·时序数据库
卓怡学长31 分钟前
m111基于MVC的舞蹈网站的设计与实现
java·前端·数据库·spring boot·spring·mvc
存在的五月雨37 分钟前
Redis的一些使用
java·数据库·redis
小冷coding8 小时前
【MySQL】MySQL 插入一条数据的完整流程(InnoDB 引擎)
数据库·mysql
鲨莎分不晴8 小时前
Redis 基本指令与命令详解
数据库·redis·缓存
专注echarts研发20年9 小时前
工业级 Qt 业务窗体标杆实现・ResearchForm 类深度解析
数据库·qt·系统架构
周杰伦的稻香11 小时前
MySQL中常见的慢查询与优化
android·数据库·mysql
冉冰学姐11 小时前
SSM学生社团管理系统jcjyw(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·学生社团管理系统·多角色管理
nvd1112 小时前
深入分析:Pytest异步测试中的数据库会话事件循环问题
数据库·pytest
appearappear12 小时前
如何安全批量更新数据库某个字段
数据库