Redis应用场景及常见问题

470 阅读2分钟

Redis是什么

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

使用目的

  1. 提高性能,加快系统响应时间
  2. 提高系统并发能力

常见使用场景

  • 高速缓存和数据存储介质

  • 生成订单号(发号器)

    1.INCRBY命令 订单号生成规则:订单业务前缀+商家id+自增序号

  • 限流(lua+redis+配置中心实现动态限流)

    local key = "limit_key:" .. KEYS[1]  ## 限流key
    local limit = tonumber(ARGV[1])      ## 单元时间内并发次数
    local expire_time = ARGV[2]          ## 过期时间
    
    local result = redis.call("EXISTS", key)
    if result == 1 then
        if redis.call("INCR", key) > limit then
            return 0
        else
            return 1
        end
    else
        redis.call("SET", key, 1)
        redis.call("EXPIRE", key, expire_time)
        return 1
    end
    
  • 分布式锁 (目前业界比较好的开源方案RedLock)

    1. 加锁过程 SET lock_name value NX PX 3000

      • lock_name:即锁名称,需具备唯一性
      • value: 用于唯一标识锁的持有者
      • NX 表示只有当 lock_name(key) 不存在的时候才能 SET 成功,从而保证只有一个客户端能获得锁,而其它客户端在锁被释放之前都无法获得锁
      • PX 30000 自动过期时间3S
    2. 解锁过程 if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end

      • 先查询(get)锁对应的 value,与自己加锁时设置的 value 进行对比,如果相同,则可确认这把锁是自己加的,然后再发起解锁(del),避免误删。
  • MQ消费端幂等(分布式锁的一种)

    ​ MQ消息体需带唯一的bizId,每次消费前,先去Redis获取该Key是否存在,存在即为重复消费,不存在,执行正常业务,并将bizId作为key放入redis,设置相应的过期时间

  • 消息队列(有兴趣自行去了解)

常见问题

  • 缓存穿透
    1. 缓存空值,设置短暂过期时间
    2. 布隆过滤器
  • 缓存雪崩
    1. 分散设置过期时间,避免集体过期
    2. 加锁访问数据库
  • hotKey
    1. 本地缓存方案
    2. 利用分片算法的特性,对key进行打散到每个集群节点
  • bigKey
    1. 对big key存储的数据进行拆分,拆分成多个key分开存储。例:ItemDTO对象 可以拆分商品基础数据和商品详情(图文详情等)单独的key存储