Redis 基础汇总

介绍

Redis 是一种基于键值对(key-value)的,worker 线程为单线程的内存数据库。其中 value 可以为 string、hash、list、set、zset,它们有自己的方法,可以满足很多应用场景。

还提供了键过期,发布订阅,事务,流水线等附加功能。

流水线:Redis的流水线功能允许客户端一次将多个命令请求发送给服务器,并将被执行的多个命令请求的结果在一个命令回复中全部返回给客户端,使用这个功能可以有效地减少客户端在执行多个命令时需要与服务器进行通信的次数。

特性

  1. 速度快,数据放在内存中,官方给出的读写性能10万/s(与机器性能也有关):
    数据放内存中是速度快的主要原因
    C语言实现,与操作系统距离近
    使用了单线程架构,预防多线程可能产生的竞争问题
  2. 键值对的数据结构服务器
  3. 功能丰富
  4. 简单稳定:单线程
  5. 持久化:发生断电或机器故障,数据可能会丢失,持久化到硬盘
  6. 主从复制:实现多个相同数据的redis副本
  7. 高可用和分布式:哨兵机制实现高可用,保证 redis节点故障发现和自动转移
  8. 客户端语言多:java php python c c++ nodejs等

使用场景

  1. 缓存:合理使用缓存加快数据访问速度,降低后端数据源压力
  2. 排行榜:按照热度排名,按照发布时间排行,主要用到列表和有序集合
  3. 计数器应用:视频网站播放数,网站浏览数,使用 redis 计数
  4. 社交网络:赞、踩、粉丝、下拉刷新
  5. 消息队列:发布和订阅

存储结构

在这里插入图片描述
Redis 的内部整体的存储结构就是一个大的 HashMap。每个 dictEntry 里都有 key 与 v,分别对应 set key value 里的 key 和 value。

重要 value 类型

全局命令

  1. 查看所有键:keys *
  2. 键总数:dbsize //如果存在大量键,线上禁止使用此指令
  3. 检查键是否存在:exists key0 //key0存在返回1,不存在返回0
  4. 删除键:del key0 key1 …//返回删除键个数,删除不存在键返回0
  5. 键过期:expire key0 seconds0
  6. 键的数据结构类型:type key0

String

字符串类型:实际上可以是字符串(包括XML、JSON),还有数字(整形浮点数),二进制(图片音频视频),最大不能超过512MB


设值命令

在这里插入图片描述
EX:过期时间,秒
PX:过期时间,毫秒
NX:如果不存在 key,可以设置成功。成功返回1。
XX:如果存在 key,可以设置成功。成功返回1。

在这里插入图片描述
效果等于上面的 set key value NX

获值命令
在这里插入图片描述
批量设置
在这里插入图片描述
批量获取
在这里插入图片描述


计数命令

自增
在这里插入图片描述
必须为整数自增1,非整数返回错误,无键从0自增返回1
使用场景的联想:可以用来做文章阅读量的自增。

自增一段
在这里插入图片描述
浮点自增一段
在这里插入图片描述
自减
在这里插入图片描述
必须为整数自减1,非整数返回错误,无键从0自减返回-1

自减一段
在这里插入图片描述


追加命令
在这里插入图片描述


截取命令

在这里插入图片描述
索引从 0 开始,截取包含 start 和 end


求字节长度

在这里插入图片描述


内部编码
在这里插入图片描述
int:如果能转化为 long。
embstr:小于等于44字节的字符串(3.2版本)
raw:大于44字节的字符串。最大 512M

embstr和raw都是由SDS(Simple Dynamic String)动态字符串构成的。
区别是:raw是分配内存的时候,redisobject 和 sds 各分配一块内存,而embstr是redisobject和raw在一块儿内存中。

embstr:
分配内存和释放内存只需要1次。对 embstr 的 操作会使 embstr 转化为 raw。
44的由来:整个 redisObject 和 sdshdr 一共占 64 字节,redisObject 占16 字节,SDS 头部占 3 字节,还有结尾 ‘\0’ 占 1 字节。一共 20 字节不能用,所以还剩 44 字节。

为什么要分配 64 字节?因为内存分配器 jemalloc、tcmalloc 分配内存的大小都是按 2/4/8/16/32/64 字节来的。因为 embstr 的“无效”部分就占了 20 字节,如果只申请 32 字节,利用率未免太低。
在这里插入图片描述

raw:
分配内存和释放内存需要2次。
在这里插入图片描述

