【实战总结】使用Redis做模糊匹配查询

最近在做一个模糊匹配查询的需求,剖析需求本质无非就是根据入参来模糊匹配相关数据进行返回展示。

由于数据是存储在数据库的,简单实现的话可以考虑使用DB的SQL来进行模糊匹配查询,比较考量的就是如何控制你的SQL以及如果能够高效命中索引来优化SQL来实现快速查询了。

由于是全查询的业务,而且业务场景对服务响应是有一定要求的,如果简单的使用数据库恐怕后续峰值难以抗住且也会影响其他同库的读写操作,所以这次打算还是使用缓存来解决这种全查询场景。

Redis的性能非常棒,而且支持多种数据结构供开发者存储和调用,而且提供了大量API对开发非常友好,而且这些API的内部算法也是非常考究的,真的是开发利器。

1、需求背景

按照汉字以最左匹配原则进行模糊匹配,每次返回不超过固定数量的匹配词即可。

2、设计分析

首先要分析设计要解决哪些问题:

Q:高并发场景下,如何保证服务可靠且快速响应

A:使用Redis做全查询缓存,DB做数据持久化,所有请求打到缓存,保护DB;若缓存失效,把请求拦截直接返回,发送MQ异步请求DB数据更新缓存;若缓存异常,代码做兜底控制,如果可以置入动态配置来控制是否兜底查DB,极端情况下直接服务降级处理不走DB。

Q:使用Redis哪种数据结构进行存储数据?

A:首先要考虑需要返回哪些数据,且这些数据的查询可以支持模糊查询;由于需求只需要返回名称和对应ID,决定采用Hash表进行存储;且hash表支持模糊查询命令。

3、数据存储

关于Redis的命令可以参考http://doc.redisfans.com/index.html

在应用启动时,使用hmset进行批量全量缓存数据更新,这里有个细节点,由于是分布式部署,如果不加限制默认每台机器启动都会更新一遍,其实是没有必要的,可以做一个全局分布式锁进行判断和控制,这个不难实现不再细说。

HMSET key field value [field value ...]

要模糊查什么就把模糊查的作为field就可以了,由于我这里只需要两个字段,我就借用哈希表的数据结构进行存储了,如果需要更多字段可以研究使用有序集合或者其他数据结构。

4、数据模糊查询

使用hscan进行模糊查询,可以使用,优缺点分析参考http://doc.redisfans.com/key/scan.html#scan

HSCAN key cursor [MATCH pattern] [COUNT count]

【实战总结】使用Redis做模糊匹配查询_第1张图片

由于hscan使用了游标,是一个增量式命令,每次查询都是返回一部分数据,所以不会像keys类命令hang住Redis导致服务短暂停滞,所以它是安全无公害的,只要运用得当,在生产环境是可以放心使用的,关于缺点要参考:

  • 同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。
  • 如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义的(undefined)。

在使用过程中仔细研究这个命令的底层实现,根据实际业务场景去使用。

业务底层还是需要封装下hscan命令,由于是游标查询,最开始cursor我们都设置为0就好,每次从0开始查询,count来控制每次遍历的数量,由于这个命令执行的时间复杂度是O(N),所以count越大,每次执行时间理论上会越长,可以根据实际场景进行调整,在遍历时候判断返回的游标cursor是否为0,如果为0代表整个遍历结束。

目前只使用到最左匹配模糊查询,如上图,我试了下最右匹配、中间模糊也是可以查询到的,可以支持后续其他业务诉求。

5、特殊字符处理

由于一般我们检索的名称是汉字,存储到Redis可能会有环境问题导致乱码,我目前的处理是把汉字转ASCII码进行存储,同样查询的时候也是转ASCII码进行查询,这样可以解决汉字或者编码带来的乱码问题。

你可能感兴趣的:(实战总结)