redis相关命令详解及其原理


一、redis

Redis 是Remote Dictionary Service 的简称;也是远程字典服务;
Redis 是内存数据库(在内存当中的数据库),KV 数据库,数据结构数据库;
涉及到的数据结构有,string、hash、list、set、zset
怎么去操作redis的呢,当然是由一个端口,不断发送命令去操作redis
在这里插入图片描述

Redis 应用非常广泛,如Twitter、暴雪娱乐、Github、Stack Overflow、腾讯、阿里巴巴、京东、华为、新浪微博等,很多中小型公司也在使用;
Redis 命令查看:http://redis.cn/commands.html
redis是用一种数据结构组织多种数据,内部是用hashtable实现的,比如说c++的unorder_map<string, T>

二、redis中的数据结构

redis是一种kv数据库,它本身提供了16个数据库,redis是一个单线程,只能去操作一个,使用的时候也只使用一个数据库,那这里我们说到的数据库是什么概念呢,我们的数据库呢,需要一种结构去组织数据,比如说我们的mysql主要用到的是B+树。我们redis使用的结构是dictionary(字典),字典就是我们常说的kv对,像图中的val只能指向一个数据结构,不能指向多个数据结构
比如说val可以指向string类型
但是跟平常我们见到的字符串不同,我们可以看到图中出现了‘\0’这种字符串结束符,这里的字符串是一种安全的二进制字符串,不会受到特殊字符的影响,这里的结束符是不会影响的
再比如说还可以指向字典,链表(双端队列),有序(插入有序)
还能支持无序集合,对顺序不关注,里边的值是唯一的
还有我们的有序集合,对顺序关注,里边的值是唯一的,根据member来确定唯一,根据score确定有序在这里插入图片描述redis中value编码
在这里插入图片描述

string

字符数组,该字符串是动态字符串 raw,字符串长度小于1M 时,加倍扩容;超过 1M 每次只多扩1M;字符串最大长度为 512M;
注意:redis 字符串是二进制安全字符串;可以存储图片,二进制协议等二进制数据;
我们可以通过访问redis的官网http://redis.cn/,比如说我们搜索set相关的命令,点进去我们查看命令以及相关的返回值,对于返回值一定要注意类型,比如说用incr命令去累加一个字符串类型,这是会报错的,其实可以incr一个不存在的值进行累加,比如incr Whistle,会自动去创建一个Whistle。
在这里插入图片描述

在这里插入图片描述
我们再来看看setnx,能设置成功是返回1,否则为0,OK是这个命令是否执行了
在这里插入图片描述
string呢,其实可以作为位图使用,我们可以用object encoding查看内部编码格式,同样是string类型,其实可以有不同的编码方式,emstr是长度小于44的时候的格式表示嵌入字符串,大于44指的是raw动态字符串,这种能够节约内存。int的话对应4个字节32位,可以描述32种不同状态,但是比较单一
在这里插入图片描述
我们可以看到对位图的操作,设置k为xkdx,设置相应位的值
在这里插入图片描述
实际应用,对象存储
SET role:10001 ‘{[“name”]:“mark”,[“sex”]:“male”,[“age”]:30}’
GET role:10001
我们来说key如何来设置,满足这几点,有意义的字段,role:10001,使用冒号是因为客户端工具的要求,能生成一些树状结构
分布式锁,在于多个进程访问资源,然后需要只有一个进程去访问,就要用到分布式锁,其他进程必须等待。
比如说我们自旋锁对应是一种非公平锁,进程获取锁具有随机性
公平锁是按照请求的顺序去获取锁释放锁
在这里插入图片描述
#加锁
setnx lock 1
#释放锁
del lock
#1. 排他功能 2. 加锁行为定义 3. 释放行为定义
redis通常实现的是一种非公平锁
请求回应模式,就是比如说B发送命令要获取锁,没能获取,因为A占用了,命令就一直不返回,然后直到获取了锁才返回。
位运算
#月签到功能 10001 用户id 202106 2021年6月份的签到 6月份的第1天
setbit sign:10001:202106 1 1
#计算 2021年6月份 的签到情况
bitcount sign:10001:202106
#获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2