空间预分配
若修改之后sds长度小于1MB,则多分配现有len长度的空间
若修改之后sds长度大于等于1MB,则扩充除了满足修改之后的长度外,额外多1MB空间

惰性空间释放
为避免缩短字符串时候的内存重分配操作,sds在数据减少时,并不立刻释放空间。

Hash

是一个 string 类型的 field 和 value 的映射表,hash 特适合用于存储对象。


设值命令
在这里插入图片描述
例:购物车场景
在这里插入图片描述
购物车编号 001,选择了 1 件 01 号商品,1 件 02 号商品
在这里插入图片描述
可以看出,hset 可以批量设值

批量设值
在这里插入图片描述
取值命令
在这里插入图片描述
hget 不能批量取值

批量取值
在这里插入图片描述
删值命令

在这里插入图片描述
字段个数
在这里插入图片描述
使用场景的联想:查看购物车里物品数量

判断字段是否存在

在这里插入图片描述
获取所有字段

在这里插入图片描述
例:
在这里插入图片描述
获取所有字段值
在这里插入图片描述
例:
在这里插入图片描述

获取所有字段与字段值

在这里插入图片描述
例:
在这里插入图片描述
自增一段
在这里插入图片描述
使用场景的联想:购物车商品数 +1
在这里插入图片描述

浮点自增一段
在这里插入图片描述
例:
在这里插入图片描述
内部编码
ziplist:当字段个数小于512且每个字段值小于64字节时
hashtable

ziplist:
在这里插入图片描述
hashtable
在这里插入图片描述
字典的结构中包括两个hash表,h[0]和h[1],每次只是用h[0]就够了。若是需要扩容,就一部分一部分的迁移到h[1],在此过程中,若是客户端线程来删改查数据,先从h[0]找,没有的话去h[1],若是添加数据,直接添加到h[1],保证h[0]数据不增加。最后迁移完成释放h[0],将h[1]设置为h[0],再在h[1]新建一个空白 table。

List

用来存储多个有序的字符串,一个列表最多可存 232-1 个元素


左push
在这里插入图片描述
使用场景的联想:消息推送
在这里插入图片描述

右push
在这里插入图片描述

左pop
在这里插入图片描述
右pop
在这里插入图片描述
左阻塞pop
在这里插入图片描述
右阻塞pop
在这里插入图片描述
替换
在这里插入图片描述
插入
在这里插入图片描述
在 pivot 前|后 插入value

查询
在这里插入图片描述

范围查询
在这里插入图片描述
查询索引 [start, stop] 的所有 value。[0, -1] 表示所有 value。

长度
在这里插入图片描述
删除指定数量的值
在这里插入图片描述
从左到右删除 count 个 value

保留范围内的值
在这里插入图片描述
内部编码
版本 3.2 以后: quicklist
在这里插入图片描述
quicklist 可以看作一个双向列表,但是列表的每个节点都是一个ziplist。
可以配置双向列表两边 n 个节点不压缩。

Set

保存无序不重复元素,一个集合最多可存 232-1 个元素,除了支持增删改查,还支持集合交集、并集、差集.



在这里插入图片描述
只会添加原本没有的 member,返回添加成功的 member 个数
使用场景的联想:黑名单,如抢红包,抢过的人加入黑名单。


在这里插入图片描述
只会删除原本有的 member,返回删除成功的 member 个数

随机pop
在这里插入图片描述
使用场景的联想:抽奖,从参与抽奖的人群里抽取几个

查询成员个数
在这里插入图片描述
查询所有成员
在这里插入图片描述
查询成员是否存在
在这里插入图片描述
随机pop一定数量的成员
在这里插入图片描述
count 不能为负数

随机查一定数量的成员
在这里插入图片描述
如果 count 为负数,允许重复。

求交集
在这里插入图片描述
使用场景的联想:微关系,共同关注的人

求交集并保存结果
在这里插入图片描述
求并集
在这里插入图片描述
求并集并保存结果
在这里插入图片描述
求差集
在这里插入图片描述
key1 在前,key2 在后,就是 key1 的数据 - key2 的数据
使用场景的联想:QQ,可能想认识的人

求差集并保存结果
在这里插入图片描述
返回第一个 key 的 set 减去交集的结果

内部编码
intset:成员都为整数且少于512个
hashtable

Zset

用分值排序的 Set
与 List、Set 对比:
在这里插入图片描述



在这里插入图片描述
NX:key 必须不存在,用于添加
XX:key 必须存在,用于修改。与 INCR 一起使用。
CH:返回结果分值。与 INCR 一起使用。
INCR:接一个整数,增加分值。接浮点数,浮点数会不准。


