Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis 学习笔记 #2

Open
RedCrazyGhost opened this issue Mar 3, 2023 · 0 comments
Open

Redis 学习笔记 #2

RedCrazyGhost opened this issue Mar 3, 2023 · 0 comments
Labels
Docker fa-brands fa-docker Redis fa-solid fa-database

Comments

@RedCrazyGhost
Copy link
Owner

RedCrazyGhost commented Mar 3, 2023

前言

本篇文章用于记录Redis的学习内容

Keys

Keys是二进制存储,说明可以存储任何二进制数据。(可以存储jpeg图片)

空字符串可以为Keys

  • 建议使用的Keys规范为"object-type:id:object-type.property"或"object-type:id:object-type-property"
  • 最大存储512MB

Strings

可以缓存HTML代码片段或页面代码

 > set iKey iValue
"OK"

 > get iKey
"iValue"

使用SET命令会覆盖已经存在的Keys

SET命令可以在Keys存在时失败,也可以成功

 > set iKey iValue nx
(nil)

 > set iKey iValue xx
"OK"

可以通过命令进行原子计算

 > set counter 1
"OK"

 > incr counter
(integer) 2

 > incrby counter 10
(integer) 12

 > decr counter
(integer) 11

 > decrby counter 10
(integer) 1

为了降低单个命令中设置或检索多个Keys的值所带来的延迟,可以使用MESTMGET

MGET返回数组

 > mset a 10 b 20 c 30
"OK"

 > mget a b c
1) "10"
2) "20"
3) "30"

EXISTS命令用于查询Keys是否存在(1表示存在,0表示不存在),DEL命令用于删除Keys和关联值(1表示删除成功,0表示不存在)

 > set iKey iValue
"OK"

 > exists iKey
(integer) 1

 > del iKey
(integer) 1

 > exists iKey
(integer) 0

 > del iKey
(integer) 0

TYPE命令获取Keys存储的值的类型

 > set iKey iValue
"OK"

 > type iKey
"string"

 > del iKey
(integer) 1

 > type iKey
"none"

Keys过期

  • 设置单位为秒或毫秒
  • 效果为毫秒级
  • 过期的Keys会被保存

EXPIRE命令进行设置Keys过期时间

List

底层实现原理是链表

能够快速的把元素添加到List中,也可以在恒定时间内获取恒定长度的元素。

LPUSH命令用于List的头插(左),RPUSH命令用于List的尾插(右),LRANGE命令用于获取角标范围内的元素

 > rpush iList A
(integer) 1

 > rpush iList B
(integer) 2

 > lpush iList C
(integer) 3

 > lrange iList 0 -1
1) "C"
2) "A"
3) "B"

-1表示从尾部开始计算倒数第一个元素,以此类推即可

 > rpush iList 1 2 3 4 5 "ok?"
(integer) 6

 > lrange iList 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "ok?"

LPOP命令用于弹出List的头元素,RPOP命令用于弹出List的尾元素。全部弹出后再通过命令弹出则会返回nil

 > rpop iList
"ok?"

 > lpop iList
"1"

 > lpop iList
(nil)

List的常见用法

  • 最新消息通知
  • 消费者-生产者模式

LTRIM命令用于List的使用范围,操作范围即丢弃

 > rpush iList 1 2 3 4 5
(integer) 5

 > ltrim iList 0 2
"OK"

 > lrange iList 0 -1
1) "1"
2) "2"
3) "3"

List的阻塞操作

在消费者-生产者模式下

  • 生产者使用LPUSH生产元素
  • 消费者使用RPOP消费元素

List有时候消费者的消费速度快于生产者的生产速度,就会出现List内没有元素的情况,如果消费者使用的是轮询执行RPOP会得到一些nil,这种方式存在一些缺点:

  • 轮询会导致Redis在List里面没有元素的情况下,执行RPOP返回nil(无效命令,算力浪费)
  • 使用的是轮询方案,为了尽可能的降低生产者和消费者之间的时间差,会降低轮询的时间间隔,这样会导致更多的RPOP(无效命令)被执行

