# Redis实战

# 名词

  • ACID: atomicity原子性、consistency一致性、isolation隔离性、durability耐久性,一个数据库实现可靠的数据事务需满足的性质。

# 特点

  • 速度快: 使用内存存储的非关系型数据库。
  • 原子性: 当命令正在读取或修改数据的时候,其他客户端不能读取或修改相同的数据。

# 数据类型

结构类型 结构存储的值 场景
STRING 字符串、浮点数、整数
LIST 一个链表
SET 无序去重的集合
HASH 包含键值对的无序散列表
ZSET 根据分值大小排序且去重的有序映射 排行榜(分值越小,排行靠前)

# 指令

# SETRING 字符串

  • GET
  • SET
  • DEL
指令 描述
APPEND key value 将值追加到字符串尾部
GETRANGE key value 将值追加到字符串尾部

# LIST 列表

redis使用双链表表示列表

  • RPUSH
  • LPUSH
  • LRANGE
  • LINDEX 获取给定位置的元素

# SET 集合

redis通过配置可设置集合使用整数集合表示的限制条件,超出限制则使用散列表表示。

指令 描述
SADD key item1 [item2 ...] 增加一个或多个元素
SMEMBERS key 返回集合包含的所有元素
SISMEMBER key item 是否在集合中
SREM key item 移除元素
SCARD key 返回集合包含元素数量
SRANDMEMBER key [count] 随机返回count个元素,整数不重复,负数会重复
SPOP key 随机移除一个元素
SMOVE source-key dest-key item 将item从source-key集合中移除,并移入dest-key的集合下
SDIFF key1 [key2 ...] 返回存在于key1,不存在于其他集合的元素(差集)
SDIFFSTORE dest-key key1 [key2 ...] 将存在于key1,不存在于其他集合的元素,存储到dest-key去(差集)
SINTER key1 [key2 ...] 返回同时存在于所有集合的元素(交集)
SINTERSTORE dest-key key1 [key2 ...] 返回同时存在于所有集合的元素,存储到dest-key去(交集)
SUNION key1 [key2 ...] 返回那些至少存在于一个集合中的元素(并集)
SUNIONSTORE dest-key key1 [key2 ...] 返回那些至少存在于一个集合中的元素,存储到dest-key去(并集)

# HASH 散列

redis使用散列表表示散列

指令 描述
HSET key field1 value1 [field2 value2] 为散列里面的一个或多个键设置值
HGET key field 从散列里获取键的值
HMGET key field1 [field2] 从散列里获取键的值
HDEL key field1 [field2] 移除散列一个或多个键值对
HLEN key 获取散列键值对数量
HEXISTS key filed 检查给定键是否存在于散列中
HKEYS key 获取散列包含的所有键
HVALS key 获取散列包含的所有值
HGETALL key 获取散列所有键值
HINCRBY key field increment 给散列指定键的值加上整数increment
HINCRBYFLOAT key filed increment 给散列指定键的值加上浮点数increment

# ZSET 有序集合

redis通过散列表加上跳跃表表示有序集合

指令 描述
ZADD key score member [score2 member2 ...] 将带有一定分值的成员添加到有序集合
ZREM key member1 [member2 ...] 移除成员
ZCARD key 返回有序集合成员数量
ZINCRBY key increment member 将member成员的分值加上increment
ZCOUNT key min max 返回分值介于min和max之间的成员数量
ZSCORE key member 返回成员member的分值
ZRANK key member 分值升序排序,返回成员member在有序集合之中的排名
ZRANGE key start stop [WITHSCORES] 分值升序排序,返回排名介于start和stop之间的成员,如果给了WITHSCORES参数,则将成员分值一并返回
ZREVRANK key member 分值升序排序,返回成员member在有序集合之中的排名
ZREVRANGE key start stop [WITHSCORES] 分值降序排序,返回排名介于start和stop之间的成员,如果给了WITHSCORES参数,则将成员分值一并返回
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 分值升序排序,返回分值介于min和max之间的成员,如果给了WITHSCORES参数,则将成员分值一并返回
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] 分值降序排序,返回分值介于max和min之间的成员,如果给了WITHSCORES参数,则将成员分值一并返回
ZREMRANGEBYSRANK key start stop 分值升序排序,移除排名介于start和stop之间的成员
ZREMRANGEBYSCORE key min max 分值升序排序,移除排名介于min和max之间的成员
ZINTERSTORE dest-key key-count key1 [key2 ...] [WEIGHTS weight1 [weight2]] [AGGREGATE SUM|MIN|MAX] 有序集合交集运算
ZUNIONSTORE dest-key key-count key1 [key2 ...] [WEIGHTS weight1 [weight2]] [AGGREGATE SUM|MIN|MAX] 有序集合并集运算

