久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

提高微服務(wù)可用性的中間件CoralCache

共計(jì) 8961 個(gè)字符,預(yù)計(jì)需要花費(fèi) 23 分鐘才能閱讀完成。

提高微服務(wù)可用性的中間件 CoralCache,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

當(dāng)數(shù)據(jù)庫(kù)出問(wèn)題時(shí)能降級(jí)從本地緩存的數(shù)據(jù)中查詢(xún)數(shù)據(jù),
CoralCache 就是這樣一個(gè)提高微服務(wù)可用性的中間件。

背景

有些場(chǎng)景下,微服務(wù)依賴(lài)數(shù)據(jù)庫(kù)中一些配置項(xiàng)或者數(shù)量很少的數(shù)據(jù),但當(dāng)數(shù)據(jù)庫(kù)本身有問(wèn)題時(shí)候,即使數(shù)據(jù)量很少,這個(gè)服務(wù)是不能正常工作;因此需要考慮一種能支持全量 + 極少變更的全局?jǐn)?shù)據(jù)的場(chǎng)景,當(dāng)數(shù)據(jù)庫(kù)出問(wèn)題時(shí)能降級(jí)從本地緩存的數(shù)據(jù)中查詢(xún)數(shù)據(jù),CoralCache 就是這樣一個(gè)提高微服務(wù)可用性的中間件。

架構(gòu)

CoralCache 中間件架構(gòu)如下圖所示,通過(guò) @EnableLocal 注解開(kāi)啟功能,應(yīng)用啟動(dòng)后將配置的表數(shù)據(jù)一次性加載到內(nèi)存中,內(nèi)存中的數(shù)據(jù)邏輯結(jié)構(gòu)和數(shù)據(jù)庫(kù)中的邏輯結(jié)構(gòu)一樣。

圖 1. 架構(gòu)圖

表達(dá)式計(jì)算引擎

內(nèi)存查詢(xún)引擎的原理是數(shù)據(jù)庫(kù)查詢(xún)降級(jí)發(fā)生后,Intercepter 將攔截到的原始 SQL 傳入查詢(xún)引擎中,查詢(xún)引擎解析 SQL 后得到表名、列名、where 條件表達(dá)式,遍歷 InnerDB 中對(duì)應(yīng)表的數(shù)據(jù)行,并通過(guò)表達(dá)式計(jì)算引擎計(jì)算結(jié)果,計(jì)算結(jié)果為真則添加到結(jié)果集中最后返回給調(diào)用方。

計(jì)算引擎結(jié)構(gòu)如下圖所示,將 where 條件表達(dá)式轉(zhuǎn)為后綴表達(dá)式后依次遍歷后綴表達(dá)式,遇到操作數(shù)直接入棧,遇到操作符則根據(jù)操作符需要的操作數(shù)個(gè)數(shù)彈棧。

圖 2. 表達(dá)式計(jì)算引擎結(jié)構(gòu)

然后根據(jù)操作符和彈出的操作數(shù)進(jìn)行計(jì)算,不同操作符對(duì)應(yīng)不同的計(jì)算方法,并將計(jì)算后的結(jié)果重新作為操作數(shù)入棧執(zhí)到遍歷完成,核心計(jì)算流程代碼如下所示:

public Object calc(Expression where, InnerTable table, InnerRow row) {
 try { postTraversal(where);
 } catch (Exception e) { log.warn( calc error: {} , e.getMessage());
 return false;
 }
 for (ExprObj obj : exprList) { switch (obj.exprType()) {
 case ITEM:
 stack.push(obj);
 break;
 case BINARY_OP: { ExprObj result = calcBinaryOperation(((ExprOperation) obj).getOperationType(), table, row);
 stack.push(result);
 break;
 }
 case UNARY_OP: { ExprObj result = calcSingleOperation(((ExprOperation) obj).getOperationType(), table, row);
 stack.push(result);
 break;
 }
 case FUNCTION_OP: { ExprObj result = calcFunctionOperation(((ExprOperation) obj).getOperationType(), table, row);
 stack.push(result);
 break;
 }
 default:
 break;
 }
 }
 return stack.pop();
 }

常見(jiàn)運(yùn)算符的實(shí)現(xiàn)邏輯運(yùn)算

邏輯常見(jiàn)運(yùn)算符為、=、、=、= 等,它們的共性都是需要 2 個(gè)操作數(shù)并且返回值是布爾類(lèi)型。

public ExprItem logicalCalculus(InnerTable table, InnerRow row, LogicalOperation logicalOperation) { ExprObj second = stack.pop();
 ExprObj first = stack.pop();
 ExprItem result = new ExprItem();
 result.setItemType(ItemType.T_CONST_OBJ);
 Obj firstObj = getObj((ExprItem) first, table, row);
 Obj secondObj = getObj((ExprItem) second, table, row);
 boolean value = logicalOperation.apply(firstObj, secondObj);
 result.setValue(new Obj(value, ObjType.BOOL));
 return result;
 }

例子,以 = 的實(shí)現(xiàn)來(lái)展示:

