02-API

nobility 发布于 2022-10-17 2638 次阅读


API

通用命令

  • keys:遍历所有key,筛选出复合条件的key,复杂度是O(n)O(n)
    • *:零个或多个任意字符
    • ?:一个任意字符
    • [a-z]:a到z中匹配的字符
  • dbsize:查看当前所有数据库中所有key的个数,复杂度是O(1)O(1)
  • exists:判断key是否存在,复杂度是O(1)O(1)
    • 存在返回1
    • 不存在返回0
  • del:根据key删除指定的键值对,也可同时指定多个key一起删除,复杂度是O(1)O(1)
  • expire:设置指定key的过期时间,单位秒,复杂度是O(1)O(1)
  • ttl:查看指定key的过期时间,复杂度是O(1)O(1)
    • 未过期返回还能存活多久的时间,单位秒
    • 已过期返回-2
    • 未设置过期时间返回-1
  • persist:删除指定key的过期时间设置,复杂度是O(1)O(1)
  • type:返回key的value所对应的数据类型,复杂度是O(1)O(1)
    • key不存在返回none
    • key存在返回对应的类型(全小写)

String数据类型

结构

  • 虽说是字符串,但是在使用不同命令进行操作时内部可以转换成对应的数字、二进制数组

  • 存储的最大限制是512MB

命令

  • get:根据key获取value,复杂度是O(1)O(1)
    • 若key不存在会返回nil,代表空
  • set:设置key和value,复杂度是O(1)O(1)
    • 若key不存在会添加,若key存在会覆盖
    • 衍射出的子命令:key和value在中间位置,即nx和xx是后缀
      • set nx:若key存在则设置失败,即添加操作,也可写成setnx
      • set xx:若key不存在则设置失败,即更新操作
  • mget:批量根据key获取value,复杂度是O(m)O( m )
    • 是原子操作
    • m与批量操作的个数有关由,所以由于网络延时的原因,合理使用该命令会比单个使用get命令效率高
  • mset:批量设置key和value,复杂度是O(m)O(m)
    • 是原子操作
    • m与批量操作的个数有关,所以由于网络延时的原因,合理使用该命令会比单个使用set命令效率高
  • getset:为key设置新的value,同时返回旧的value,复杂度是O(1)O(1)
    • 是原子操作
整型数字操作
  • incr:指定key自增1,复杂度是O(1)O(1)
    • 若key不存在会创建一个value为1的key
    • 若value有非数字的字符会报错,包括小数点
  • decr:指定key自减1,复杂度是O(1)O(1)
    • 若key不存在会创建一个value为-1的key
    • 若value有非数字的字符会报错,包括小数点
  • incrby:指定key自增指定步长,复杂度是O(1)O(1)
    • 若指定步长为负数就是递减了
    • 若key不存在会创建一个value为步长的key
    • 若value有非数字的字符会报错,包括小数点
  • decrby:指定key自减指定步长,复杂度是O(1)O(1)
    • 若指定步长为负数就是递增了
    • 若key不存在会创建一个value为负步长的key
    • 若value有非数字的字符会报错,包括小数点
浮点型数字操作
  • incrbyfloat:指定key自增指定步长,可以指定步长为小数,复杂度是O(1)O(1)
    • 若指定步长为负数就是递减了
    • 若key不存在会创建一个value为步长的key
    • 若value有非数字的字符会报错,不包括小数点
字符串操作
  • append:指定key的value后追加字符串,复杂度是O(1)O(1)
  • strlen:指定key的value中字符串的长度,复杂度是O(1)O(1)
    • 注意:一个中文字符会占用两个长度
  • getrange:获取key的value某指定范围子串,复杂度是O(1)O(1)
    • 下标从0开始,闭区间
    • 负数倒着数
  • setrange:设置key的value某指定位置开始,向后偏移的覆盖为指定内容,复杂度是O(1)O(1)
    • 下标从0开始
    • 负数倒着数

使用场景

存储对象方案一

将整个对象进行序列化或标准化为JSON、XML,将key做为对象的ID

  • 优点:访问Redis编程简单,节约内存

  • 缺点:序列化开销,修改属性需要操作字符串整个数据

存储对象方案二