# 其他命令

指令 描述
SORT key [BY pattern] [LIMIT offset count] [GET pattern] [ASC|DESC] [ALPHA] destination 排序
# 发布与订阅
指令 描述
SUBSCRIBE channel [channel] 订阅给定一个或多个频道
UNSUBSCRIBE [channel... [channel2 ...]] 退订给定一个或多个频道,没有给定则退订所有频道
PUBLISH channel message 向给定频道发送消息
PSUBSCRIBE pattern1 [pattern2 ...] 订阅与给定模式匹配的所有频道
PUNSUBSCRIBE pattern1 [pattern2 ...] 退订给定模式匹配的所有坡;频道,没有给定则退订所有频道
# 事务
指令 描述
MULTI 事务开始
EXEC 执行事务开始后的多个指令
# 过期
指令 描述
PERSIST key 移除键的过期时间(s)
TTL key 查看键距离过期剩余时间(s)
EXPIRE key seconds 给定键在指定秒数后过期
EXPIREAT key timestamp 给定键在给定UNIX时间戳(s)后过期
PTTL key 查看键距离过期剩余时间(ms)
PEXPIRE key milliseconds 给定键在指定毫秒数后过期
PEXPIREAT key timestamp-milliseconds 给定键在给定UNIX时间戳(ms)后过期

# 数据持久化

# 方法

  • 快照: 把某一时刻所有数据写入硬盘
  • AOF: append-only file,在执行命令时,将被执行的命令写入硬盘

# 指令

指令 描述
BGSAVE 创建一个快照。通过fork一个子进程,负责将快照写入硬盘,而父进程继续处理命令。缺点: 速度慢,内存占用大
SAVE 创建一个快照。在快照创建完毕前不再响应任何其他指令 。缺点:无法正常执行其他指令
SHUTDOWN 执行SAVE后关闭服务器
BGREWRITEAOF 移除AOF文件中冗余命令来重写AOF文件,从而减小AOF文件体积,工作原理同BGSAVE
INFO 查看服务器当前状态有关信息,如内存占用量、客户端连接数、上次快照后执行的命令数量等,其中aof_pending_bio_fsync为0时,表示服务器将所有数据已持久化到硬盘了

# 实践

# 分布式锁

用于解决能够被不同客户端多个进程访问的共享内存数据结构。在数据进行加锁时,程序需通过获取锁来对数据进行排他性访问的能力,才能对数据进行操作,最后还要将锁释放给其他程序。

  • 公平锁:按照申请锁的顺序提供锁
  • 非公平锁: 不按申请锁的顺序提供锁
  • 独享锁:仅允许被一个线程所持有
  • 共享锁:允许多个线程持有
  • 乐观锁:常用于读场景,先操作后拿锁,不等待锁释放
  • 悲观锁:常用于写场景,先拿锁后操作,等待锁释放后拿锁执行,行锁表锁都是用这个
  • 粗粒度锁:通过一个锁,把执行的代码块都锁定
  • 细粒度锁:和粗粒度锁相对
  • 带超时限制特性的锁

# 信号量

  • 计数信号量: 限定能够同时使用的资源数量。通过时间戳作为有序集合的分值的方式,统计获得锁的用户,移除超时限的用户,剩下拿到锁的用户。缺点是多个客户端时,时间较慢的客户端会偷走时间较快的客户端的信号量。
  • 公平信号量: 通过自增的计数器作为有序集合的分值的方式

# 细粒度锁

在拥有多个操作分区情况下,如果只有单一一个锁,会阻塞多个请求。为了支持更高并发,减少阻塞,需细化锁的设计

分级锁的设计:

  • Top锁
  • Child锁

使用规则: 在操作开始前,必须先申请得到Top锁来准备获取Child锁,在获取得到Child锁之后,可以再释放Top锁。这里的Child锁,可以理解为就是每个分区锁。这里Top锁的目的是为了保证获取各个分区锁的原子性。

# 任务队列

通过有序集合,分值为任务执行时间,定时轮询队列,按分值升序排序,小于当前时间的立即执行。

# 性能优化

# 事务

一次向Redis发送多条指令

# 压缩列表

  • 让键名保持简短
  • 使用短结构
Last Updated: 11/29/2024, 1:40:42 PM