Redis 实战 —— 08. 实现自动补全、分布式锁和计数信号量

自动补全 P109

自动补全在日常业务中随处可见,应该算一种最常见最通用的功能。实际业务场景肯定要包括包含子串的情况,其实这在一定程度上转换成了搜索功能,即包含某个子串的串,且优先展示前缀匹配的串。如果仅包含前缀,那么可以使用 Trie 树,但在包含其他的情况下,使用数据库/ ES 本身自带查询就足够了。可以按照四种情况(精确匹配、前缀、后缀、包含(也可将后两种融合成包含)),分别查询结果,直至达到数据条数上限或者全部查询完毕。但这种使用方法有缺点:查询次数多、难以分页。不过实际场景中需要补全的情况都只要第一页的数据即可。

自动补全最近联系人 P110

需求: 记录最近联系过的 100 个人名,并支持对输入的串进行自动补全。 P110

数据量很小,所以可以在 Redis 中用列表维护最近联系人,然后在内存中进行过滤可自动补全的串。

步骤: P111

  1. 维护长度为 100 的最近联系人列表
    1. 如果指定的联系人已在列表中,则从列表中移除 (LREM)
    2. 将指定的联系人添加到列表最前面 (LPUSH)
    3. 如果添加完成后,列表长度超过 100 ,则对列表进行修剪,仅保留列表 前面的 100 个联系人 (LTRIM)
  2. 获取整个最近联系人列表,在内存中根据四种情况进行过滤即可
通讯录自动补全 P112

需求: 有很多通讯录,每个通讯录中有几千个人(仅包含小写英文字母),尽量减少 Redis 传输给客户端的数据量,实现前缀自动补全。 P112

思路: 使用有序集合存储人名,利用有序集合的特性:当成员的分值相同时,将根据成员字符串的二进制顺序进行排序。如果要查找 abc 前缀的字符串,那么实际上就是查找介于 abbz... 之后和 abd 之前的字符串。所以问题转化为:如何找到第一个排在 abc 之前的元素的排名 和 第一个排在 abd 之前的元素的排名。我们可以构造两个不在有序集合中的字符串 (abb{ , abc{ ) 辅助定位,因为 { 是排在 z 后第一个不适用的字符,这样可以保证这两个字符串不存在与有序集合中,且满足转化后的问题的限制。 P113

综上: 通过将给定前缀的最后一个字符替换为第一个排在该字符前的字符,再再在末尾拼接上左花括号,可以得到前缀的前驱 (predecessor) ,通过给前缀的末尾拼接上左花括号,可以得到前缀的后继 (successor) 。

  • 字符集:当处理的字符不仅仅限于 a~z 范围,那么要处理好以下三个问题: P113
    • 将所有字符转换为字节:使用 UTF-8UTF-16 或者 UTF-32 字符编码(注意: UTF-16UTF-32只有大端版本可用于上述方法)
    • 找出需要支持的字符范围,确保所选范围的前面和后面至少留有一个字符
    • 使用位于范围前后的字符分别代替反引号 ` 和左花括号 {

步骤: P114

  1. 运用思路中的方法找到前缀的前驱和后继(为了防止同时查询相同的前缀出现错误,可以在前驱和后继之后添加上 UUID
  2. 将前驱和后继插入到有序集合里
  3. 查看前驱和后继的排名
  4. 取出他们之间的元素
  5. 从有序集合中删除前驱和后继

通过向有序集合添加元素来创建查找范围,并在取得范围内的元素之后移除之前添加的元素,这种技术还可以应用在任何已排序索引 (sorted index) 上,并且能通过改善(第七章介绍)应用于几种不同类型

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值