[redis系列] redis数据结构—命令篇

本redis系列文章集合https://blog.csdn.net/home_liang/article/details/148634904

介绍

redis的key是字符串类型, 而value可以是字符串类型 (memcached仅支持这一种类型)、列表类型、散列类型、集合类型、有序集合类型等等.

开发环境

# redis version: 7.4.2
# python version: 3.11
# redis-py version: 6.2.0

import redis

# 连接本地 Redis 服务,默认端口是 6379
client = redis.Redis(host='localhost', port=6379, decode_responses=True)

通用命令

通用命令是指与具体数据结构无关的命令.

KEYS

1. *匹配0-任意个字符
2. ?匹配单个字符
3. [abc]匹配方括号内的任意一个字符

# 获取test开头的所有key
client.keys("test*")

SCAN

# 迭代数据库中的数据库键
# SCAN 命令是一个基于游标的迭代器,每次被调用之后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数,以此来延续之前的迭代过程。

client.scan(cusor=0, match="*", count=1, _type="HASH")

# 4个重要参数
cursor: 游标位置, 直接用上一次scan命令的返回值
match: 与keys命令的pattern一致
count: 建议redis一次返回的数量, 但redis并不一定按照count返回
_type: 非检索条件, 只按redis数据结构类型对查询结果做一次过滤

EXISTS

# 是否存在key1
client.exists("key1")

TYPE

# 查看my_hash_key的类型, 比如为hash类型
client.type("my_hash_key")

PERSIST & TTL & PTTL

# 返回key1的ttl, 单位是秒, 如果是永久, ttl为-1
client.ttl("key1")

# 返回key1的ttl, 单位是毫秒, 如果是永久, pttl为-1
client.pttl("key1")

# 将ttl设置为永久
client.persist('key1')

EXPIRE & EXPIREAT & PEXPIRE & PEXPIREAT

# 设置my_hash_key的过期时间为10s
client.expire("my_hash_key", 10)
client.pexpire("my_hash_key", 10000)

# expireat和pexpireat是设置绝对时间, 而expire和pexpire是设置相对时间

# 4个重要参数
NX: 当且仅当该key 没有 设置过期时间
XX: 当且仅当该key 有 设置过期时间
GT: 当且仅当新的过期时间 大于 该key当前的过期时间
LT: 当且仅当新的过期时间 小于 该key当前的过期时间

DEL

# 删除key1 key2, 支持同时删除多个
client.delete('key1', 'key2')

字符串类型 STRING

SET

# set命令有很多参数:

1. key/value: 将key的值设置成value
client.set('my_name', 'enroute')

2. NX/XX: 当且仅当key不存在/存在时
client.set('my_name', 'enroute', nx=True)
client.set('my_name', 'enroute', xx=True)

3. EX/PX/EXAT/PXAT: 相对时间-单位秒/相对时间-单位毫秒/绝对时间-单位秒/绝对时间-单位毫秒
// 1s后过期
client.set('my_name', 'enroute', ex=1)
client.set('my_name', 'enroute', px=1)
client.set('my_name', 'enroute', exat=int(time.time()) + 1)
client.set('my_name', 'enroute', exat=int(time.time()*1000) + 1000)

4. GET: 返回旧value
client.set('my_name', 'new enroute', get=True)

5. KEEPTTL: 保留key的旧ttl, 如果key不存在, 则不设置ttl
client.set('my_name', 'enroute', keepttl=True)

SETNX & SETEX & GETSET & PSETEX 其实都对应着 SET 命令的选项, redis官方已经不建议使用, 而是使用 SET 命令结合相应的选项, 比如:

SETNX (deprecated)

As of Redis version 2.6.12, this command is regarded as deprecated.

It can be replaced by SET with the NX argument when migrating or writing new code.

GET

client.get("key1")

MSET & MGET

# 同时set多个, 但是不支持指定额外参数
client.mset({"key1": "value1", "key2": "value2"})

# 同时get多个
client.mget("key1", "key2")