list

双向链表实现,列表首尾操作(删除和增加)时间复杂度 O(1) ;查找中间元素时间复杂度为
O(n) ;
列表中数据是否压缩的依据:
元素长度小于 48,不压缩;
元素压缩前后长度差不超过 8,不压缩;

基础命令
#从队列的左侧入队一个或多个元素
LPUSH key value [value …]
#从队列的左侧弹出一个元素 LPOP key
#从队列的右侧入队一个或多个元素
RPUSH key value [value …]
#从队列的右侧弹出一个元素 RPOP key
#返回从队列的 start 和 end 之间的元素 0, 1 2
LRANGE key start end
#从存于 key 的列表里移除前 count 次出现的值为 value 的元素
LREM key count value
#它是 RPOP 的阻塞版本,因为这个命令会在给定list无法弹出任何元素的时候阻塞连接
BRPOP key timeout#超时时间 + 延时队列

阻塞连接
redis关键特性:典型操作
关于阻塞连接,比如说BRPOP,往一个队列操作,如果队列为空,就必须加一个阻塞的操作,直到这个队列在其他的连接中加了值,然后这个连接就返回来了。这就是BRPOP,只要没有值就一直阻塞,直到有值了
在这里插入图片描述我们来操作一下,比如说nbsp没有值,后边的0表示一直阻塞,这里阻塞指的是连接,没有使用线程
在这里插入图片描述
存储结构是一种双端队列
实际应用

LPUSH + LPOP 或者 RPUSH + RPOP
队列
LPUSH + RPOP 或者 RPUSH + LPOP
阻塞队列
LPUSH + BRPOP 或者 RPUSH + BLPOP
异步消息队列
操作与队列一样,但是在不同系统间;
在这里插入图片描述

hash

散列表,在很多高级语言当中包含这种数据结构;c++ unordered_map 通过 key 快速索引value;

基础命令
#获取 key 对应 hash 中的 field 对应的值
HGET key field
#设置 key 对应 hash 中的 field 对应的值
HSET key field value
#设置多个hash键值对
HMSET key field1 value1 field2 value2 … fieldn valuen
#获取多个field的值
HMGET key field1 field2 … fieldn
#给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
#获取 key 对应的 hash 有多少个键值对
HLEN key
#删除 key 对应的 hash 的键值对,该键为
field HDEL key field

存储结构
节点数量大于 512(hash-max-ziplist-entries) 或所有字符串长度大于 64(hash-max-ziplistvalue),则使用 dict 实现;
节点数量小于等于 512 且有一个字符串长度小于 64,则使用 ziplist 实现;

应用
存储对象
hmset hash:10001 name mark age 18 sex male
#与 string 比较
set hash:10001 ‘{[“name”]:“mark”,[“sex”]:“male”,[“age”]:18}’
#假设现在修改 mark的年龄为19岁
#hash: hset hash:10001 age 19
#string: get role:10001
#将得到的字符串调用json解密,取出字段,修改 age 值
#再调用json加密
set role:10001 ‘{[“name”]:“mark”,[“sex”]:“male”,[“age”]:19}’
比如说购物车

set

集合;用来存储唯一性字段,不要求有序;存储不需要有序,交并差集的时候排序

基础命令
#添加一个或多个指定的member元素到集合的 key中
SADD key member [member …]
#计算集合元素个数
SCARD key
#SMEMBERS key
SMEMBERS key
#返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member
#随机返回key集合中的一个或者多个元素,不删除这些元素
SRANDMEMBER key [count]
#从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]
#返回一个集合与给定集合的差集的元素
SDIFF key [key …]
#返回指定所有的集合的成员的交集
SINTER key [key …]
#返回给定的多个集合的并集中的所有成员
SUNION key [key …]

存储结构
元素都为整数且节点数量小于等于 512(set-max-intset-entries),则使用整数数组存储;元素当中有一个不是整数或者节点数量大于 512,则使用字典存储;