Redis中提供了BRPOP命令来降低上诉轮询方案产生过多的无效命令和算力浪费

 > brpop iList 1
1) "iList"
2) "1"

 > brpop iList 1
(nil)

等待iList 1秒,是否存在元素,存在即弹出元素,不存在则返回nil

可以使用0来永久等待List中的元素产生,还可以指定多个List同时进行等待,并在第一个List获得元素时返回通知。
Redis在集群情况下,阻塞等待List的第一个Redis在其他Redis推送元素时最先提供服务,以此类推。
BRPOP返回的是一个双元素数组,包含Keys名,因为BRPOPBLPOP可以针对多个List操作
BRPOPBLPOP在超时后返回nil

扩展:旋转队列(环形队列?)LMOVE和阻塞命令BLMOVE

自动创建和删除Keys

适用于stream、map、hashmap、hash

  1. 在给聚合类型添加元素时,如果目标Keys不存在,则会在添加元素之前自动创建一个空的聚合数据类型
  2. 在删除聚合类型元素时,如果聚合数据类型值为空,则自动销毁Keys。(Stream例外)
  3. 使用只命令,例如LLEN,或者一个删除元素的写命令,使用一个空Keys,会产生相同的结果。

规则1:

 > del iList
(integer) 1

 > lpush iList 1 2 3
(integer) 3

如果Keys存在,不能对错误的数据类型操作

 > set iList iValue
"OK"

 > lpush iList 1 2 3
"WRONGTYPE Operation against a key holding the wrong kind of value"

 > type iList
"string"

规则2:

 > lpush iList 1 2
(integer) 2

 > exists iList
(integer) 1

 > lpop iList
"2"

 > lpop iList
"1"

 > exists iList
(integer) 0

弹出所有元素后,Keys被销毁

规则3:

 > del iList
(integer) 0

 > llen iList
(integer) 0

 > lpop iList
(nil)

hash

可以存放任意数量的字段和值(不超过内存大小)

 > hset iHash username RedCrazyGhost email redcrazyghost@163.com
(integer) 2

 > hget iHash username
"RedCrazyGhost"

 > hget iHash email
"redcrazyghost@163.com"

 > hgetall iHash
1) "username"
2) "RedCrazyGhost"
3) "email"
4) "redcrazyghost@163.com"

HMGET命令以数组的形式返回多个字段的值

 > hmget iHash username email
1) "RedCrazyGhost"
2) "redcrazyghost@163.com"

集合

无序的字符串集合。有利于表示对象的属性,可以轻松实现标签功能。

SADD命令将新元素添加到集合中

 > sadd iS 1 2 3
(integer) 3

 > smembers iS
1) "1"
2) "2"
3) "3"

SISMEMBER命令用于集合查询元素是否存在

> sismember iS 3
(integer) 1

 > sismember iS 30
(integer) 0

甚至可以进行类似倒排索引的存储

 > sadd Object:100:tags 1 5 7 99
(integer) 4

 > sadd tag:1:Object 100
(integer) 1

 > sadd tag:5:Object 100
(integer) 1

 > sadd tag:7:Object 100
(integer) 1

 > sadd tag:99:Object 100
(integer) 1

 > smembers Object:1:tags
1) "1"
2) "5"
3) "7"
4) "99"

注:假设使用Redis Hash,可以将标签ID关联到标签名称

SINTER命令用于不同集合之间取交集

 > sinter tag:1:Object tag:5:Object tag:7:Object tag:99:Object
1) "100"

扑克牌示例:

♣️ 梅花 ♦️ 方块 ♥️ 红心 ♠️ 黑桃
(C)lubs (D)iamonds (H)earts (S)pades

下方取其上方内容首字母使用

 > sadd iCard C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 CJ CQ CK D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 DJ DQ DK H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 HJ HQ HK S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 SJ SQ SK
(integer) 52

第一局游戏开始!SUNIONSTORE命令用于复制集合

 > SUNIONSTORE game:1:card iCard
(integer) 52