APPEND & GETRANGE & SETRANGE

# 给key1的值value1追加字符串, 结果为: value1_suffix
client.append("key1", "_suffix")

# 若key1的值为value1, setrange会将值改为vxxxe1, 等价于replace
# offset=1 为偏移量
# xxx为替换的字符串
client.setrange("key1", 1, "xxx")

# 若key1的值为value1, getrange会返回al, 等价于切片
# start=1 end=2, [start, end]
client.getrange("key1", 1, 2)

# 获取key1的值字符串长度
client.strlen("key1")

STRLEN

# 获取key1的值字符串长度
client.strlen("key1")

数字类型

redis本身并没有指出数字类型, 只是在进行数字的相关操作时, redis会将字符串转为数字 (如果字符串不是数字会抛出异常), 并进行数字运算.

 INCR & INCRBY & DECR & DECRBY

# 给key1的值value1加1
# 如果value1不是数字会报错
# 如果key1不存在, 会设置其值为1
client.incr("key1")

# 给key1的值value1加888
# 如果value1不是数字会报错
# 如果key1不存在, 会设置其值为888
client.incrby("key1", 888)

# 给key1的值value1减1
# 如果value1不是数字会报错
# 如果key1不存在, 会设置其值为-1
client.decr("key1")

# 给key1的值value1减888
# 如果value1不是数字会报错
# 如果key1不存在, 会设置其值为-888
client.decrby("key1", 888)

位类型

SETBIT, GETBIT

# 将key1的第10 bit位设置为1
client.setbit("key1", 10, 1)

# 获取key1的第10 bit位, 默认值为0
client.getbit("key1", 10)

列表类型 LIST

可以当数组、链表、堆栈、队列使用

数组 & 链表

RPUSH & RPUSHX

# 列表尾部添加任意数量元素
# 注意顺序是["v4","v5"]
client.rpush("list_key", "v4", "v5")

# 当且仅当列表存在时,向列表尾部添加一个元素
client.rpushx("list_key", "v4")

LLEN

# 获取list的元素个数
client.llen("list_key")

LRANGE

# 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 
# 也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推
# 获取全部元素
client.lrange("list_key", 0, -1)

LINDEX

# 按数组下标访问元素
client.lindex("list_key", 2)

LSET

# 按数组下标设置元素, 当list_key不存在或者下标超出数组长度, 都会报错
client.lset("list_key", 1, "v3")

LTRIM

# 裁剪,只保留[start,end]的元素
# 裁剪掉首位元素
client.ltrim("list_key", 1, -2)

LREM

# 删除3个值为v2的元素
client.lrem("list_key", count=-3, "v2")

# count参数
count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
count = 0 : 移除表中所有与 VALUE 相等的值。

LINSERT

# 在v1元素之前或之后插入v3元素
client.linsert("list_key", "BEFORE", "v1", "v3")
client.linsert("list_key", "AFTER", "v1", "v3")

堆栈 & 队列

LPUSH & LPUSHX

# 列表头部添加任意数量元素
# 注意顺序是["v2","v1"]
client.lpush("list_key", "v1", "v2")

# 当且仅当列表存在时,向列表头部添加一个元素
client.lpushx("list_key2", "v3")

LPOP & BLPOP

# 弹出列表头部的元素
client.lpop("list_key")

# 比lpop多个timeout参数,当列表有元素直接弹出头部元素
# 当列表没有元素时会等待(单位秒)直到列表有元素或超时
client.blpop("list_key", timeout=3)

RPOP & BRPOP

# 弹出列表头部的元素
client.rpop("list_key")

# 比rpop多个timeout参数,当列表有元素直接弹出尾部元素
# 当列表没有元素时会等待(单位秒)直到列表有元素或超时
client.brpop("list_key", timeout=3)

哈希类型 HASH

HSET & HMSET

# 设置my_hash_key的field1值为value1, 支持同时set多个field
# HMSET功能与HSET一致
client.hset("my_hash_key", "field1", "value1")

HSETNX

