了解内容:geoHash,scan,sentinel 哨兵,Redis的近似LRU算法

GeoHash 实现附近的人

  • GeoHash 算法将二维的经纬度数据映射成一维的整数,这样所有的元素都将挂载到一 条线上。这样实际距离相近的目标,它们的二维坐标映射到一维的点的距离也会很接近。当我们想要计算附近的人时,首先将目标位置映射到这条线上,然后在这个一维的线上获取附近的点就行了。
  • 大致的映射方法是将二维平面划分成一系列正方形的方格,所有地图坐标放置在唯一的一个方格中,每个正方形方格可以标记为 00,01,10,11 四个二进制整数,通过这种方式编码后每个地图元素就会变成一个整数了。它内部存储采用的是 zset 结构,通过 zset 的 score 排序就可以得到坐标附近的其他元素了。

Scan

  • 假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 以某个固定的已知的前缀开头,可以使用 scan 指令无阻塞的提取出指定模式的 key 列表,但是会有一定的重复率,需要在客户端去重。
  • 如果观察到 Redis 的内存大起大落,这有可能是大 key 导致的,因为 key 太大的话会导致数据迁移时出现卡顿,而且扩容时,会一次性申请更大的内存,导致卡顿。删除这个大 key 时,内存会一次性回收,卡顿现象会再次发生。解决方法是需要定位出具体哪个是大 key,进一步定位出具体的业务来源,然后修改相关业务代码的设计。可以采用 scan 指令进行扫描,type 指令获取 key 的类型,然后使用类型对应的 size 方法得到 key 的大小,将前几名作为扫描结果展现出来,这样就查到最大的几个 key 了。
  • 原理: Scan 采用的是高位进位加法来做的遍历,高位进位加法指的是从左边加,进位时往右边移动,比如 0110,通过高位进位加法加 1 后变成 1110 。而普通进位加法是 0110 变成 0111。这样做是为了防止重复遍历,比如数组长度由 16 位扩容到 32 位,那么 6 号槽位,也就是 0110 会被 rehash 到新数组的 0110 和 1110 位置,也就是 6 号和 14 号槽位,然后就从 0110 这个槽位还是往后遍历,下一个就是高位加 1 的 1110。

Sentinel 哨兵

  • Redis sentinel 哨兵集群通过心跳机制监控主从节点,每一个 sentinel 节点会定时对 Redis 集群中的所有节点发出心跳包,检测节点是否正常,如果某个节点在规定时间内没有回复 sentinel 节点,那么该 redis 节点就会被该 sentinel 节点主观下线。当 redis 节点被某个 sentinel 节点主观下线时,并不意味着该节点肯定故障了,还需要 sentinel 集群里的其他 sentinel 节点共同判断为主观下线才行,如果 Sentinel 集群中超过 quorum 数量的 Sentinel 节点认为该 Redis 节点主观下线,则该 Redis 客观下线,quorum 是用来识别故障的一个参数。
  • 当客户端来连接集群时,首先连接 sentinel,通过 sentinel 来查询主节点的地址,然后客户端根据查到的地址去连接主节点进行数据交互。
  • 当主节点发生故障时,客户端会重新向 sentinel 询问地址,sentinel 会将新的主节点地址告诉客户端,这样应用程序就不需要重启就可以自动完成节点切换了。
  • redis 默认端口为 6379,sentinel 默认端口为 26379。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lTIyfTvI-1586432025293)(C:\Users\123\AppData\Roaming\Typora\typora-user-images\image-20200114151042381.png)]

LRU 算法

  • 实现 LRU 算法需要 key-value 字典,以及一个链表。当字典的某个元素被访问时,它在链表中的位置就会被移动到表头。所以链表的元素排列顺序就是元素最近被访问的顺序。
  • 位于链表尾部的元素就是最近最少使用的元素,优先被踢掉;而位于链表头部的元素就是最近刚被使用过的元素,暂时不会被踢。

Redis 的近似 LRU 算法

  • redis 使用的是一种近似 LRU 算法,之所以不用传统的 LRU 算法是因为它引入的链表会占用较多的内存。
  • 近似 LRU 算法使用随机采样的方式来淘汰元素,它为每个 key 增加了一个最后一次被访问的时间戳,当内存超出 max memory 时,就会执行一次这个近似 LRU 淘汰算法,原理步骤是随机采样 5 个 key,根据时间戳淘汰掉最旧的那个 key,如果淘汰后内存还是超出 max memory,就继续随机采样来淘汰。采样的方式通过 max memory policy 来配置,如果配置的是 allkeys,就从所有的 key 中随机采样,如果配置的是 volatile,就从设有过期时间的 key 中随机采样,每次采样的 key 的个数通过 max memory samples 来配置,默认为 5,这个采样值越大,效果就越接近传统的 LRU 算法。
  • redis 3.0 在算法中增加了淘汰池,进一步提升了近似 LRU 算法的效果。具体原理是构建一个淘汰池的数组,大小为每次采样的个数,在每一次淘汰循环中,新随机采样的 key 会和淘汰池中的 key 进行融合,淘汰掉最旧的那个 key 后,保留剩余的 key 放入淘汰池中等待下一次循环。
发布了307 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dl674756321/article/details/105410981
今日推荐