给玩家发牌,SPOP命令用于随机删除一个元素并将其结果返回

 > SPOP game:1:card
"D3"

 > SPOP game:1:card
"D5"

 > SPOP game:1:card
"S9"

 > SPOP game:1:card
"H5"

 > SPOP game:1:card
"SQ"

手气似乎不太好,此时可以使用SCARD命令查看集合中的元素数量

 > scard game:1:card
(integer) 47

52-5=47,看来这个发牌员没有黑手。

如果只想随机获取元素并不想删除元素,则可以使用SRANDMEMBER命令,这个命令还具有返回重复元素或非重复元素的能力

排序集合

类似Set和Hash的混合,排序集合的值是具有唯一且不重复的字符串。每个值都有一个浮点类型的数值(分数),排序按照一下规则排序

首先按照分数大小比较排序
出现分数相同的情况则比较两个数值的字典顺序

下方实例:按照出生年为分数比较

 > zadd iUser 2000 RedCrazyGhost
(integer) 1

 > zadd iUser 1999 xiaoming
(integer) 1

 > zadd iUser 1999 xiaowang
(integer) 1

 > zrange iUser 0 -1
1) "xiaoming"
2) "xiaowang"
3) "RedCrazyGhost"

排序集合通过哈希表的双端口和跳跃列表的数据结构完成添加元素的时间复杂度为O(log(N))

zrevrange用于反向排序,携带withscores参数返回分数

 > zrevrange iUser 0 -1 withscores
1) "RedCrazyGhost"
2) "2000"
3) "xiaowang"
4) "1999"
5) "xiaoming"
6) "1999"

zrangebyscore命令返回满足不同分数规则的结果,
zrank命令查询元素的位置,
zremrangebyscore命令删除满足不同分数规则的元素

 > zrangebyscore iUser -inf 1999
1) "xiaoming"
2) "xiaowang"

 > zrank iUser RedCrazyGhost
(integer) 2

 > zremrangebyscore iUser 1999 2000
(integer) 3

词典

Redis 2.8的最新版本中,引入新功能,允许按照字典顺序获取范围

> zadd iUser 0 A 0 B 0 C 0 D
(integer) 4

 > zrange iUser 0 -1
1) "A"
2) "B"
3) "C"
4) "D"

 > zrangebylex iUser [B [Z
1) "B"
2) "C"
3) "D"

排序集合的分数可以随时更新,由于地层的数据结构,适合用于纯在大量数据更新时。
常见用法是用于作为排行榜使用

Bit

Bit不是实际的数据类型,而是定义在String类型上的一组二进制数据。由于String是二进制安全的blob,并且最大长度为512MB,因此它们适合设置最多2^32个不同的位

Bit操作分为两种:

  1. 恒定时间单个位操作,例如将Bit设置为0或1
  2. 对位组的操作,例如计算给定Bit范围内的数值和

Bit的优点之一就是可以使用512MB的内存记录下40亿用户的单个Bit信息

SETBIT设置bit,位号为第一个参数,值为第二参数(0/1),如果寻址的位超出当前字符串长度,则会自动扩大字符串
GETBIT获取bit,超出范围的位则返回0

 > setbit iBit 1 1
(integer) 0

 > getbit iBit 1
(integer) 1

 > getbit iBit 2
(integer) 0

对位组的操作有以下三种:

  1. BITOP在不同的字符串之间执行运算(AND、OR、XOR、NOT)
  2. BITCOUNT执行计数,返回设置为1的位数
  3. BITPOS返回指定值0/1的第一个位

BITCOUNTBITPOS对字符串字节对范围内进行操作

 > bitcount iBit
(integer) 1

常见用例:

  • 各种实时分析
  • 存储与对象ID关联的节省空间但高性能的Bool
@RedCrazyGhost RedCrazyGhost added the Redis fa-solid fa-database label Mar 3, 2023
@RedCrazyGhost RedCrazyGhost added the Docker fa-brands fa-docker label Jul 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docker fa-brands fa-docker Redis fa-solid fa-database
Projects
None yet
Development

No branches or pull requests

1 participant