• golang工程中间件——redis常用结构及应用(set,zset)


    Redis

    命令中心

    这些篇文章专门以应用为主,原理性的后续博主复习到的时候再详细阐述

    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 ...]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    应用

    抽奖
    # 添加抽奖用户
    sadd Award:1 10001 10002 10003 10004 10005 10006
    sadd Award:1 10009
    # 查看所有抽奖用户
    smembers Award:1
    # 抽取多名幸运用户
    srandmember Award:1 10
    # 如果抽取一等奖1名,二等奖2名,三等奖3名,该如何操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    共同关注
    sadd follow:A person1 person2 person3 person4 person5
    sadd follow:C person3 person4
    # 交集
    sinter follow:A follow:C
    
    • 1
    • 2
    • 3
    • 4
    推荐好友
    sadd follow:A person1 person2 person3 person4 person5
    sadd follow:C person3 person4
    # C可能认识的人:
    sdiff follow:A follow:C
    
    • 1
    • 2
    • 3
    • 4

    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中,分数在min和max之间的所有元素(且包含min和max); limit 指定从第几个开始返回多少个元素
    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    有序集合比较规则,先通过比较 score 来确定排序,如果 score 相同则比较 member; member 比较规则是按照字母顺序来进行比较;

    存储结构

    节点数量少且字符串长度小时使用压缩列表存储;否则使用跳表来进行存储;

    应用

    热榜
    # 点击新闻:
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    延时队列

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

    在这里插入图片描述

    # delay thread
    zadd delay:1 now+5 task1
    zadd delay:1 now+10 task2
    # check thread
    # for {
    # vals :=
    zrangebyscore delay:1 0 now limit 0 1
    # val := vals[0]
    zrem delay:1 val
    # handle(val)
    # }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    分布式定时器

    在这里插入图片描述

    生产者将定时任务 hash 到不同的 redis 实体中,为每一个 redis 实体分配一个 dispatcher 进 程,用来定时获取 redis 中超时事件并发布到不同的消费者中

    时间窗口限流

    限流是窗口移动,在一个窗口内限流比如六秒窗口:1s-7s, 2-8s, 3s-9s

    熔断则是分成一个个时间区间,区间内不能超过多少次请求:1s-6s, 7s-12s

    # 指定用户 user_id 的某个行为 action 在特定时间内 period 只允许发生操作次数
    max_count
    # key limit:10001:action1
    # now 时间单位为 毫秒
    zadd limit:10001:action1 now now
    # 删除score 在0~now-period*1000 内的元素,保留最近period*1000 内的元素
    zremrangebyscore limit:10001:action1 0 now - period*1000
    # count =
    zcard limit:10001:action1
    expire limit:10001:action1 60+1
    # 比较 count 与 max_count
    # 如果 count > max_count 说明超过次数;否则没有超过限定次数
    # 第二种实现
    # 比较 string + expire
    # val =
    incr limit:10001:action1
    # val =
    incr limit:10001:action1
    expire limit:10001:action1 60+1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    不解压的情况下从各种压缩包中直接读取文本行内容
    【算法与数据结构】--前言
    MySQL - 为什么索引结构默认使用B+树,而不是其他?
    [pwn基础]Linux安全机制
    CDB与OA-以T为例子进行分析
    【Java开发】 Spring 07 :Spring AOP 实践详解(通过 AOP 打印数据访问层)
    C++ 性能优化指南 KurtGuntheroth 第7章 优化热点语句 摘录
    【泛函分析】距离空间和赋范空间
    QDebug 日志输出的浏览器
    发布DDD脚手架到Maven仓库,IntelliJ IDEA 配置一下即可使用
  • 原文地址:https://blog.csdn.net/qq_43058348/article/details/134304480