将key为对象的业务ID+属性名,对各个属性分散存储,比如:user:name,使用冒号分隔

  • 优点:Redis数据直观可查,可部分属性更新,比较方便
  • 缺点:内存占用较大,key较为分散

Hash数据类型

结构

对应着一个Map集合,该Map集合的key称之为field,value还是value,并且这个集合中的field和value只能存储字符串数据类型

                  Map
             field   value
          +--------+--------+
          | field1 | value1 |
key ----> | field2 | value2 |
          | field3 | value3 |
          | ...    | ...    |
          +--------+--------+

命令

  • hget:获取指定key的field对应的value,复杂度是O(1)O(1)
  • hset:设置指定key的field对应的value,复杂度是O(1)O(1)
    • hsetnx:若field存在则设置失败,即添加操作
  • hdel:删除指定key的field对应的value,也可同时指定多个field一起删除,复杂度是O(1)O(1)
    • 若删除到整个Map都为空时,这个key也会被删除
  • hmget:批量获取指定key的field,复杂度是O(m)O(m)
    • 是原子操作
    • m与批量操作的个数有关
  • hmset:批量设置指定key的field的value,复杂度是O(m)O(m)
    • 是原子操作
    • m与批量操作的个数有关
  • hexists:判断指定key的field是否存在,复杂度是O(1)O(1)
    • 存在返回1
    • 不存在返回0
  • hlen:获取指定key的field的个数,复杂度是O(1)O(1)
遍历操作
  • hgetall:获取所有field和value,复杂度是O(m)O(m)
    • m与field个数有关
  • hvals:获取所有的value,复杂度是O(m)O(m)
    • m与field个数有关
  • hkeys:获取所有的key,复杂度是O(m)O(m)
    • m与field个数有关
整型数字操作
  • hincrby:指定key的field的value自增指定步长,复杂度是O(1)O(1)
    • 若field不存在会创建一个value为步长的field
      • 若key不存在会先创建key,再创建field
    • 若指定步长为负数就是递减了
    • 若value有非数字的字符会报错,包括小数点
浮点数字操作
  • hincrbyfloat:指定key的field的value自增指定步长,可以指定步长为小数,复杂度是O(1)O(1)
    • 若field不存在会创建一个value为步长的field
      • 若key不存在会先创建key,再创建field
    • 若指定步长为负数就是递减了
    • 若value有非数字的字符会报错

使用场景

存储对象

将对象属性在field中,将key做为对象的ID

  • 优点:Redis数据直观可查,可部分属性更新,比较方便,节约内存(底层到一定程度会该为压缩Map编码格式)

  • 缺点:访问Redis编码稍微比较复杂,属性过期时间不好控制(需要自己逻辑实现)

List数据类型

结构

  • 有序,有重复元素
  • 有独特的负索引
[ a,  b,  c,  d] : 元素列表
[ 0,  1,  2,  3] : 正索引
[-4, -3, -2, -1] : 负索引,即倒数第几个,从1开始

命令

增加
  • rpush:在指定key的右面添加一个或多个元素,复杂度是O(1)O(1)O(m)O(m),m取决于要添加的个数
    • 插入多个元素时,从左向右依次添加到右面
  • lpush:在指定key的左面添加一个或多个元素,复杂度是O(1)O(1)O(m)O(m),m取决于要添加的个数
    • 插入多个元素时,从左向右依次添加到左面
  • linsert:在指定key的指定元素前面或后面插入元素,需要遍历整个列表,复杂度是O(m)O(m)
    • before:前面插入
    • after:后面插入
删除

若删除到整个List都为空时,这个key也会被删除

  • rpop:从指定key的右面删除一个元素,复杂度是O(1)O(1)
  • lpop:从指定key的左面删除一个元素,复杂度是O(1)O(1)
  • lrem:从指定key中删除指定个数的与之匹配的元素,复杂度是O(n)O( n )
    • count等于0:全部删除
    • count是正数:从左往右删除count个
    • count是负数:从右往左删除count个
  • ltrim:将指定key中的列表修剪为指定索引范围内(闭区间)的子列表,复杂度是O(n)O(n)
  • brpop:阻塞的从指定key的右面删除一个元素,即若列表为空时会等待到有值时才会弹出,复杂度是O(1)O(1)
    • timeout:设置的阻塞超时时间,单位秒,若设置为0,代表用不阻塞
  • blpop:阻塞的从指定key的左面删除一个元素,即若列表为空时会等待到有值时才会弹出,复杂度是O(1)O(1)
    • timeout:设置的阻塞超时时间,单位秒,若设置为0,代表用不阻塞
