Redis1——基本命令及原理

文章目录

  • Redis1------基本命令及原理
    • [1. Redis原理](#1. Redis原理)
      • [1.1 特点](#1.1 特点)
      • [1.2 数据类型及其存储方式](#1.2 数据类型及其存储方式)
        • [1.2.1 **string** 字符串](#1.2.1 string 字符串)
        • [1.2.2 **list** 列表](#1.2.2 list 列表)
        • [1.2.3 **hash** 哈希表](#1.2.3 hash 哈希表)
        • [1.2.4 **set** 集合](#1.2.4 set 集合)
        • [1.2.5 **zset** 有序集合](#1.2.5 zset 有序集合)
    • [2. 基本命令及应用场景:](#2. 基本命令及应用场景:)
      • [2.1 Redis应用场景](#2.1 Redis应用场景)
      • [2.2 string------sds动态字符串](#2.2 string——sds动态字符串)
      • [2.3 list------双向循环链表](#2.3 list——双向循环链表)
      • [2.4 hash------散列表](#2.4 hash——散列表)
      • [2.5 set------无序集合](#2.5 set——无序集合)
      • [2.6 zset------有序集合](#2.6 zset——有序集合)
    • [2. 如何设计kv](#2. 如何设计kv)
      • [2.1 如何设计key](#2.1 如何设计key)
    • 学习参考

Redis1------基本命令及原理

1. Redis原理

Redis是Re mote D ictionary Service的简称,及远程字典服务。Redis是一个基于内存的存储键值对的非关系型数据库。

1.1 特点

  • 没有显式地创建和和删除数据结构地语句,当添加元素地时候自动创建,当删除元素时,如果集合为空,则自动删除数据结构。
  • 数据量少的时候,以存储效率高为主(ziplist),数据量大的时候以查询效率高为主(skiplist,dict)

1.2 数据类型及其存储方式

主要是指value指的数据结构:

1.2.1 string 字符串

存储结构:如果字符串可以表示为整数,且范围在64位二进制以内,则存储为整数,否则使用sds存储。

sds是一个能够动态扩容的内存安全的数组结构,当字符串长度不超过512M时使用它来存储。

如果字符串长度小于44字节,使用embstr编码(压缩编码),将redis对象结构与SDS分配在连续的内存中,减少内存碎片。

否则采用raw编码(普通编码),将redis对象结构与SDS分开存储,因此需要更多的内存分配和释放操作。

注意 :redis的string是一个安全的二进制字符串。二进制指可以不存储为字符编码,安全是指保存了字符串的长度信息。

1.2.2 list 列表

存储结构:当节点总数小于等于512或者元素长度都不超过64字节时采用ziplist压缩列表。否则采用quicklist双向循环链表。

注意:保证插入有序。

1.2.3 hash 哈希表

存储结构:节点数量大于512(hash-max-ziplist-entries)或所有字符串长度大于64(hash-max-ziplist-value),则使用dict实现。

节点数量小于等于512且有一个字符串长度小于64,则使用ziplist实现。

注意:保存的元素为键值对,能够去重。

1.2.4 set 集合

存储结构:元素都为整数且元素数量小于等于512(set-max-intset-entries),则使用整数数组存储。否则使用dict。

注意:保存的元素为值,能够去重。

1.2.5 zset 有序集合

存储结构:节点数量大于128或者有一个字符串长度大于64,则使用跳表skiplist,否则使用压缩列表ziplist。

2. 基本命令及应用场景:

2.1 Redis应用场景

用于各种需要高效的临时存储和访问数据的场景。例如用作缓存中间件:缓存热点数据;用户标识信息等。

2.2 string------sds动态字符串

扩容策略:当长度小于1M时,加倍扩容;超过1M每次只扩容1M;字符串最大为512M。

存储内容:既可以存储字符串,也可以存储其它二进制数据,例如二进制协议数据protobuf等。

基本操作:

shell 复制代码
# 赋值与查询
SET key val
SETNX key val	# 如果不存在才赋值
GET key
# 增加
INCR key	# 累加1
INCRBY key increment
# 减少
DECR key
DECRBY key decrement
# 删除各种类型的kv对
DEL key
# 查看值得数据类型
TYPE key

应用

作为位图使用

shell 复制代码
# 将其作为二进制数据,位图
SETBIT key offset value
BITCOUNT key start end
GETBIT key offset

对象存储

shell 复制代码
SET key '{"name":["li", "lou", "la"], "age": [21, 33, 12]}'

累加器

shell 复制代码
incr num
incrby num 100

分布式锁

shell 复制代码
# 获取锁
SET lock_key uuid NX EX 10

释放锁:lua脚本,保证原子性

lua 复制代码
if redis.call("GET", lock_key) == uuid then
    -- 成功释放
    return redis.call("DEL", KEYS[1])
else return 0
end

2.3 list------双向循环链表

列表首尾操作时间复杂度为O(1),中间元素操作时间复杂度为O(n)。

基本操作

shell 复制代码
LPUSH key e1 e2 ... en # 插入左侧
LPOP key [count] # 弹出左侧
RPUSH key e1 e2 ... en # 掺入右侧
RPOP key [count]
# 查询
LRANGE key start end
# 删除
LREM key count element
# 阻塞弹出,如果列表为空就等待
BRPOP k1 k2 ... kn timout
# 裁剪数据,只保留特定范围的数据
ltrim key start end

应用

栈(先进后出)

shell 复制代码
LPUSH + LPOP
# 或者
RPUSH + RPOP

队列(先进先出)

shell 复制代码
LPUSH + RPOP
# 或者
RPUSH + LPOP

阻塞队列

shell 复制代码
LPUSH + BRPOP
# 或者
RPUSH + BLPOP

异步消息队列

shell 复制代码
# 同队列操作,只是在不同的系统之间

获取固定窗口的数据记录

shell 复制代码
# 获取最近50条记录
LTRIM key 0 49

2.4 hash------散列表

数据类型为散列表,保存多个键值对,可以方便修改某个字段的值。

基本命令

shell 复制代码
# 赋值与查询
hset key f1 v1 f2 v2 ... fn vn
hmset key f1 v1 f2 v2 ... fn vn
hgetall key
hget key field

# 递增
hincrby key field increment
# 查看键值对个数
hlen key
# 删除
hdel key field

应用

通常将hash与其它数据结构组合,完成业务功能

shell 复制代码

2.5 set------无序集合

基本命令

shell 复制代码
# 添加元素
SADD key m1 m2 ... mn
# 查看集合所有元素
SMEMBERS key
# 查询元素个数
SCARD key

# 查询集合中是否存在某个元素
SISMEMBER key member
# 从集合中随机返回一个或多个元素,但不删除
SRANDMEMBER key [count]
# 从集合中随机删除一个或多个元素
SPOP key [count]

# 做差集
SDIFF key [key ...]
# 做交集
SINTER key [key ...]
# 做并集
SUNION key [key ...]

应用

抽奖

shell 复制代码
srandmember key 10

共同关注的人

shell 复制代码
sinter key1 key2

推荐好友

shell 复制代码
sdiff john tom # 将john的好友推荐给tom

2.6 zset------有序集合

基础命令

shell 复制代码
# 插入元素
ZADD key [NX|XX] [CH] [INCR] s1 m1 s2 m2 ... sn mn
# 删除元素
ZREM key m1 m2 ... mn
ZREMRANGEBYSCORE key min max
# 返回score
ZSCORE key member
# 修改score
ZINCRBY key increment member
# 返回元素个数
ZCARD key
# 返回排名
ZRANK key member
# 返回排名范围的member,默认时从小到大排序
ZRANGE key start stop [WITHSCORES]
# 逆序返回
ZREVRANGE key start stop [WITHSOCRES]

应用

排行榜

shell 复制代码
ZINCRBY players 13 adam
# 返回分数最大前10位player
ZREVRANGE players 0 9 withscores

延时队列

使用zset保存消息,其score为到期时间,这样可以轮询zset将到期的消息取出处理。

python 复制代码
def delay(msg):
    msg.id = str(uuid.uuid4())
    value = json.dumps(msg)
    retry_ts = time.time() + 5
    redis.zadd("delay-queue", retry_ts, value)
    
def loop():
    while True:
        values = redis.zrangebyscore("delay-queue", 0, time.time(), start=0, num=1)
        if not values:
            time.sleep(1)
            continue
        value = values[0]
        success = redis.zrem("delay-queue", value)
        # 保证原子性
        if success:
            msg = json.loads(value)
            handle_msg(msg)

分布式定时器

生产者将定时任务利用hash分配到不同的redis中,每个redis有一个dispather进程,不断从中获取到期的定时任务并发布到不同的消费者中。

时间窗口限流

限定用户的某个行为在指定的可动态变化的时间范围内最多发生N次

lua 复制代码
local function is_action_allowed(res, userid, action, period, max_count)
    local key = tab_concat({"hist", userid, action}, ":")
    local now = zv.time()
    
    red:init_pipeline()
    -- 记录行为
    red:zadd(key, now, now)
    -- 移除时间窗口外的行为
    red:zremrangebyscore(key, 0, now - period * 100)
    -- 获取时间窗口内的行为数量
    red:zcard(key)
    -- 设置过期时间
    red:expire(key, period + 1)
    local res = red:commit_pipeline()
    return res[3] <= max_count
end

2. 如何设计kv

2.1 如何设计key

对于单个功能的单个key,使用有意义的名字

shell 复制代码
SET name lee

对于相同功能的多个key,使用有意义的字段并用冒号分隔。

shell 复制代码
SETBIT sign:lee:202410 12 1

学习参考

学习更多相关知识请参考零声 github。

相关推荐
时间静止不是简史37 分钟前
生产事故排查:Redis 宕机导致补偿队列消费线程死亡,通话录音未上送业务平台
java·redis
2301_32241428044 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
catoop7 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
Web极客码7 小时前
我用 Claude 分析 Redis 哨兵日志,实现跨机房数据不一致自动对齐
数据库·redis·php
库库的数据库笔记7 小时前
国产信创数据库的MySQL兼容性深度对比解析
大数据·数据库·mysql·oceanbase·政务
microrain7 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
姚远Oracle ACE8 小时前
为什么无法连接到 PostgreSQL?
数据库·postgresql
ss2738 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 22 PostgreSQL实例与集群
数据库·笔记·postgresql
ss2738 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 21 PostgreSQL进程与内存架构介绍
数据库·笔记·postgresql