private ExprObj calcBinaryOperation(OperationType type, InnerTable table, InnerRow row) {
 ExprObj result = null;
 switch (type) {
 case T_OP_EQ:
 result = logicalCalculus(table, row, (a, b) -  ObjUtil.eq(a, b)); //  等于符號(hào)的實(shí)現(xiàn)
 break;
 ...
 default:
 break;
 }
 return result;
 }
public class ObjUtil { private static ObjType resultType(ObjType first, ObjType second) { return ObjType.RESULT_TYPE[first.ordinal()][second.ordinal()];
 }
 public static boolean eq(Obj first, Obj second) { ObjType type = resultType(first.getType(), second.getType());
 switch (type) {
 case LONG: { long firstValue = first.getValueAsLong();
 long secondValue = second.getValueAsLong();
 return firstValue == secondValue;
 }
 case DOUBLE: { double firstValue = first.getValueAsDouble();
 double secondValue = second.getValueAsDouble();
 return Double.compare(firstValue, secondValue) == 0;
 }
 case TIMESTAMP: { java.util.Date firstValue = first.getValueAsDate();
 java.util.Date secondValue = first.getValueAsDate();
 return firstValue.compareTo(secondValue) == 0;
 }
 ...
 default:
 break;
 }
 throw new UnsupportedOperationException(first.getType() +   and   + second.getType() +   not support  =  operation. 
 }
}

數(shù)學(xué)運(yùn)算

數(shù)學(xué)運(yùn)算和邏輯運(yùn)算的流程都一樣,只不過(guò)運(yùn)算后的結(jié)果為數(shù)字類(lèi)型。

LIKE 運(yùn)算符

除了上面說(shuō)的邏輯運(yùn)算和數(shù)學(xué)運(yùn)算外,還支持進(jìn)行模糊匹配的特殊操作符 LIKE。

LIKE 表達(dá)式語(yǔ)法

常見(jiàn)用法如下

LIKE %HUAWEI 匹配以 HUAWEI 結(jié)尾的字符串

LIKE HUAWEI% 匹配以 HUAWEI 開(kāi)頭的字符串

LIKE A_B 匹配以 A 起頭且以 Z 為結(jié)尾的字串

LIKE A?B 同上

LIKE %[0-9]% 匹配含有數(shù)字的字符串

LIKE %[a-z]% 匹配含有小寫(xiě)字母字符串

LIKE %[!0-9]% 匹配不含數(shù)字的字符串


? 和_都表示單個(gè)字符

JAVA 中實(shí)現(xiàn) LIKE 的方案:將 LIKE 的模式轉(zhuǎn)為 JAVA 中的正則表達(dá)式。

LIKE 詞法定義

expr := wild-card + expr
 | wild-char + expr
 | escape + expr
 | string + expr
 |  
wild-card := % 
wild-char := _ 
escape := [%|_] 
string := [^%_]+ (One or   more characters that are not wild-card or wild-char)

定義 Token 類(lèi)

public abstract class Token {
 private final String value;
 public Token(String value) {
 this.value = value;
 }
 public abstract String convert();
 public String getValue() {
 return value;
 }
public class ConstantToken extends Token { public ConstantToken(String value) { super(value);
 }
 @Override
 public String convert() { return getValue();
 }
public class EscapeToken extends Token { public EscapeToken(String value) { super(value);
 }
 @Override
 public String convert() { return getValue();
 }
public class StringToken extends Token { public StringToken(String value) { super(value);
 }
 @Override
 public String convert() { return Pattern.quote(getValue());
 }
public class WildcardToken extends Token { public WildcardToken(String value) { super(value);
 }
 @Override
 public String convert() {
 return  .* 
 }
public class WildcharToken extends Token { public WildcharToken(String value) { super(value);
 }
 @Override
 public String convert() {
 return  . 
 }
}

創(chuàng)建 Lexer(Tokenizer)

public class Tokenizer { private Collection Tuple  patterns = new LinkedList ();
 public  T extends Token  Tokenizer add(String regex, Function String, Token  creator) { this.patterns.add(new Tuple Pattern, Function String, Token (Pattern.compile(regex), creator));
 return this;
 }
 public Collection Token  tokenize(String clause) throws RuntimeException { Collection Token  tokens = new ArrayList ();
 String copy = String.copyValueOf(clause.toCharArray());
 int position = 0;
 while (!copy.equals()) {
 boolean found = false;
 for (Tuple tuple : this.patterns) { Pattern pattern = (Pattern) tuple.getFirst();
 Matcher m = pattern.matcher(copy);
 if (m.find()) {
 found = true;
 String token = m.group(1);
 Function String, Token  fn = (Function String, Token) tuple.getSecond();
 tokens.add(fn.apply(token));
 copy = m.replaceFirst( position += token.length();
 break;
 }
 }
 if (!found) { throw new RuntimeException( Unexpected sequence found in input string, at   + position);
 }
 }
 return tokens;
 }
}

創(chuàng)建 LIKE 到正則表達(dá)式的轉(zhuǎn)換映射

public class LikeTranspiler { private static Tokenizer TOKENIZER = new Tokenizer()
 .add(^(\\[[^]]*]) , ConstantToken::new)
 .add(^(%) , WildcardToken::new)
 .add(^(_) , WildcharToken::new)
 .add(^([^\\[\\]%_]+) , StringToken::new);
 public static String toRegEx(String pattern) throws ParseException { StringBuilder sb = new StringBuilder().append( ^ 
 for (Token token : TOKENIZER.tokenize(pattern)) { sb.append(token.convert());
 }
 return sb.append($).toString();
 }
}

直接調(diào)用 LikeTranspiler 的 toRegEx 方法將 LIKE 語(yǔ)法轉(zhuǎn)為 JAVA 中的正則表達(dá)式。

private ExprObj calcBinaryOperation(OperationType type, InnerTable table, InnerRow row) {
 ExprObj result = null;
 switch (type) {
 . . .
 case T_OP_LIKE:
 result = logicalCalculus(table, row, (a, b) -  ObjUtil.like(a, b));
 break;
 . . .
 }
 return result;
 }
public static boolean like(Obj first, Obj second) { Assert.state(first.getType() == ObjType.STRING, OperationType.T_OP_LIKE +   only support STRING. 
 Assert.state(second.getType() == ObjType.STRING, OperationType.T_OP_LIKE +   only support STRING. 
 String firstValue = (String) first.getRelValue();
 String secondValue = (String) second.getRelValue();
 String regEx = LikeTranspiler.toRegEx(secondValue);
 return Pattern.compile(regEx).matcher(firstValue).matches();
 }

通過(guò)創(chuàng)建詞法分析器并使用此方法進(jìn)行轉(zhuǎn)換,我們可以防止 LIKE 像這樣的子句被轉(zhuǎn)換為正則表達(dá)式 %abc[%]%,該子句應(yīng)將其中的任何子字符串與其中的子字符串匹配,該子句將與子字符串或匹配任何字符串。abc%.abc[.].abc.abc。

類(lèi)型計(jì)算轉(zhuǎn)換

不同數(shù)據(jù)類(lèi)型在進(jìn)行計(jì)算時(shí)需要轉(zhuǎn)型,具體的轉(zhuǎn)化入下二維數(shù)組中。

//  不同類(lèi)型計(jì)算后的類(lèi)型
ObjType[][] RESULT_TYPE = {
 //UNKNOWN BYTE SHORT INT LONG FLOAT DOUBLE DECIMAL BOOL DATE TIME TIMESTAMP STRING NULL
 { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN },// UNKNOWN
 { UNKNOWN, LONG, LONG, LONG, LONG, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, LONG, UNKNOWN },// BYTE
 { UNKNOWN, LONG, LONG, LONG, LONG, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, LONG, UNKNOWN },// SHORT
 { UNKNOWN, LONG, LONG, LONG, LONG, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, LONG, UNKNOWN },// INT
 { UNKNOWN, LONG, LONG, LONG, LONG, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, LONG, UNKNOWN },// LONG
 { UNKNOWN, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, DOUBLE, UNKNOWN },// FLOAT
 { UNKNOWN, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DECIMAL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, DOUBLE, UNKNOWN },// DOUBLE
 { UNKNOWN, DECIMAL, DECIMAL, DECIMAL, DECIMAL, DECIMAL, DECIMAL, DECIMAL, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, DECIMAL, UNKNOWN },// DECIMAL
 { UNKNOWN, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, UNKNOWN, UNKNOWN, UNKNOWN, BOOL, UNKNOWN },// BOOL
 { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, TIMESTAMP, TIMESTAMP, TIMESTAMP, TIMESTAMP, UNKNOWN },// DATE
 { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, TIMESTAMP, TIMESTAMP, TIMESTAMP, TIMESTAMP, UNKNOWN },// TIME
 { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, TIMESTAMP, TIMESTAMP, TIMESTAMP, TIMESTAMP, UNKNOWN },// TIMESTAMP
 { UNKNOWN, LONG, LONG, LONG, LONG, DOUBLE, DOUBLE, DECIMAL, BOOL, TIMESTAMP, TIMESTAMP, TIMESTAMP, STRING, UNKNOWN },// STRING
 { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN },// NULL
};

點(diǎn)擊關(guān)注,第一時(shí)間了解華為云新鮮技術(shù)~

關(guān)于提高微服務(wù)可用性的中間件 CoralCache 問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注丸趣 TV 行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-04發(fā)表,共計(jì)8961字。
轉(zhuǎn)載說(shuō)明:除特殊說(shuō)明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒(méi)有評(píng)論)
主站蜘蛛池模板: 墨江| 镇远县| 沂南县| 广南县| 汝南县| 靖宇县| 蚌埠市| 佛山市| 茌平县| 迭部县| 巍山| 南宫市| 墨竹工卡县| 罗江县| 岳西县| 黄陵县| 金门县| 顺义区| 从江县| 平定县| 佳木斯市| 朔州市| 修水县| 五原县| 雷山县| 石嘴山市| 含山县| 洛阳市| 三亚市| 大荔县| 永仁县| 合水县| 两当县| 安陆市| 博爱县| 平山县| 萨嘎县| 临武县| 江山市| 新竹县| 六枝特区|