修改
  • lset:设置指定key下指定索引的元素内容,复杂度是O(n)O( n )
查询
  • lrange:获取指定key的指定索引范围内(闭区间)的所有元素,复杂度是O(n)O(n)
    • lrange key 0 -1:遍历整个列表
  • lindex:获取指定key的指定索引下的元素,复杂度是O(n)O(n)
  • llen:获取指定key的列表长度,复杂度是O(1)O(1)

使用场景

  • 栈:使用lpushlpop
  • 队列:使用lpushrpop
  • 固定容量的容器集合:使用lpushltrim
  • 消息队列:使用lpushbrpop

Set数据类型

结构

  • 无序,无重复元素
  • 支持集合间的操作

命令

集合内的操作
  • sadd:向指定key中添加元素(可添加多个),若元素已存在则不会添加进去,复杂度是O(1)O(1)
  • srem:将指定key中的元素删除(可删除多个),复杂度是O(1)O(1)
  • sismember:判断元素是否存在集合中,存在返回1,不存在返回0,复杂度是O(1)O(1)
  • srandmember:获取指定key中随机的一个或多个元素,个数可以指定,复杂度是O(1)O(1)
    • 指定个数为正数:一次性获取过多时,不会超过集合中元素个数
    • 指定个数为负数:一次性获取过多时,可以超过集合元素个数
  • spop:将指定key中元素随机删除一个或多个,个数可以指定,且不允许为负数,复杂度是O(1)O(1)
  • smembers:获取指定key中的所有元素,复杂度是O(m)O(m),m取决于集合中元素的个数
  • scard:获取指定key中元素的个数,复杂度是O(1)O(1)
集合间的操作
  • sdiff:返回指定key的差集,可指定多个key,若只有一个则返回key集合本身
    • sdiffstore:从第二个key开始计算,不返回结果,将结果存储在第一个key中
  • sinter:返回指定key的交集,可指定多个key,若只有一个则返回key集合本身
    • sinterstore:从第二个key开始计算,不返回结果,将结果存储在第一个key中
  • sunion:返回指定key的并集,可指定多个key,若只有一个则返回key集合本身
    • sinterstore:从第二个key开始计算,不返回结果,将结果存储在第一个key中

使用场景

抽奖系统

将参与的用户添加到集合中,在使用spopsrandmember获取获奖用户

赞踩系统

将赞或踩过的用户添加到该消息的赞踩集合中,使用集合间操作sinter,就可以得到共同爱好的用户

标签系统

给用户添加标签,使用sadd,将标签添加到用户集合中

给标签添加用户,使用sadd,将用户添加到标签集合中

ZSet数据类型

结构

  • 有序,无重复元素
  • 每个元素都多存储着一个分数信息,是根据分数来排序的,从小到大
                  Map
             value    key
                |      |
               \|/    \|/
             score   element
          +--------+----------+
          | score1 | element1 |
key ----> | score2 | element2 |
          | score3 | element3 |
          | ...    | ...      |
          +--------+----------+

命令

集合内的操作
  • zadd:向指定key中添加分数和元素(可添加多对),若元素已存在则不会添加进去,复杂度是O(logn)O(log_n)
  • zrem:将指定key中的元素删除(可删除多个),复杂度是O(1)O( 1 )
  • zscore:获取指定key中指定元素的分数,复杂度是O(1)O(1)
  • zrank:获取指定key中元素的从高到底排名,排名从零开始,复杂度是O(n)O(n)
  • zrevrank:获取指定key中元素的从低到高排名,排名从零开始,复杂度是O(n)O(n)
  • zincrby:将指定key中指定元素的分数自增指定步长,复杂度是O(1)O(1)
    • 若指定步长为负数就是递减了
    • 若element不存在会创建一个score为步长的key
      • 若key不存在会先创建key,再创建element
    • 若value有非数字的字符会报错,不包括小数点
  • zcard:获取指定key中元素的个数,复杂度是O(1)O(1)
