面试札记

1.接口的幂等性如何实现的?

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
常见的多种实现方案:
1.通过代码逻辑判断实现;
2.使用token机制实现;
3.乐观锁机制
4.唯一主键
5.防重表
6.唯一ID

A: 通过代码逻辑判断实现接口幂等性,只能针对一些满足判断的逻辑实现,具有一定局限性。
B: 使用token机制实现接口幂等性,通用性强的实现方法:
token详解:
1.生成全局唯一的token,token放到redis或jvm内存,token会在页面跳转时获取.存放到pageScope中,请求提交先获取token
2.提交后后台校验token,执行提交逻辑,提交成功同时删除token,生成新的token更新redis ,这样当第一次提交后token更新了,页面再次提交携带的token是已删除的token后台验证会失败不让提交。

关键是先删除token,还是后删除token?

后删除token:如果进行业务处理成功后,删除redis中的token失败了,这样就导致了有可能会发生重复请求,因为token没有被删除。这个问题其实是数据库和缓存redis数据不一致问题。

先删除token:如果系统出现问题导致业务处理出现异常,业务处理没有成功,接口调用方也没有获取到明确的结果,然后进行重试,但token已经删除掉了,服务端判断token不存在,认为是重复请求,就直接返回了,无法进行业务处理了。

先删除token可以保证不会因为重复请求,业务数据出现问题。出现业务异常,可以让调用方配合处理一下,重新获取新的token,再次由业务调用方发起重试请求就ok了。

token机制缺点:
业务请求每次请求,都会有额外的请求(一次获取token请求、判断token是否存在的业务)。其实真实的生产环境中,1万请求也许只会存在10个左右的请求会发生重试,为了这10个请求,我们让9990个请求都发生了额外的请求。

C.乐观锁机制
这种方法适合在更新的场景中
根据version版本,也就是在操作库存前先获取当前商品的version版本号,然后操作的时候带上此version号。我们梳理下,我们第一次操作库存时,得到version为1,调用库存服务version变成了2;但返回给订单服务出现了问题,订单服务又一次发起调用库存服务,当订单服务传如的version还是1,再执行上面的sql语句时,就不会执行;因为version已经变为2了,where条件就不成立。这样就保证了不管调用几次,只会真正的处理一次。

D.唯一主键
这个机制是利用了数据库的主键唯一约束的特性,解决了在insert场景时幂等问题。但主键的要求不是自增的主键,这样就需要业务生成全局唯一的主键。如果是分库分表场景下,路由规则要保证相同请求下,落地在同一个数据库和同一表中,要不然数据库主键约束就不起效果了,因为是不同的数据库和表主键不相关。

E.防重表
使用订单号orderNo做为去重表的唯一索引,把唯一索引插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。

F.唯一ID
调用接口时,生成一个唯一id,redis将数据保存到集合中(去重),存在即处理过。

2.接口的幂等性如果是用缓存的方式去做, 那么第二次请求来了, 是直接返回订单号还是抛出异常?

假设缓存是先删除的,那么当相同的请求第二次来了,那么可以在后台进行判断,判断该缓存是否还存在,不存在返回自己设置的一些响应,尽量少抛出异常。

3.用户发送的两次请求, 两次请求的间隔是毫秒级的, 第一次请求还没有入库, 那么如何把第二次请求直接返回第一次请求的订单号 ?

在第一次生成订单号后,先把数据放进缓存,然后再入库,这样第二次请求可以在第一次的订单号还没入库前就可以返回第一次的订单号了。

4.Redis分布式锁有没有了解过 ?

什么是分布式锁?
先讲讲线程锁和进程锁
线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。

分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问

5.Redis的lua脚本有没有了解过?

Redis中为什么引入Lua脚本?
Redis是高性能的key-value内存数据库,在部分场景下,是对关系数据库的良好补充。
Redis提供了非常丰富的指令集,官网上提供了200多个命令。但是某些特定领域,需要扩充若干指令原子性执行时,仅使用原生命令便无法完成。
Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向服务器发送 lua 脚本来执行自定义动作,获取脚本的响应数据。Redis 服务器会单线程原子性执行 lua 脚本,保证 lua 脚本在处理的过程中不会被任意其它请求打断。

