redis分布式锁

  1. 分布式锁本质上要实现的目标就是在 Redis 里面占一个“坑”,当别的进程也要来占时,发现已经有人在那里了,就只好放弃或者稍后再试。占坑一般是使用 setnx(set if not exists) 指令,只允许被一个客户端占坑。先来先占, 用完了,再调用 del 指令释放茅坑。占坑一般是使用 setnx(set if not exists) 指令,只允许被一个客户端占坑。先来先占, 用完了,再调用 del 指令释放茅坑。
  1. setnx lockcodehole true
  2. del lockcodehole

但是有个问题,如果逻辑执行到中间出现异常了,可能会导致 del 指令没有被调用,这样就会陷入死锁,锁永远得不到释放。
于是我们在拿到锁之后,再给锁加上一个过期时间,比如 5s,这样即使中间出现异常也可以保证 5 秒之后锁会自动释放。

  1. set lock:codehole true ex 5 nx
  1. 超时问题
    Redis 的分布式锁不能解决超时问题,如果在加锁和释放锁之间的逻辑执行的太长,以至于超出了锁的超时限制,就会出现问题。因为这时候第一个线程持有的锁过期了,临界区的逻辑还没有执行完,这个时候第二个线程就提前重新持有了这把锁,导致临界区代码不能得到严格的串行执行。
  2. 延时队列
    redis 的 list 数据结构可以用来做异步消息队列,使用rpush/lpush操作入队列,使用lpop 和 rpop来出队列。
    客户端是通过队列的 pop 操作来获取消息,然后进行处理,处理完了再获取消息,再进行处理。列队为空了会陷入 pop 死循环,sleep 可以解决(如果有多个消费者,这个延迟时间就会下降),更好的解决方案。blpop/brpop ,阻塞读在列队没有数据的时候,会立刻进入休眠状态,一旦数据来了,就会立刻醒过来。用blpop/brpop替代前面的lpop/rpop
  3. 空闲连接自动断开
    线程一直阻塞在哪里,Redis 的客户端连接就成了闲置连接,闲置过久,服务器一般会主动断开连接,减少闲置资源占用。这个时候blpop/brpop会抛出异常来。

所以编写客户端消费者的时候要小心,注意捕获异常,还要重试。

  1. 位图
    就是普通的字符串,也就是 byte 数组。
    Redis 的位数组是自动扩展,如果设置了某个偏移位置超出了现有的内容范围,就会自动将位数组进行零扩充。
  2. 简单限流
    zset 数据结构的 score 值,可以通过 score 来圈出这个时间窗口来。而且我们只需要保留这个时间窗口,窗口之外的数据都可以砍掉。zset 的 value 保证唯一性就行,可以存为时间戳
    同时如果用户是冷用户, zset 就可以从内存中移除,不再占用空间。
    它的整体思路就是:每一个行为到来时,都维护一次时间窗口。将时间窗口外的记录全部清理掉,只保留窗口内的记录。zset 集合中只有 score 值非常重要,value 值没有特别的意义,只需要保证它是唯一的就可以了。

redis位图

Redis 的位数组是自动扩展,如果设置了某个偏移位置超出了现有的内容范围,就会自动将位数组进行零扩充。
位数组的顺序和字符的位顺序是相反的。

CAP 原理

  • C - Consistent ,一致性
  • A - Availability ,可用性
  • P - Partition tolerance ,分区容忍性
    • 分布式系统的节点往往都是分布在不同的机器上进行网络隔离开的,这意味着必然会有网络断开的风险,这个网络断开的场景的专业词汇叫着「网络分区」
    • 在网络分区发生时,两个分布式节点之间无法进行通信,我们对一个节点进行的修改操作将无法同步到另外一个节点,所以数据的「一致性」将无法满足,因为两个分布式节点的数据不再保持一致。
      除非我们牺牲「可用性」,也就是暂停分布式节点服务,在网络分区发生时,不再提供修改数据的功能,直到网络状况完全恢复正常再继续对外提供服务。
  • 一句话概括 CAP 原理就是——网络分区发生时,一致性和可用性两难全。
  • 最终一致
    • Redis 的主从数据是异步同步的,所以分布式的 Redis 系统并不满足「一致性」要求。当客户端在 Redis 的主节点修改了数据后,立即返回,即使在主从网络断开的情况下,主节点依旧可以正常对外提供修改服务,所以 Redis 满足「可用性」。
    • Redis 保证「最终一致性」,从节点会努力追赶主节点,最终从节点的状态会和主节点的状态将保持一致。如果网络断开了,主从节点的数据将会出现大量不一致,一旦网络恢复,从节点会采用多种策略努力追赶上落后的数据,继续尽力保持和主节点一致。

跳跃表

跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。