网站建设带有注册账号网站怎么被收录

当前位置: 首页 > news >正文

网站建设带有注册账号,网站怎么被收录,手机 网站开发软件,免费x网站域名如何给飞行中的飞机换引擎? 背景 业务背景 略 技术背景 线下集群40个索引左右#xff0c;总数据量不大,不到100G因为ES承担的业务鉴权业务#xff0c;所以不能接受停机割接 还有就是ES中数据来自各个业务方#xff0c;推送的时机不定#xff0c;也没有完备的重推机制总数据量不大,不到100G因为ES承担的业务鉴权业务所以不能接受停机割接 还有就是ES中数据来自各个业务方推送的时机不定也没有完备的重推机制所以不能停机割接 索引中基本都没有创建或者更新时间字段即使部分有也没有用起来 也就无法使用logstash的增量同步功能。 希望不进行业务改造直接替换。虽然服务分为了读写服务但通过读服务还是可以调用写入的API通过写服务也可以调用读的API。
架构方案 全量数据同步logstash脚步比对出来的差异数据脚步补数 注意 CLB及代理层的配置一定有冗余如果个CLB支撑不了可以考虑 方式一直接申请多个CLB,并将这多个CLB的地址配置到应用中方式二先申请一个EIP在EIP的后面配置多个CLB这样应用只配置一个EIP的地址就可以了方式三CLB直接升配到NLB CLB文档NLB文档准备两套CLB及代理层的原因是代理层是个Nginx集群手动一台一台更新配置然后reload很慢这时候数据写入的主ES是不确定的。 比对核心逻辑 获取线下集群所有索引(跳过系统所以及不需要迁移的索引)遍历第一步获取到的索引集合 获取线上、线下索引的文档总数如果总数不一样,终止比对如果总数一样则通过search after(需要)分页分别从线上、线下获取数据比对。
注意search_after的排序字段集合有几个要求 如果_id就是业务ID则直接使用该字段如果_id是ES自动生成的ID,则需要使用业务ID字段来排序(需要保证该业务ID索引内部不重复如果不能保证则需要添加其他字段来保证唯一保证唯一的目的就是比对的两个索引在相同位置的文档就应该是一样的不一样就是有问题)如果无法找到能构建复合主键的字段则需要将索引数据完整的拉到内存中然后根据mapping将所有字段拼接构建组合ID然后去重再依次比对。(索引条数不一样的也可以通过类似的方式来查找异常的原因;采取这种简单粗暴方式的原因是1、我们这种类型索引的数据量不大 2、这个比对程序其实就是个临时的工具不会长期使用) 模板、mapping、index setting这些都需要比对。 比对核心代码 MapFlatUtil.java import java.util.;/** Author jiankunking* Date 2024/9/4 17:13* Description:/ public class MapFlatUtil {static String PREFIX .;public static MapString, Object flat(MapString, Object map) {MapString, Object configMap new LinkedHashMap();map.entrySet().forEach(entry - {if (entry.getValue() instanceof Map) {MapString, Object subMap flat(entry.getKey(), (MapString, Object) entry.getValue());if (!subMap.isEmpty()) {configMap.putAll(subMap);}} else if (entry.getValue() instanceof List) {configMap.put(entry.getKey(), entry.getValue());} else {configMap.put(entry.getKey(), entry.getValue() null ? : String.valueOf(entry.getValue()));}});return configMap;}private static MapString, Object flat(String parentNode, MapString, Object source) {MapString, Object flatMap new LinkedHashMap();SetMap.EntryString, Object set source.entrySet();set.forEach(entity - {Object value entity.getValue();String key entity.getKey();String newKey parentNode PREFIX key;if (value instanceof Map) {flatMap.putAll(flat(newKey, (MapString, Object) value));} else if (value instanceof List) {flatMap.put(newKey, value);} else {flatMap.put(newKey, value null ? : String.valueOf(value));}});return flatMap;} } MapCompareUtil.java import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j;import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors;import static com.jiankunking.branchcompare.es.SortUtil.mapComparator;/** Author jiankunking* Date 2024/9/14 9:48* Description:/ Slf4j public class MapCompareUtil {public static boolean isMapEquals(MapString, Object offlineMap, MapString, Object onlineMap) throws JsonProcessingException {offlineMap MapFlatUtil.flat(offlineMap);onlineMap MapFlatUtil.flat(onlineMap);if (offlineMap.size() ! onlineMap.size()) {return false;}for (Map.EntryString, Object offlineEntry : offlineMap.entrySet()) {String offlineEntryKey offlineEntry.getKey();if (!onlineMap.containsKey(offlineEntryKey)) {return false;}Object offlineEntryValue offlineEntry.getValue();Object onlineEntryValue onlineMap.get(offlineEntryKey);Class offlineEntryValueClass offlineEntryValue.getClass();Class onlineEntryValueClass onlineEntryValue.getClass();if (offlineEntryValueClass ! onlineEntryValueClass) {log.warn(value type not equals,offlineEntryValue: offlineEntryValueClass.getName() ,onlineEntryValue: onlineEntryValueClass.getName());return false;}if (offlineEntryValue instanceof Map) {MapString, Object offlineMapValue (MapString, Object) offlineEntryValue;MapString, Object onlineMapValue (MapString, Object) onlineEntryValue;if (!isMapEquals(offlineMapValue, onlineMapValue)) {return false;}continue;} else if (offlineEntryValue instanceof List) {ListObject offlineList (ListObject) offlineEntryValue;ListObject onlineList (ListObject) onlineEntryValue;if (offlineList.size() ! onlineList.size()) {log.warn(list size not equals,offlineList: offlineList.size() ,onlineList: onlineList.size());return false;}// ListMapif (!offlineList.isEmpty() offlineList.get(0) instanceof Map) {ListMapString, Object offlineEntryValueTmp (ListMapString, Object) offlineEntryValue;ListMapString, Object onlineEntryValueTmp (ListMapString, Object) onlineEntryValue;ListSortUtil.Sort sorts new ArrayList();// 按照map 的key 排序for (Map.EntryString, Object entry : offlineEntryValueTmp.get(0).entrySet()) {sorts.add(new SortUtil.Sort(entry.getKey(), SortUtil.Order.ASC));}ListMapString, Object offlineEntryValueSorted offlineEntryValueTmp.stream().sorted(mapComparator(sorts)).collect(Collectors.toList());ListMapString, Object onlineEntryValueSorted onlineEntryValueTmp.stream().sorted(mapComparator(sorts)).collect(Collectors.toList());for (int i 0; i offlineEntryValueSorted.size(); i) {Object offlineListItem offlineEntryValueSorted.get(i);Object onlineListItem onlineEntryValueSorted.get(i);if (!isMapEquals((MapString, Object) offlineListItem, (MapString, Object) onlineListItem)) {return false;}}} else {// List简单类型offlineList.sort(Comparator.comparing(o - o.toString()));onlineList.sort(Comparator.comparing(o - o.toString()));for (int i 0; i offlineList.size(); i) {Object offlineListItem offlineList.get(i);Object onlineListItem onlineList.get(i);if (!simpleObjectEquals(offlineListItem, onlineListItem)) {log.warn(list item not equals,offlineListItem: offlineListItem ,onlineListItem: onlineListItem);return false;}}}continue;}if (!simpleObjectEquals(offlineEntryValue, onlineEntryValue)) {log.warn(map value not equals,offlineEntryValue: offlineEntryValue ,onlineEntryValue: onlineEntryValue);return false;}}return true;}// 只能处理简单对象 不能处理Map List等复杂类型private static boolean simpleObjectEquals(Object o1, Object o2) throws JsonProcessingException {String offlineJson new ObjectMapper().writeValueAsString(o1);String onlineJson new ObjectMapper().writeValueAsString(o2);if (offlineJson.equals(onlineJson)) {return true;}return false;} }SortUtil.java import java.math.BigDecimal; import java.util.; import java.util.stream.Collectors;/*** Author jiankunking* Date 2024/9/5 14:00* Description: https://gist.github.com/IOsetting/25ca8d70c12c11390113d343f666cd6e*/ public class SortUtil {public enum Order {ASC, DESC}/*** param sorts keys and sort direction* return sorted list*/public static ComparatorMapString, Object mapComparator(ListSort sorts) {return (o1, o2) - {int ret 0;for (Sort sort : sorts) {Object v1 o1.get(sort.field);Object v2 o2.get(sort.field);ret singleCompare(v1, v2, sort.order Order.ASC);if (ret ! 0) {break;}}return ret;};}public static class Sort {public String field;public Order order;public Sort(String field, Order order) {this.field field;this.order order;}}private static int singleCompare(Object ao, Object bo, boolean asc) {int ret;if (ao null bo null) {ret 0;} else if (ao null) {ret -1;} else if (bo null) {ret 1;} else if (ao instanceof BigDecimal) {ret ((BigDecimal) ao).compareTo((BigDecimal) bo);} else if (ao instanceof Number) {if (((Number) ao).doubleValue() ! ((Number) bo).doubleValue()) {ret ((Number) ao).doubleValue() ((Number) bo).doubleValue() ? 1 : -1;} else {ret 0;}} else if (ao instanceof Date) {ret ((Date) ao).compareTo((Date) bo);} else {ret String.valueOf(ao).compareTo(String.valueOf(bo));}if (!asc) {return -ret;}return ret;}public static void main(String[] args) {ListMapString, Object list new ArrayList();ListSort sorts new ArrayList();ListMapString, Object sorted list.stream().sorted(mapComparator(sorts)).collect(Collectors.toList());for (MapString, Object map : sorted) {System.out.println(map.get(somekey));}} }EsQueryUtil.java public static SearchResponse searchAfterByMultiFields(RestHighLevelClient restHighLevelClient, String indexName, ListString searchAfterSortFields, ListObject searchAfterValues, int size) throws IOException {SearchSourceBuilder builder new SearchSourceBuilder();builder.size(size);builder.trackTotalHits(true);builder.query(QueryBuilders.matchAllQuery());// USING SEARCH AFTERif (searchAfterValues ! null !searchAfterValues.isEmpty()) {builder.searchAfter(searchAfterValues.toArray());}for (String sortField : searchAfterSortFields) {builder.sort(sortField, SortOrder.ASC);}SearchRequest searchRequest new SearchRequest();searchRequest.indices(indexName);searchRequest.source(builder);// log.info(searchRequest.toString());log.info(searchRequest.source().toString());SearchResponse response restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);return response;}static ListObject getSearchAfterValues(ListString searchAfterSortFields, SearchHit hit) {ListObject searchAfterValues new ArrayList(searchAfterSortFields.size());MapString, Object map hit.getSourceAsMap();for (String field : searchAfterSortFields) {if (field.equals(_id)) {searchAfterValues.add(hit.getId());} else {searchAfterValues.add(map.get(field));}}return searchAfterValues;}反思 要拉通全流程及相关人员核对每个可能出现的问题及应对方案有些东西不能因为是临时的就放松警惕性 比如本次代理层申请的机器是有两块的盘1、一个50G的系统盘 2、一个500G的数据盘但最终落地的时候云厂商同学还是把nginx的访问日志落到了系统盘导致系统盘满了系统受到的影响。 这个500G的盘当时还讨论过要用来存储访问日志防止机器磁盘写满。 任务列表也梳理了代理层遇到问题要发送告警但没有一一核实导致系统盘满的时候没有第一时间收到告警。只要是在核心链路上的不管是不是临时的必须一一测试、验证。