# 当my_hash_key的field2不存在, 设置其值为value2
client.hsetnx("my_hash_key", "field2", "value2")

HGET & HMGET & HGETALL

# 获取my_hash_key的field1的值
client.hget("my_hash_key", "field1")

# 获取my_hash_key的所有field的值
client.hgetall("my_hash_key")

# 获取my_hash_key的field1和field2的值, 支持同时获取多个field
client.hmget("my_hash_key", "field1", "field2")

HKEYS & HVALS

# 获取my_hash_key的所有field
client.hkeys("my_hash_key")

# 获取my_hash_key的所有field的值
client.hvals("my_hash_key")

HLEN & HSTRLEN

# my_hash_key所包含field的数量
client.hlen("my_hash_key")

# my_hash_key的field1对应值的字符串长度
client.hstrlen("my_hash_key", "field1")

HEXISTS

# my_hash_key的field1是否存在
client.hexists("my_hash_key", "field1")

HDEL

# 删除my_hash_key的field1和field2, 支持同时删除多个
client.hdel("my_hash_key", "field1", "field2")

HSCAN

# 迭代my_hash_key中的field和value
client.hscan("my_hash_key", cursor=0, match="*", count=1, no_values=True)

# 4个重要参数
cursor: 类似scan命令
match: 类似scan命令
count: 类似scan命令
no_values: 只返回field, 而不返回value

集合类型 SET

SADD

# 添加两个member1和member2到my_set_key, 支持同时添加多个
client.sadd("my_set_key", "member1", "member2")

SCARD

# 查看my_set_key的所有member数量
client.scard("my_set_key")

SISMEMBER

# 查看member1是否是my_set_key中的member
client.sismember("my_set_key", "member1")

SMEMBERS

# 查看my_set_key中的所有member
client.smembers("my_set_key")

SSCAN

# 迭代my_set_key中的member
client.sscan("my_set_key", cursor=0, match="*", count=1)

# 4个重要参数
cursor: 类似scan命令
match: 类似scan命令
count: 类似scan命令

SREM

# 删除my_set_key中的member1和member2, 支持同时删除多个
client.srem("my_set_key", "member1", "member2")

SMOVE

# 将member1从my_set_key1中删除, 并添加到my_set_key2
# 如果my_set_key1不包含member1, 则不执行任何操作
client.smove("my_set_key1", "my_set_key2", "member1")

SPOP & SRANDMEMBER

# 从my_set_key中随机弹出2个元素 (弹出意味着获取并删除), 返回值不重复
client.spop("my_set_key", 2)

# 从my_set_key中随机获取2个元素, 返回值不重复
client.srandmember("my_set_key", 2)

交并差

SDIFF & SDIFFSTORE

# 差集

# 返回在my_set_key1但不在my_set_key2中的所有元素
# my_set_key1和my_set_key2中的元素不变
client.sdiff("my_set_key1", "my_set_key2")

# 将差集结果放到dest_set_key中
# my_set_key1和my_set_key2中的元素不变
client.sdiffstore("dest_set_key", "my_set_key1", "my_set_key2")

SINTER &SINTERSTORE

# 交集

# 返回同时在my_set_key1和my_set_key2中的所有元素
# my_set_key1和my_set_key2中的元素不变
client.sinter("my_set_key1", "my_set_key2")

# 将交集结果放到dest_set_key中
# my_set_key1和my_set_key2中的元素不变
client.sinterstore("dest_set_key", "my_set_key1", "my_set_key2")

SUNION & SUNIONSTORE

# 并集

# 返回在my_set_key1或者在my_set_key2中的所有元素
# my_set_key1和my_set_key2中的元素不变
client.sunion("my_set_key1", "my_set_key2")

# 将并集结果放到dest_set_key中
# my_set_key1和my_set_key2中的元素不变
client.sunionstore("dest_set_key", "my_set_key1", "my_set_key2")

有序集合类型 ZSET

有序集合 zset 和集合 set 一样不允许重复的成员, 不同的是 zset 每个成员都会关联一个 double 类型的分数, zset 的成员是唯一的, 但成员的分数可以重复。

