redis-----02-----redis-string结构以及应用

1 string

字符数组,redis字符串是二进制安全字符串,可以存储图片等二进制数据,同时也可以存储经过
messagepack 或者 protobuffer 等工具压缩后的二进制数据。

内部实际存储根据 string 的数据特征可采用 int 、 embstr 、 raw 存储(使用object encoding key来查看)。

  • 1)如果字符串长度小于20并能转成数字,那么使用int存储字符串。
  • 2)如果不满足1,且字符串长度小于44,即0<x<20但不能转成数字加上20<=x<44范围的字符串,那么使用embstr存储字符串。
  • 3)如果字符串长度大于44,那么使用raw存储字符串。
    例如:
192.168.1.9:6379> set hello world
OK
192.168.1.9:6379> get hello
"world"
192.168.1.9:6379>
192.168.1.9:6379>
192.168.1.9:6379> OBJECT encoding hello
"embstr"
192.168.1.9:6379> set hello 100
OK
192.168.1.9:6379> OBJECT encoding hello
"int"
192.168.1.9:6379> set hello 111111111111111111111111111111111111111111111111111111111111111111111111111111111
OK
192.168.1.9:6379> OBJECT encoding hello
"raw"

2 基础命令

Redis详细命令查看:http://redis.cn/commands.html。

2.1 SET、GET、INCR、INCRBY、DECR、DECRBY

# 设置 key 的 value 值 
SET key value [EX seconds] [PX milliseconds] [NX|XX]
# 获取 key 的 value 
GET key 

# 下面四个命令都有的特征:如果指定的key不存在,那么在执行incr操作之前,会自动创建并会先将它的值设定为0。
# 执行原子加一的操作。
# 返回值integer-reply:执行递增操作后key对应的值。
INCR key 
# 执行原子加一个整数的操作。
# 返回值integer-reply: 增加之后的value值。
INCRBY key increment

# 执行原子减一的操作。
# 返回值数字:减小之后的value。
DECR key 
# 执行原子减一个整数的操作。
# 返回值数字:减小之后的value。
DECRBY key decrement

结果:
在这里插入图片描述

2.2 SETNX、DEL

# 如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做。
# 返回值Integer reply, 特定值:1 如果key被设置了。0 如果key没有被设置。
SETNX key value

# 删除指定的一批keys,如果删除中的某些key不存在,则直接忽略。返回值integer-reply: 被删除的keys的数量。
DEL key [key ...]

可以看到前面,因为tyy存在,那么SETNX tyy 100是不会成功的,所以get tyy返回的值仍然是-100。
然后删除,删除很简单,你可以使用get tyy去看,此时会返回nil。
在这里插入图片描述

2.3 SETBIT、GETBIT、BITCOUNT
这几个命令主要是进行二进制位的操作,例如可以使用二进制位来记录一个月下来的打卡情况,打卡了置为1,没打卡置为0,并可以统计一个月打卡了多少天。

# 设置或者清空key的value(字符串)在offset处的bit值。 offset代表二进制位,从0开始。value只能是0或者1.
# 返回值integer-reply:返回在offset处原来的bit值。
SETBIT key offset value 
# 返回key对应的string在offset处的bit值。
GETBIT key offset 
# 统计字符串被设置为1的bit数. 
# 返回值Integer reply:返回被设置为 1 的位的数量。
BITCOUNT key
  • 下图看到,前两个命令可以确定我们的offset是从0开始的,因为第一次setbit返回默认的0,然后第二次setbit返回原来的值即第一次设置的值。
  • 然后setbit时,value不是0或者1时,会报越界的错误。
  • 然后后面就是简单的getbit,bitcount,注意bitcount返回1,是offset为10的,因为offset为0的value在第二条命令时被置为0了。
    在这里插入图片描述

3 应用

3.1 对象存储