在2.6版本推出了 lua 脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。
使用脚本的好处如下:

1.减少网络开销:可以将多个请求通过脚本的形式一次发送,减少网络时延。
2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他请求插入。因此在脚本运行过程中无需担心会出现竞态条件,无需使用事务。
3.复用:客户端发送的脚本会永久存在redis中,这样其他客户端可以复用这一脚本,而不需要使用代码完成相同的逻辑。

什么是Lua?
Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放。
其设计目的就是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。因为广泛的应用于:游戏开发、独立应用脚本、Web 应用脚本、扩展和数据库插件等。
比如:Lua脚本用在很多游戏上,主要是Lua脚本可以嵌入到其他程序中运行,游戏升级的时候,可以直接升级脚本,而不用重新安装游戏。

6.解释一下搜索引擎的倒排索引是什么

数据的搜索与查找是计算机软件的核心算法,对海量文档进行快速检索,主要使用的就是倒排索引技术。
倒排索引相当于创建了关键词目录,记录了哪个关键词被哪些部分包含。
当要搜索找到有“关键字”的内容时,先去关键词目录找,找到后去对应部分获取到相应的内容。

倒排表以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档,一个表项就是一个字表段,它记录该文档的ID和字符在该文档中出现的位置情况。

由于每个字或词对应的文档数量在动态变化,所以倒排表的建立和维护都较为复杂,但是在查询的时候由于可以一次得到查询关键字所对应的所有文档,所以效率高于正排表。在全文检索中,检索的快速响应是一个最为关键的性能,而索引建立由于在后台进行,尽管效率相对低一些,但不会影响整个搜索引擎的效率。
在这里插入图片描述

7.es的分词是跟什么有关系的, 分词插件是怎么配置的

分词
搜索引擎的核心是倒排索引,而倒排索引的基础就是分词。所谓分词可以简单理解为将一个完整的句子切割为一个个单词的过程。在 es 中单词对应英文为 term 。
分词是将文本转换成一系列单词(Term or Token)的过程,也可以叫文本分析,在ES里面称为Analysis分词器。
keyword类型的字符串不会被分词,搜索时全匹配查询。
text类型的字符串会被分词,搜索时是包含查询。
不同的分词器对相同字符串分词的结果大有不同,选择不同的分词器对索引的创建有很大的影响。

配置
1.进入IKAnalyzer.cfg.xml 配置如下

<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">XXX.dic</entry>

2.保存后 再同级目录下建立XXX.dic
3.重启es
4.测试

8.es的mapping机制讲一下

Mapping是定义如何存储和索引一个document及其所包含字段的过程。
Mapping是index和type的元数据,每个type都有自己的一个mapping,决定了字段的数据类型和建立倒排索引的行为以及搜索的行为。mapping设置字段的数据类型的时候也设置了该字段是否为exact value还是full text。

Elasticsearch将值分为exact value和full text:
exact value:在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的。当针对exact value的字段进行搜索的时候用bool布尔值进行判断;

full text:会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换),才会建立到倒排索引中,当针对full value的字段进行搜索的时候,需要计算相关度评分;

exact value和full text类型的field就决定了,在一个搜索过来的时候,对exact value field或者是full text field进行搜索的行为也是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索。

工作机制:
每个mapping有一至多个analyzer构成,每个analyzer由一至多个顺序排列的filter组成。在进行搜索文档的时候,将字段内存传给相应的analyzer处理。analyzer内部根据filter顺序依次进行处理。

9.solr和es的异同点?

ElasticSearch vs Solr
1.es基本是开箱即用,非常简单。Solr安装略微复杂。
2.Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。
3.Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持json文件格式。
4.Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑。
5.Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。
6. Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。
7.Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高。

10.es的分片是怎么分的? 怎么去配置它的分片(shard)

1.elasticsearch在建立索引时,根据id或(id,类型)进行hash,得到hash值之后再与该索引的分片数量取模,取模的值即为存入的分片编号。

2.可以指定把数据存储到某一个分片中,通过routing参数

注意:显著提高查询性能,routing

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值