zoukankan      html  css  js  c++  java
  • 怎样设计一个轻量的用户autocomplete系统

    http://antirez.com/post/autocomplete-with-redis.html

    怎样设计一个轻量的用户autocomplete系统


    我最近在设计一个系统时需要有一个用户下拉选择的功能,设计成输入首字母自动联想的autocomplete模式。现在在设计后端数据结构上遇到了些麻烦。目前是我直接用mysql的LIKE来做的这一功能,但如果随着用户和访问量的增长,这样肯定很慢。

    我使用的是redis缓存,用redis的朋友都应该读过那篇用redis实现autocomplete的文章。不过我要说的是,这篇文章并不解决我的问题。因为它只能完成关键词的联想功能,但它的关键词是无状态的,没有任何索引标记它的id。也就是说它除了能完成自动联想以外,无法完成关键词与用户的关联过程。

    另一个缺点是,这玩意索引的代价太高了,要对每个字都做分词,然后存入cache中做索引。而用户名是可以修改的,我觉得每次修改再重建索引的成本太大。

    我想了另一个方案,利用redis的交集功能来做搜索,这也是比较流行的方法。比如一个用户名叫Hello,用php代码来展示如何处理这个用户名,为了展示方便,我只处理英文字母

    $user_name = strtolower('Hello');
    $user_id
    = 1001;
    $len
    = strlen($user_name);

    for ($pos = 0; $pos < $len; $pos ++) {
        $key
    = md5($user_name[$pos]);
        $redis
    ->sAdd('user_name:' . $key . ':' . $pos, $user_id);
    }

    在上面的代码中,我把每个字母用md5哈希一下然后和他的位置值$pos共同组成一个redis索引。这样如果在所有用户名都用这种办法做索引后,我们就可以使用redis的交集功能来做搜索了

    $keyword = strtolower('he');    // 测试的关键词
    $indexes
    = array();             // 索引集合
    $len
    = strlen($keyword);

    for ($pos = 0; $pos < $len; $pos ++) {
        $key
    = md5($keyword[$pos]);
        $indexes
    [] = 'user_name:' . $key . ':' . $pos;
    }

    // 得出结果仅需一步, 求它们的交集
    $result
    = $redis->sInter($indexes);

    但这个办法有几个缺陷

    1. 我觉得还是偏重,因为我只想实现一个用户名自动联想的功能而不是搜索。这样的系统还要维护一套庞大的索引,每次更新用户名还得一个一个删掉然后再塞入新的。
    2. 无法做LIMITOFFSET啊,翻页怎么半,万一一个交集非常大,岂不是要把系统撑死
    3. 模糊查询的功能偏弱,只能处理以关键词开头的情况。不过这个不是重点,能把上面两点解决就很好了。

    不知道各位有什么好的方案?

    redis mysql autocomplete0条评论 | 修改 | 链接

    1 个回答


    • huacnleehuacnlee 1 14分钟前

      http://github.com/huacnlee/redis-sear...

      1. 并没有每个字都索引的,只是在 zset 里面才有每个字,但是数据重复的会被合并掉,我那个模糊查询是以分词的结果作为索引的;
      2. 用户与某些特别关键词的关联这种功能是我下阶段的实现目标(加别名字段)

      内存占用方面:
      89m, 7500+ 实际数据在前缀匹配索引里面, 2086+ 分词索引,此外,一起还有1万多条实际数据在

      huacnlee 1 修改于 9分钟前

  • 相关阅读:
    【C#语言规范版本5.0学习】2 词法结构(一、简述)
    【C#语言规范版本5.0学习】1.11 特性
    TP5.1 实现超时未支付订单自动关闭
    tp5.1使用队列
    开启队列时,命令行输入php think queue:listen出现乱码
    mysql 查询分组后的总条数
    处理mysql先排序在分组
    mysql 5.7 sql_mode设置 坑
    Windows 版 SourceTree 免登录跳过初始设置的方法和下载地址
    thinkphp5.1-jwt的安装与使用
  • 原文地址:https://www.cnblogs.com/lexus/p/2285158.html
Copyright © 2011-2022 走看看