权衡问题---学习了微服务各大常用组件的一点思考

1.没有什么技术可以完全通用,只要深度使用一定需要从业务出发对技术进行权衡

从几个例子出发:

1.ES的分片机制天生支持分布式,同时也带来了分布式了弊端:排序和算分问题;

搜索的场景需要严格的定制化,通过对mapping的修改可以支持算分的调整,影响查询的结果-----代价是大大增加开发和mapping的维护成本

想要精确的算分和排序--->需要大量的计算和内存

如果数据量不大---->默认使用一个分片---->不需要对排序和算法另外处理/同时牺牲了分布式的特性(建议一个业务场景的分片不超过20g。日志索引的分片不超过50g),这也是为什么7.x版本之后默认一个分片

如果数据量巨大---->必须使用分片----->定制化mapping,粒度到字段级别----->同时还需要大量的内存(只能通过优化尽量压缩,对业务进行区分,必要的时候只能占用大量的cpu和内存 DFS query then Fetch

 

 

下面来看一下ES的查询过程:默认场景下的-----牺牲精准度保证效率

 

 

 

 

 

2.kafka与ES面临相同的问题:kafka的单个分区内可以保证顺序性,分区之间是不能保证顺序性的

如果是类似于日志,不需要考虑消息的顺序性,那可以很好的发挥性能

 

如果需要保证顺序性:

2.1)从业务上把需要有序的打到同一个partition。因为大多数情况只需要业务上保证有序就可以,不用全局有序通过message key来定义,因为同一个key的message可以保证只发送到同一个partition,比如说key是user id,table row id等等,所以同一个user或者同一个record的消息永远只会发送到同一个partition上,保证了同一个user或record的顺序

 

那么单个分片内kafka如何保证有序?

  1. producer发消息到队列时,通过加锁保证有序
    现在假设两个问题:
    broker leader在给producer发送ack时,因网络原因超时,那么Producer 将重试,造成消息重复。
    先后两条消息发送。t1时刻msg1发送失败,msg2发送成功,t2时刻msg1重试后发送成功。造成乱序。

     2.解决重试机制引起的消息乱序

       为实现Producer的幂等性,Kafka引入了Producer ID(即PID)和Sequence Number。对于每个PID,该Producer发送消息的每个<Topic, Partition>都对应一个单调递增的Sequence Number。同样,Broker端也会为每个<PID, Topic, Partition>维护一个序号,并且每Commit一条消息时将其对应序号递增。对于接收的每条消息,如果其序号比Broker维护的序号)大一,则Broker会接受它,否则将其丢弃:

  • 如果消息序号比Broker维护的序号差值比一大,说明中间有数据尚未写入,即乱序,此时Broker拒绝该消息,Producer抛出InvalidSequenceNumber
  • 如果消息序号小于等于Broker维护的序号,说明该消息已被保存,即为重复消息,Broker直接丢弃该消息,Producer抛出DuplicateSequenceNumber
  • Sender发送失败后会重试,这样可以保证每个消息都被发送到broker

 

 

3.分布式的系统中路由算法的弊端:增加/删除节点时会有路由错误的问题(引发类似于缓存雪崩的场景)

对应的解决方案:

3.1)如redis的一致性hash算法

3.2)ES同样面临类似的场景:每个index的主分片设置策略,动态分配会有大量的数据迁移,分配不合理又会影响性能

对此,ES的解决方案是:index建立好之后不允重新设置分片,需要重新设置需要reindex

 

2.从CAP到BASE,都是对分布式的一种权衡策略

 

 

总结:

根据不同的需求和场景,进行定制化的使用

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章