Book(7) Redis深度历险 核心原理与应用实战

279 阅读5分钟
Redis可以做什么
  • 记录帖子的点赞数、评论数和点击数(hash)
  • 记录用户的帖子ID列表(排序),便于快速显示用于的帖子列表(zset)
  • 记录帖子的标题、摘要、作者和封面信息,用于列表也展示(hash)
  • 记录帖子的点赞用户ID列表,评论ID列表,用户显示和去重计数(zset)
  • 缓存近期热帖内容(帖子内容的空间占用比较大),减少数据库压力(hash)
  • 记录帖子相关的文章ID,根据内容推荐相关帖子(list)
  • 如果帖子的ID是正数自增的,可以使用Redis来分配帖子ID(计数器)
  • 收藏集和帖子之间的关系(zset)
  • 记录热榜帖子ID列表、总热榜和分类热榜(zset)
  • 缓存用户历史行为,过滤恶意行为(zset、hash)
5种基础的数据结构
  • string
  • list 相当于Java语言里的LinkedList
  • hash
  • set 集合
  • zset 有序列表
分布式锁
  • 一般使用setnx 命令,只允许一个客户端占据锁,客户端使用完后,可以使用del指令释放锁。
  • 发生异常的时候,占据锁的客户端由于异常而导致del指令没有执行,就会陷入死锁,锁永远得不到释放。这时候可以添加一个过期时间expire,规定时间内如果还有释放锁,就会在到期时自动释放。
  • 超时问题 如果在加锁和释放锁之间,程序还没有执行完,锁就被释放了。被其他客户端占有,会导致临界区代码不能严格串行执行。为了解决这个问题。可以在锁的key后面添加一个随机字符串。
延时队列
  • 可以使用Redis的list数据结构来作为一部消息队列的使用,使用rpush和lpush操作入列,用lpop和rpop操作出列。
  • 如果对了空了怎么办? 如果队列空了,客户端就会不断的实行pop进入死循环,这时候可以使用sleep,让线程睡一会儿。
  • 阻塞读 用上面的方法可以解决空队列的问题。但是又有一个小问题,就是睡眠会导致消息的延时,可能在睡眠的时候,消息队列中就有了新的消息。这时候,依然要等待睡眠结束,才能处理消息。这样就导致延时。 可以使用blpop和brpop指令,也就是阻塞读,阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。消息的延迟几乎为0.
  • 空闲时自动断开 阻塞读的问题在于,如果长时间没有消息,就一直保持连接,占用系统资源,服务器一般会主动断开连接,减少系统资源的占用。
  • 延时队列的实现 可以通过redis的zset(有序列表)来实现。将消息序列化成一个字符串作为zset的value,这个消息的到期处理时间作为score,然后用多个线程轮训zset获取到期的任务进行处理。
位图

在开发过程中,有一些bool型的数据需要存取,比如用户一年的签到情况,签到了是1,没签到是0.如果使用普通的k-v,每个用户需要记录365个。当用户上亿的时候,需要的存储空间是惊人的。 为了解决这个问题,redis提供了位图数据结构,这样每天的签到记录只需要占据1位,365天就是365个位,46个字节,大大节省了存储空间

  • 统计和查找 使用bitcount来统计指数位置范围内内1的个数,bitpos来查找范围内出现的第一个0 或者第一个1
  • 魔术指令bitfield setbit和getbit指定位的值都是单个的,如果要一次操作多个位,就必须要使用管道来处理。 不过在redis 3.2版本以后就新增了bitfield指令,一次性可以进行多个位操作,它有3个子指令,get、set、incrby。
HyperLogLog

如果要统计某个网页每天的uv统计数据,可以通过HyperLogLog来实现,它提供了不精确的去重计数方案,误差范围是0.81%,但是已经可以满足UV统计需求了。 有pfadd和pfcounnt、pfmerge指令。

布隆过滤器

HyperLogLog可以用来统计和估数,但是并不能知道一个数据是否已经在HyperLogLog里面了。 这时候可以使用布隆过滤器 它有bf.add 和 bf.exists两个指令。

简单限流

限流需要存在一个滑动时间窗口,可以通过zset数据结构来实现。

GeoHash

Redis 3.2之后添加了地理位置Geo模块,意味着Redis可以实现搜索附近地理位置的功能。

scan

在redis的维护工作中,需要从成千上万个key中找出特定前缀的key列表来手动处理数据。可以通过scan操作。

线程IO模型

Redis是单线程的,但是不影响效率,因为在内存中,所以效率特别高。 它采用select系列的事件轮训API,采用了非阻塞的IO。

持久化

有两种持久化机制

  • 快照 一次全量的备份。 采用COW机制来实现,产生一个子进程来完成快照持久化。
  • AOF日志 是连续的增量备份,重启时需要加载所有的指令重放,效率比较低。
事务

从multi开始,可以输入存储若干命令,exec触发执行。