Redis

常用场景

场景 应用场景
缓存 数据缓存、会话管理、页面缓存等
计数器 访问次数、在线人数、PV、UV等
消息队列 异步任务、实时消息推送、事件通知等
分布式锁 分布式事务、资源协调、防止重复提交等
地理位置 LBS、社交应用、出行服务等
全文检索 搜索引擎、文本分析、关键字提取等

基本数据结构

数据结构 特点 适用场景
String(字符串) 最基本的数据类型,是二进制安全的,可以存储任何类型的数据 缓存、计数器、限流、分布式锁等
List(列表) 可以存储有序的字符串列表,支持从两端进行元素的插入和弹出操作 消息队列、任务队列、排行榜、时间轴等
Set(集合) 可以存储多个唯一的字符串,支持集合运算,如并集、交集、差集等 标签系统、好友关系、投票系统、推荐系统等
Hash(哈希表) 可以存储多个键值对,支持单个键值的添加、删除和获取操作 对象存储、商品属性、用户信息、配置信息等
Zset(有序集合) 可以存储多个成员,每个成员都有一个分数,支持按分数排序和范围查找 排行榜、计分板、游戏排名等

部署方式

部署方式 描述 适用场景
单机模式 Redis 运行在单台服务器上,不进行数据分片,只使用一份配置文件。 适用于开发、测试等小规模环境。
主从复制模式 将 Redis 实例分为主节点和从节点,主节点负责写入数据,从节点负责读取数据。当主节点发生故障时,从节点可以自动切换为主节点。 适用于对数据一致性要求较高的应用场景,如电商、金融等。
Sentinel 模式 Sentinel 是 Redis 的高可用性解决方案,通过多个 Sentinel 进程对 Redis 主从节点进行监控,当主节点失效时自动将从节点切换为主节点。 适用于对高可用性和数据一致性要求较高的应用场景,如金融、医疗等。
集群模式 Redis Cluster 可以将数据分散到多个节点上进行存储和管理,支持自动数据分片和负载均衡。 适用于对扩展性要求较高的应用场景,如互联网应用、物联网等。

配置要求

部署方式 机器内存 机器CPU 磁盘 并发 响应指标
单机模式 1GB-4GB 单核或双核 10GB-100GB 10K-100K QPS 响应时间一般在毫秒级别
主从复制模式 4GB-32GB 四核或八核 100GB-1TB 10K-100K QPS 主节点写入时响应时间一般在毫秒级别,从节点读取时响应时间较快
Sentinel 模式 8GB-64GB 四核或八核 100GB-1TB 10K-100K QPS 响应时间一般在毫秒级别,当主节点失效时,切换时间一般在秒级别
集群模式 32GB-512GB 多核 多个硬盘 100K-1M QPS 响应时间一般在毫秒级别

实现一个分布式锁

Redis 可以通过 SETNX(set if not exists)命令实现分布式锁。具体实现步骤如下:

  1. 定义一个键(key)表示锁的名字,例如 lock:my_lock。
  2. 在获取锁之前,需要设置一个过期时间(expire_time),避免因为某个客户端崩溃或者网络异常导致锁一直被占用。可以通过 SETNX 命令设置键值,如果返回值为 1,表示设置成功,获得锁;如果返回值为 0,表示该锁已经被占用,获取锁失败。
  3. 如果成功获取到锁,需要在执行完任务后及时释放锁,可以通过 DEL 命令删除键值释放锁。

下面是一个简单的示例代码:

def get_lock(conn, lock_name, expire_time=10):
    # 尝试获取锁
    is_locked = conn.setnx(lock_name, 'locked')
    if is_locked:
        # 设置锁的过期时间
        conn.expire(lock_name, expire_time)
        return True
    else:
        return False

def release_lock(conn, lock_name):
    # 释放锁
    conn.delete(lock_name)

在使用分布式锁的时候,需要考虑到网络延迟、锁的粒度等问题。同时,为了避免死锁的发生,需要设置合理的过期时间,并在释放锁的时候检查是否是自己持有的锁。

Redis Key 的过期机制