在这里插入图片描述

查范围
在这里插入图片描述
索引在[start, stop]之间的成员。索引顺序与分值顺序一致。
WITHSCORES:显示分值。

查成员个数
在这里插入图片描述
查名次
在这里插入图片描述
名次从 0 开始。顺序从小到大。

查排名
在这里插入图片描述

查倒序名次
在这里插入图片描述
顺序从大到小。

查倒序排名
在这里插入图片描述
查分数范围内成员
在这里插入图片描述
表示从 x 到无穷大:(x +inf
表示从无穷小到 x:(x -inf

倒序查分数范围内成员
在这里插入图片描述
查分数范围内成员个数
在这里插入图片描述
增加分数
不能直接改,只能在原分数上更改。除了用 zadd 以外,还有:
在这里插入图片描述
使用场景的联想:热搜排行

删名次范围内成员
在这里插入图片描述
删分数范围内成员
在这里插入图片描述
求交集并保存
在这里插入图片描述
destination:要保存的结果的 key 的名字
numkeys:key 个数
WEIGHTS:对应 key 的排列设值,代表各 key 里所有成员的分数权值。在后续的计算之前,将分数与对应权值相乘。
AGGREGATE:聚合方式,有求和、求最小值、求最大值。默认是求和。

求并集并保存
在这里插入图片描述

内部编码
ziplist:当成员个数小于128且成员值小于64字节
skiplist + dict:skiplist 最大层数64,dict 是为了在O(1)的时间复杂度下通过元素成员得到分数

ziplist:
在这里插入图片描述
skiplist:
在这里插入图片描述

查找的效率平均是O(logN)

为什么用跳表而不用 BTree?

  1. 占用内存更小
  2. 对范围查找的支持更好
  3. 实现更容易

BitMap


在这里插入图片描述
如:setbit key1 1 1
0 1 0 0 0 0 0 0

index 大小会决定字节多少

1的数量
在这里插入图片描述
字节下标范围内有多少个1

使用场景的联想:时间窗口内天数、每天活跃用户数

逻辑操作
在这里插入图片描述

如:bitop and andkey k1 k2

布隆过滤器

小结

在这里插入图片描述

三种方案实现用户信息存储优缺点

  1. 原生
    set user:1:name Tom
    set user:1:age 23
    set user:1:sex male
    优点:简单直观,每个键对应一个值
    缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境
  2. 将对象序列化存入redis
    set user:1 serialize(userlnfo);
    优点:编程简单,若使用序列化合理内存使用率高
    缺点:序列化与反序列化有一定开销,更新属性时需要把 userlnfo 全取出来进行反序列化,更新后再序列化到redis
  3. 使用hash类型
    hmset user:1 name Tom age 23 sex male
    优点:简单直观,使用合理可减少内存空间消耗
    缺点:要控制 ziplist 与 hashtable 两种编码转换,且 hashtable 会消耗更多内存

总结:

  • 对于更新不多的情况下,可以使用序列化
  • 对于VALUE值不大于64字节可以使用 Hash 类型

Redis VS Memcached

Memcached 的 value 只能存储 String,数据向计算移动。
Redis 的 value 能存储多种类型,且每种类型有自己的方法,计算向数据移动。

移动的成本往往大于计算,Redis 的 IO 量更少,这是它的优势。

单线程

为什么这么快

  • 开发语言
    Redis 就是用 C 语言开发的,C 语言是非常贴近操作系统的语言,所以执行会比较快。

  • 纯内存访问
    Redis 将所有数据放在内存中,非数据同步正常工作时,是不需要从磁盘读取数据的。

  • worker 单线程
    第一,单线程简化算法的实现,并发的数据结构实现不但困难而且测试也麻烦。
    第二,单线程避免了线程切换以及加锁释放锁带来的消耗,对于服务端开发来说,锁和线程切换通常是性能杀手。

  • 多路复用
    Redis 使用 epoll 作为 I/O 多路复用技术的实现,再加上 Redis 自身的事件处理模型将 epoll 的 read、write、close 等都转换成事件,不在网络 I/O 上浪费过多的时间,从而实现对多个 FD 读写的监控,提高性能。

  • 计算向数据移动
    Redis 的 value 能存储多种类型,且每种类型有自己的方法。减少 IO 数据包的大小。

劣势

问题:不能发挥多核优势
解决:woker 线程计算,io threads 并行读写。
新问题:不同连接,读写先后顺序,会有问题。这个问题无法解决,回想一下多路复用器的 select。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值