范围操作
  • zrange:获取指定key的指定排名(排名从零开始)范围内(闭区间)的所有元素(升序),复杂度是O(logn+m)O(log_n+m),n是指有序集合中的元素个数,m是指范围内的元素个数
    • withscores:若加此后缀参数后,元素分数也会对应返回
    • zrange key 0 -1:遍历整个有序集合
    • zrange key 0 -1 withscores:遍历整个有序集合,包括分数
  • zrevrange:降序的zrange
  • zrangebyscore:获取指定key的指定分数范围内(闭区间)的所有元素(升序),复杂度是O(logn+m)O(log_n+m),n是指有序集合中的元素个数,m是指范围内的元素个数
    • withscores:若加此后缀参数后,元素分数也会对应返回
  • zrevrangebyscore:降序的zrangebyscore
  • zcount:获取指定key的指定分数范围内(闭区间)的元素个数,复杂度是O(logn+m)O(log_n+m),n是指有序集合中的元素个数,m是指范围内的元素个数
  • zremrangebyrank:删除指定key的指定排名范围(闭区间)的元素,复杂度是O(logn+m)O(log_n+m),n是指有序集合中的元素个数,m是指范围内的元素个数
  • zremrangebyscore:删除指定key的指定分数范围(闭区间)的元素,复杂度是O(logn+m)O(log_n+m),n是指有序集合中的元素个数,m是指范围内的元素个数
集合间的操作
  • zunionstore:返回指定key的并集(必须指定要操作的key的个数),可指定多个key,从第二个key开始计算,将结果存储在第一个key中
    • withscore:设置乘法因子,默认都是1,若有重复key在合并时,是将两个相同的元素的分数进行相加,若还需要乘上一个数在相加就需要在该参数中设置
  • zinterstore:返回指定key的交集(必须指定要操作的key的个数),可指定多个key,从第二个key开始计算,将结果存储在第一个key中
    • withscore:设置乘法因子,默认都是1,重复key在合并时,是将两个相同的元素的分数进行相加,若还需要乘上一个数在相加就需要在该参数中设置

使用场景

排行榜

使用zadd进行分数添加、zincrby进行分数添加、zrem进行删除,对于这些最核心的就是分数使用什么表示

  • 更新榜:使用时间戳作为分数
  • 点赞榜:使用点赞量即可
  • 月榜周榜日榜:使用日榜进行并集汇总

Bitmap数据结构

结构

其实就是字符串,每个字符都是以ASCII进行编码,位图提供了一种操作字符串中单个二进制位的API,对于这些API来说复杂度是O(m)O(m),m取绝于字符串中二进制位的个数

命令

  • getbit:获取字符串中的指定索引的二进制位
    • 若超过字符串二进制位数长度,会返回0
  • setbit:设置字符串中的指定索引的二进制位,只能设置0和1
    • 若key不存在会创建key
    • 若超过字符串二进制位数长度,会在前面自动补零
  • bitcount:获取指定key中二进制位为1的个数
    • 可指定范围,注意范围说的是字节范围,8个二进制位为一个字节,闭区间,索引从0开始
  • bitop:从第二个key开始做位运算,结果存放到第一个key中,返回结果key的字节长度
    • and:与
    • or:或
    • not:非
    • xor:异或
  • bitpos:获取指定key中,从左到右,第一个为0或1的二进制位索引
    • 可指定范围,注意范围说的是字节范围,8个二进制位为一个字节,闭区间,索引从0开始

使用场景

用户统计

将所有用户都与一个索引对应(用户ID),将赞或踩过的用户对应的索引位置为1

相比set,若要记录的用户越多则该方式越省内存,反之则会更浪费内存,因为set至少需要一个整型(32位)来记录一个用户,bitMap只需要一个二进制位,若用户ID很大会导致一个用户会使用很大的索引导致索引偏后,前面二进制位都是无用的内容

要注意,Redis中一个字符串的最大容量是512MB,并且在位操作时也比较耗时

HyperLogLog数据结构

结构

基于HyperLogLog算法,极小空间完成独立数量统计的数据结构,本质还是字符串

  • 不会有重复元素
  • 有错误率,错误率为0.81%
  • 无法该结构内元素对单个用户进行判断是否已经存入

命令

  • pfadd:向指定key中添加元素(可添加多个),添加正常会返回1,而不是添加成功的个数
  • pfcount:返回指定key中的元素个数
  • pfmerge:从第二个key开始进行合并,合并后的结果存放到第一个key中