有序集合 zset 的有序体现在:

1. 排序规则: 成员按分数进行排序。分数小的成员排在前面,分数大的成员排在后面。

2. 相同分数的成员顺序: 如果两个成员的分数相同,会按照成员的字典序进行排序。

ZADD

# 为my_zset_key添加两个member, 分数分别为1.5和2
# 此命令也可更新已有member的score
client.zadd("my_zset_key", {"member1": 1.5, "member2": 2})

# 重要参数
NX: 当且仅当member不存在时才添加
XX: 当且仅当member存在时才更改score
GT/LT: 当且仅当新score 大于/小于 当前score才更新, 不影响添加操作

ZINCRBY

# 为my_zset_key的member1分数添加888
client.zincrby("my_zset_key", 888, "member1")

ZSCORE

# 获取my_zset_key的member1分数
client.zscore("my_zset_key", "member1")

ZCARD

# 获取my_zset_key的member数量
client.zcard("my_zset_key")

ZSCAN

# 迭代my_zset_key中的member
client.zscan("my_zset_key", cursor=0, match="*", count=1)

# 4个重要参数
cursor: 类似scan命令
match: 类似scan命令
count: 类似scan命令

ZRANGE & ZREVRANGE

# 按照下标获取my_zset_key的member, withscores=True表示同时获取member的score
client.zrange("my_zset_key", 0, -1)
client.zrange("my_zset_key", 0, -1, withscores=True)

# 同上, 只是顺序为按照score倒序
client.zrevrange("my_zset_key", 0, -1, withscores=True)

ZRANGEBYLEX & ZREVRANGEBYLEX

前提条件: 所有member都是相同的score, 才能保证字典序有意义

# 仅当所有member的score全部一样时, bylex才有意义

# 按字典序正序获取my_zset_key的member
client.zrangebylex("my_zset_key", min="(member1", max="+", start=1, num=2)

# 按字典序倒序获取my_zset_key的member
client.zrevrangebylex("my_zset_key", min="(member1", max="+", start=1, num=2)

# 4个重要参数
min: - 表示最小, (表示不包括边界, [表示包括边界
max: + 表示最大, (表示不包括边界, [表示包括边界
start: 表示offset
num: 表示pagesize

ZRANGEBYSCORE & ZREVRANGEBYSCORE

# 按照score正序获取my_zset_key的member
client.zrangebyscore("my_zset_key", min=1.0, max=3.5, start=0, num=10, withscores=True)

# 按照score倒序获取my_zset_key的member
client.zrevrangebyscore("my_zset_key", min=1.0, max=3.5, start=0, num=10, withscores=True)

# 5个重要参数
min: score下限
max: score上限
start: 表示offset
num: 表示pagesize
withscores: 表示是否返回score

ZCOUNT & ZLEXCOUNT

# 获取my_zset_key的分数在[min, max]的成员数
client.zcount("my_zset_key", min=1, max=1.5)

# 获取my_zset_key的成员字典序在[min, max]的成员数
client.zlexcount("my_zset_key", min="(member1", max="+")

ZRANK & ZREVRANK

# 获取my_zset_key的成员member1的下标, withscore=True表示同时返回分数
client.zrank("my_zset_key", "member1", withscore=True)

# 获取my_zset_key的成员member1的倒序下标, withscore=True表示同时返回分数
client.zrevrank("my_zset_key", "member1", withscore=True)

ZREM

ZREMRANGEBYLEX & ZREMRANGEBYRANK & ZREMRANGEBYSCORE

# 删除my_zset_key的成员member1 member2, 支持同时删除多个
client.zrem("my_zset_key", "member1", "member2")

# ZREMRANGEBYLEX & ZREMRANGEBYRANK & ZREMRANGEBYSCORE 按照选定范围批量删除
# 参考 ZRANGEBYLEX & ZRANGE & ZRANGEBYSCORE

你可能感兴趣的:(redis)