应用
抽奖
#添加抽奖用户
sadd Award:1 10001 10002 10003 10004 10005 10006
sadd Award:1 10009
#查看所有抽奖用户
smembers Award:1
#抽取多名幸运用户
srandmember Award:1 10

zset

有序集合;用来实现排行榜;它是一个有序唯一;

基础命令
#添加到键为key有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score member …]
#从键为key有序集合中删除 member 的键值对
ZREM key member [member …]
#返回有序集key中,成员member的score值
ZSCORE key member
#为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
#返回key的有序集元素个数
ZCARD key
#返回有序集key中成员member的排名
ZRANK key member
#返回存储在有序集合key中的指定范围的元素 order by id limit 1,100
ZRANGE key start stop [WITHSCORES]
#返回有序集key中,指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]

存储结构
节点数量大于 128或者有一个字符串长度大于64,则使用跳表(skiplist);
节点数量小于等于128(zset-max-ziplist-entries)且所有字符串长度小于等于64(zset-maxziplist-value),则使用 ziplist 存储;
数据少的时候,节省空间; O(n)
数量多的时候,访问性能;O(1) o(logn)

应用比如说百度的热榜
在这里插入图片描述
#点击新闻:
zincrby hot:20210601 1 10001
zincrby hot:20210601 1 10002
zincrby hot:20210601 1 10003
zincrby hot:20210601 1 10004
zincrby hot:20210601 1 10005
zincrby hot:20210601 1 10006
zincrby hot:20210601 1 10007
zincrby hot:20210601 1 10008
zincrby hot:20210601 1 10009
zincrby hot:20210601 1 10010
#获取排行榜: zrevrange hot:20210601 0 9 withscores

延时队列
将消息序列化成一个字符串作为 zset 的 member;这个消息的到期处理时间作为 score,然后用多个线程轮询 zset 获取到期的任务进行处理。

分布式定时器
在这里插入图片描述生产者将定时任务 hash 到不同的 redis 实体中,为每一个 redis 实体分配一个 dispatcher 进程,用来定时获取 redis 中超时事件并发布到不同的消费者中;

时间窗口限流
系统限定用户的某个行为在指定的时间范围内(动态)只能发生N次;

三、应用与操作

我们来操作一下redis
创建一个kv,比如说我们设置一个k为hello,value为world
在这里插入图片描述
redis提供的是一种请求回应模式,一请求必须一回应,按照发送命令的顺序来进行执行,我们提一下mongo这种数据库,这种呢没有这样严格的有序性,每一次请求都要带一个session,必须要唯一,没有严格有序
根据k获取value
在这里插入图片描述
还有一种hash结构,通过这个来设置多重的k,如果是查找一个不存在的数据,会返回一个nil,如果是查找一个字典的数据,就需要把两个k都输入
在这里插入图片描述
如果我们重复设置会返回0
在这里插入图片描述
我们再来看看使用list,我们可以看到我们的list设置value的时候可以设置多个,然后我们获取的时候,0表示第一个value,-1表示倒数第一个
在这里插入图片描述
客户端去连接redis的时候,需要去验证owner以及密码,然后选定数据库,如果什么都数据库不去选,就是select 0

我们谈到的数据结构在实际的应用中是怎样的呢
记录朋友圈点赞数、评论数和点击数(hash)
记录朋友圈说说列表(排序),便于快速显示朋友圈(list)
记录文章的标题、摘要、作者和封面,用于列表页展示(hash)
记录朋友圈的点赞用户ID列表(list也可以),评论ID列表(list),用于显示和去重计数(zset有序又可去重)
缓存热点数据,减少数据库压力,这就是我们常说的缓存(hash)
如果朋友圈说说 ID 是整数 id,可使用 redis 来分配朋友圈说说 id(计数器)(string),比如说图中的sayid
在这里插入图片描述

通过集合(set)的交并差集运算来实现记录好友关系(set)
游戏业务中,每局战绩存储(list)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值