过期机制 描述 适用场景 优点 缺点
定时过期 当设置了键的过期时间时,Redis会自动在键的过期时间到达时将其删除 需要自动清理过期数据的场景,例如缓存 实现简单,易于理解和维护;能够确保过期键及时被删除 在键过期时会阻塞主线程,可能会影响性能;无法处理键在过期之前就被更新或删除的情况
惰性过期 当键过期后,只有在被访问时才会被删除 需要缓存的数据量非常大的场景,避免一次性删除大量数据影响性能 减少了过期键对性能的影响,能够优化内存的使用;可以处理键在过期之前被更新或删除的情况 无法保证过期键及时被删除;可能会出现一些过期键没有被及时删除的情况
定期过期 Redis会定期扫描过期键并删除它们,确保不会出现太多过期键没有被删除的情况 需要删除过期键,但又不能承受一次性删除过多数据的场景 能够保证过期键的及时删除,对性能的影响相对较小;可以处理键在过期之前被更新或删除的情况 无法保证过期键及时被删除,可能会出现一些过期键没有被及时删除的情况;定期过期的时间间隔需要根据实际情况进行调整

Redis key 的淘汰策略

淘汰策略 描述 适用场景 优点 缺点
LRU(Least Recently Used) 淘汰最近最少使用的键 适用于读多写少的场景,例如缓存 能够确保经常使用的键不会被淘汰;实现简单,性能高 在写入时会影响性能;不适用于访问模式不规律的场景
LFU(Least Frequently Used) 淘汰访问频率最少的键 适用于访问频率较为稳定的场景,例如热点数据 能够确保访问频率高的键不会被淘汰;能够适应访问模式的变化 需要额外记录键的访问次数,增加了内存开销;不适用于访问模式频繁变化的场景
Random 随机选择一个键进行淘汰 适用于所有场景 实现简单,无需记录键的访问次数 无法确保经常使用的键不会被淘汰;淘汰效率低下
TTL 淘汰剩余时间最短的键 适用于具有时效性的数据,例如会话数据 能够确保过期时间较短的键不会占用过多内存空间 只适用于具有时效性的数据;无法处理访问频率高的键

stop the world 问题

Redis是一个单线程的内存数据库,这意味着它使用一个主线程来处理所有客户端请求。Redis设计为使用非阻塞I/O,因此在执行一些操作时不会阻塞主线程。这样可以避免大多数"stop the world"问题。

然而,Redis在执行一些操作时也可能出现阻塞主线程的情况。例如,当执行某些命令,如BGSAVE、BGREWRITEAOF、FLUSHALL和FLUSHDB时,Redis会执行一个持久化操作,这时需要将内存中的数据写入磁盘。在这些操作期间,Redis主线程将被阻塞,直到操作完成。如果Redis数据库非常大,这个过程可能需要一段时间,从而导致长时间的停顿。

此外,当Redis主线程执行大量计算时,也可能会出现阻塞主线程的情况。例如,当执行复杂的Lua脚本或执行大型集合运算时,Redis主线程可能会被占用,导致客户端请求无法及时得到响应。

因此,虽然Redis在大多数情况下不会出现"stop the world"问题,但在某些情况下仍然可能出现。为了避免这种情况,需要对Redis的使用进行仔细规划和优化,以确保操作能够在可接受的时间内完成。

竞品分析

竞品名称 差异 优点 缺点 适用场景
Memcached - 不支持持久化
- 不支持数据结构
- 支持分布式锁
- 简单易用
- 高性能
- 高并发
- 内存使用效率高
- 仅支持缓存场景
- 不支持持久化
- 不支持复杂的数据结构
适用于高并发、读写比例高、数据量大的缓存场景
RocksDB - 存储介质不限于内存
- 可以保存磁盘上的数据
- 支持事务
- 支持多种数据结构
- 高性能
- 可扩展性强
- 不支持分布式 适用于需要对大量数据进行持久化存储的场景
LevelDB - 存储介质不限于内存
- 可以保存磁盘上的数据
- 高性能
- 支持事务
- 轻量级
- 不支持复杂的数据结构
- 不支持分布式
适用于需要对大量数据进行持久化存储的场景
Cassandra - 支持分布式
- 可以水平扩展
- 支持多数据中心部署
- 高可用性
- 高可靠性
- 高扩展性
- 复杂性高
- 部署和维护成本高
适用于需要存储海量数据且需要高可用性、高可靠性的场景
MongoDB - 支持复杂数据结构
- 支持事务
- 高可用性
- 高灵活性
- 支持分布式部署
- 性能较差
- 不支持 ACID 特性
适用于需要存储复杂数据结构、需要高可用性、高灵活性的场景

powered by ChatGPT

results matching ""

    No results matching ""