字符串可以用来存储对象,此时key的设计需要注意,一般以:“具体功能:描述这个具体功能的唯一id”来命名的。例如下面:角色加上它的唯一id。后面的字符串就是这个key的具体对象信息。

SET role:10001 '{["name"]:"tyy",["sex"]:"male",["age"]:24}' 
GET role:10001

字符串存储对象信息一般是以json格式,但是注意:

  • json不能含义特殊字符例如\0,会被截断。
  • 因为json需要编码后存储,以及从redis读取后需要解码,所以使用string作对象存储时,这个对象信息应该是固定不变或者几乎不会修改它。否则应该使用后面讲到的hash字典去存储这个对象,因为hash修改个别字段是非常快速且方便的。

运行结果:
在这里插入图片描述

3.2 累加器

string的incr以及incrby可以做一些统计的信息,这个统计指的就是累加。例如微信文章的点击量,用户每次点击文章进入,那么我们就累加一次,这样就可以统计文章的点击量。
当然也可以每次先在内存累加,当内存累加的次数是100时,然后使用incrby进行记录,这样可以减少代码与redis服务器之间的交互,但是就无法做到实时更新点击量,大家可以按照实际场景来处理即可。

再或者支付宝的步数也是同理。

# 统计阅读数 累计加1 
incr reads 
# 累计加100 
incrby reads 100

3.3 分布式锁

在这里插入图片描述
例如上图,四个进程即四台集群的集群,同时访问同一台redis服务器中的某一个资源,那么我们就需要一把锁来进行限制,如果有进程在访问这个资源,那么其它进程此时就不能访问,只能等该进程访问完毕后,再去尝试访问。这把锁我们称为分布式锁,和常见的互斥锁其实是一样的道理。
分布式锁的特点(按照互斥锁理解即可):

  1. 排他性:有人访问,那么其它人不能访问。
  2. 定义获取锁行为:获取到锁才能访问。
  3. 定义释放锁行为:释放锁,代表本次访问结束,其它人可以申请锁去访问。

我们可以使用setnx来实现这个分布式锁。
例如下图:

  • 1)首先s1去获取锁,发现lock锁没有用,那么上锁成功。若此时s2来获取lock这把锁,会获取失败,所以返回了0。 既然获取到锁了,那么就可以访问共享数据了(假设get lock就是访问共享数据的操作)。访问完毕后,那么del lock就是释放这把锁了。
  • 2)经过前四个命令(实际是3个,setnx lock s2不算),一个人成功访问到共享资源并释放了锁。那么此时s2来上锁就会成功,然后再访问资源,最后释放锁。 下图就是模拟了两个人访问共享资源的例子。

但是下图只是简单的模拟分布式锁,实际开发中的分布式锁会比这个更难、更复杂。
在这里插入图片描述

分布式锁的注意点:

  • 1)setnx等价于set 命令后加nx。例如:
SETNX lock s1
# 等价于
SET lock s1 nx
  • 2)如果已经对一把锁上锁,再对这把锁上锁,同样会上锁失败,但不会像互斥锁那样卡死即死锁。
    例如下面,s1已经上锁,然后再setnx lock s1上锁,发现返回0但客户端cli不会卡死。
    在这里插入图片描述

3)为啥不能使用set来实现分布式锁呢,因为set无法做到排他性,例如上面的例子:当我s1上锁后正在访问数据,s2来上锁,也是能成功的,正确的应该是让s2等待,所以set无法做到排他性。
在这里插入图片描述

3.4 位运算

例如使用位运算进行处理月签到功能。

# 月签到功能。
# sign:签到功能。10001:用户id。202107:2021年7月份的签到。1:7月份的第1天。 末尾的1:代表签到了。 
setbit sign:10001:202107 1 1 

# 计算 2021年7月份 的签到情况。
bitcount sign:10001:202107 

# 获取 2021年7月份 第二天的签到情况。
# 1 已签到;0 没有签到。
getbit sign:10001:202107 2

redis中执行:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值