使用场景

只需要统计用户数,不关心其他问题,并且可以容忍错误率

GEO数据结构

结构

基于ZSet实现,所以可以使用ZSet的所有命令

命令

  • geoadd:向指定key中添加经纬度和地名(可添加多对),地名不会重复,仅仅其标识作用
  • geopos:获取指定key下的指定地名的经纬度
  • geodist:计算指定key下的两个地名之间的距离
    • unit:指定距离单位,mkmmi(英尺)、ft(尺),默认是m
  • georadius:获在指定key中某个地理位置在一定范围内(需要指定单位)的地理位置信息集合
    • withcoord:返回包含经纬度
    • withdist:返回包含距中心节点的距离,单位与指定的一致
    • withhash:返回结果中包含geohash(52位有符号整数)
    • count:返回指定数量结果
    • asc|desc:返回结果按照距离中心位置升序或降序
    • store:将返回结果的位置信息保存在指定键中
    • storedist:将距离保存在指定的键中

使用场景

存储地理信息,计算距离,范围等

发布订阅

发布订阅模型

命令

  • publish:向指定频道发送消息(频道就是key),返回订阅者的数量
  • subscribe:订阅频道(可同时订阅多个频道)
    • psubscribe:模式订阅,可使用通配符进行多个频道的订阅
  • unsubscribe:取消订阅(可同时取消订阅多个频道)
    • punsubscribe:模式取消订阅,可使用通配符进行多个频道的订阅
  • pubsub channels:返回至少有一个订阅者的频道
  • pubsub numsub:列出指定频道的订阅者数量

消息格式

  • 首次开始监听订阅消息时的三行内容:

    1. 固定内容subscribe,即刚才执行的命令
    2. 频道的名称,即刚才执行命令的参数
    3. 固定内容返回1
  • 之后的接收的消息时的三行内容:

    1. 固定内容message
    2. 频道的名称
    3. 收到的新消息

代码

Java
发布者
import redis.clients.jedis.Jedis;

public class Main {
  public static void main(String[] args) {
    Jedis jedis = null;
    try {
      jedis = new Jedis("127.0.0.1", 6379);
      jedis.auth("redis");  //操作数据前设置的密码
      jedis.publish("channel", "hello");
    } finally {
      if (jedis != null) {
        jedis.close();
        //3. 关闭连接
      }
    }
  }
}
订阅者
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

public class Main {
  public static void main(String[] args) {
    Jedis jedis = new Jedis("122.51.213.160", 6379);
    jedis.auth("redis");  //操作数据前设置的密码
    /**
     * Jedis对象的subscribe()方法接收两个参数
     * JedisPubSub jedisPubSub :用来写监听接收到消息的监听函数,无法使用lambda表达式
     *             需要实现内部的onMessage()方法,监听函数会阻塞掉当前线程的运行
     *             String channel :接收到是那个频道的消息
     *             String message :接收到的消息
     * String... channels :所监听的频道,是个可变参数,所以可以同时监听多个频道
     */
    jedis.subscribe(new JedisPubSub() {
      @Override
      public void onMessage(String channel, String message) {
        System.out.println("接收到 " + channel + " 频道发送的:" + message);
      }
    }, "channel");
  }
}
Node
发布者
const redis = require("redis"); //导入redis模块
const client = redis.createClient(6379, "122.51.213.160", {
    password: "redis"
}); //获取redis连接对象
client.on("error", function (err) { //监听连接出错
    throw err;
});
client.once("connect", () => { //监听连接建立成功
    client.publish("testPublish", "message"); //向指定频道发布消息
    client.quit(() => console.log("关闭连接")) //关闭连接
})
订阅者
const redis = require("redis"); //导入redis模块
const client = redis.createClient(6379, "122.51.213.160", {
    password: "redis"
}); //获取redis连接对象
client.on("error", function (err) { //监听连接出错
    throw err;
});
client.once("connect", () => { //监听连接建立成功
    client.subscribe('testPublish');    //订阅频道
})
client.on('message', function (channel, msg) {  //监听以订阅频道消息
    console.log(channel, ":", msg);
});
此作者没有提供个人介绍
最后更新于 2022-10-17