简历 preview
简历上 : 设计并实现了 搜索
需求分析
平台里面都会有一个搜索栏 大体上的目的是 :
-
方便用户快速找到所需的内容
-
增加广告收入
支持搜索主要是支持 :
-
搜索具体的用户
-
搜索某篇文章
因为需要考虑使用使用 ES 进行实现, 所以需要把这两个服务原有的数据 额外的 写入到 ES 中 。

Q : 为什么 不是用户直接写入到 ES
A : 从 DDD 的角度来说 , es 并不考虑 user 的索引怎么确定 也不处理一些业务相关的内容 。 所以只能通过 search 服务
搜索流程设计
推送接口
-
支持业务定制化的结构 和 统一处理的结构
-
提供统一处理接口 和 定制化接口
|
|
推送接口实现
唯一需要注意的一点就是,我们需要传入 user.Id 保证是 updateSert 语意
|
|

es 表结构设计
文章表结构
mapping :
title : type : text
content : type : text
id : type long ; (贯穿业务的id)
status : type : interger
用户表结构
mapping :
nickname : type : text
email : type : text (不使用keyword,正常人很难记住邮箱)
phone : type : keyword
id : tyoe long
- (这里要不要处理,理论上来说前端是不支持的 。 用户层面应该是看不到的,但是客服预计能看到)
搜索接口设计
|
|
搜索接口的实现
|
|
|
|
推送消息
我们在推送消息那个模块引入 3个 kafka 进行异步的推送消息
-
为不同的业务定义不同的 event , 而后业务方朝特定的 Topic 发送消息
-
定义一个统一的 Event 的格式

标签流程设计
标签功能
-
提升用户体验
-
提高搜索引擎优化
-
社交分享
-
个性化推荐
全局标签、个人标签、通用标签
-
用户创建标签
-
用户对某个资源打上标签

表结构设计
创建两张表
-
Tag 表 , 索引 uid . 主要是为了解决 加载个人的全部标签的 内容
-
TagBiz 表, 记录某个人对某个资源打的标签 。
-
理论上我们可以通过 TagBiz 查询一次 Tag 进行获获取 Uid。 但是会多一次自查询 。 尤其是我们在覆盖标签的写法的时候 删除的时候很麻烦
|
|
- 我们为什么要外键 。 Tid 必须对应完整的 Id 字段 。 避免脏关系 。 并且设置级联删除,删除标签的时候 关联的 tag_bizs 一起清理掉
|
|
缓存方案
对于获取用户的全部 tags 我们使用 redis-list 进行缓存预加载
- 提供一个
PreloadUserTags在程序启动的时候 获取全量的tags 分为多个不同的uidlist 进行插入
|
|
标签 + 搜索
使用 kafka 发送一个通用的信息到 any里面 。 注意这里需要保证有序性 因此需要设置key
|
|
标签索引定义 :
|
|
关联两个查询
一个问题 :
- 我们标签和文章是两个索引, 我们需要解决一个类似 mysql 一样的 JOIN 查询
ES 提供了两种方式
-
内嵌文档
-
父子关系

这两种性能很差,我们采用多次查询的方式
-
先查询标签,找到对应的 biz id
-
查询 article ,子 title 和 conent 的查询基础上进一步叠加是否在第一次查询到的 biz id
- 先去 tags 查询出符合条件的 artclie - id
- 然后再去 article 查询对应的 文章。并且设置文章命中的 权重更高
|
|
面试
-
你有没有用过 ES ? 用它来解决什么问题?
-
ES 中的倒排索引是什么? 为什么叫做倒排索引 ?
-
ES 是如何组织倒排索引的 ? 核心是利用了 FST 结构
-
ES 的节点类型有哪些? 他们的作用是什么 ?
-
ES 的写入过程是怎么样的 ? 为什么说他是近实时的
-
什么是缓存预加载?
-
怎么判定一个场景要不要缓存? 缓存时间多久?
- 同一个资源,短时间内不会被重复访问 就不需要缓存
- 理论上缓存时间应该根据用户的习惯来定
-
如何控制 ES 返回的结果
-
怎么在 ES 中解决类似 Mysql Join 的查询场景 ?