新聞中心
1、概述
說到熱點問題,首先我們先理解一下什么是熱點?

創(chuàng)新互聯(lián)聯(lián)系熱線:18982081108,為您提供成都網(wǎng)站建設(shè)網(wǎng)頁設(shè)計及定制高端網(wǎng)站建設(shè)服務(wù),創(chuàng)新互聯(lián)網(wǎng)頁制作領(lǐng)域十多年,包括服務(wù)器托管等多個行業(yè)擁有豐富的網(wǎng)站運維經(jīng)驗,選擇創(chuàng)新互聯(lián),為網(wǎng)站錦上添花!
熱點通常意義來說,是指在一段時間內(nèi),被廣泛關(guān)注的物品或事件,例如微博熱搜,熱賣商品,熱點新聞,明星直播等等,所以熱點產(chǎn)生主要包含2個條件:1.有限時間, 2流量高聚。
而在互聯(lián)網(wǎng)領(lǐng)域,熱點又主要分為2大類:
1. 有預(yù)期的熱點:比如在電商活動當(dāng)中推出的爆款聯(lián)名限量款的商品,又或者是秒殺的會場活動等
2. 無預(yù)期的熱點:比如受到了,網(wǎng)絡(luò)爬蟲頻繁訪問,又或者突發(fā)新聞帶來的流量沖擊等
針對于有預(yù)期的熱點可以通過熱點數(shù)據(jù)預(yù)熱, 流量限制和異步隊列進行處理。但是對于突發(fā)性無感知的熱點數(shù)據(jù)流量,往往由于請求過于集中,導(dǎo)致訪問數(shù)據(jù)流量超出的server的正常負(fù)載水位,從而出現(xiàn)服務(wù)過載不可用的情況,這種問題被稱之為熱點問題。
2、熱點場景
看完關(guān)于熱點問題的簡單介紹,我們已經(jīng)理解了熱點產(chǎn)生的條件是短時間內(nèi)被頻繁訪問導(dǎo)致流量高聚,而流量高聚就會出現(xiàn)一系列的熱點問題。那被頻繁訪問的Key,就是我們通常所說的熱Key。
接下來我們來看一下哪些場景會導(dǎo)致熱點問題以及對應(yīng)的熱Key:
- MySQL中被頻繁訪問的數(shù)據(jù) ,如熱門商品的主鍵Id
- Redis緩存中被密集訪問的Key,如熱門商品的詳情需要get goods$Id
- 機器人爬蟲的請求信息,如特定標(biāo)識的userId、機器IP
- 頻繁被訪問的接口地址,如獲取用戶信息接口 /userInfo/ + userId
3、熱點探測技術(shù)原理
了解完什么是熱點問題和熱Key出現(xiàn)的場景以后,我們會提出一個疑問,如何去提前感知這些熱點數(shù)據(jù)?這里就需要聊到熱點探測技術(shù)。
3.1 熱點探測可以帶來什么好處?
3.1.1 提升性能
解決熱點問題通常會使用分布式緩存,但是在讀取時還是需要進行網(wǎng)絡(luò)通訊,就會有額外的時間開銷。那如果能對熱點數(shù)據(jù)提前進行本地緩存,即本地預(yù)熱,就能大幅提升機器讀取數(shù)據(jù)的性能,減輕下層緩存集群的壓力。
- 注意,本地緩存與實時數(shù)據(jù)存在不一致的風(fēng)險。需要根據(jù)具體業(yè)務(wù)場景進行評估,緩存級數(shù)越多,數(shù)據(jù)不一致的風(fēng)險就越大!
3.1.2 規(guī)避風(fēng)險
對于無預(yù)期的熱數(shù)據(jù)(即突發(fā)場景下形成的熱Key),可能會對業(yè)務(wù)系統(tǒng)帶來極大的風(fēng)險,可將風(fēng)險分為兩個層次:
- 對數(shù)據(jù)層的風(fēng)險
正常情況下,Redis 緩存單機就可支持十萬左右 QPS,并能通過集群部署提高整體負(fù)載能力。對于并發(fā)量一般的系統(tǒng),用 Redis 做緩存就足夠了。但是對于瞬時過高并發(fā)的請求,因為Redis單線程原因會導(dǎo)致正常請求排隊,或者因為熱點集中導(dǎo)致分片集群壓力過載而癱瘓,從而擊穿到DB引起服務(wù)器雪崩。
- 對應(yīng)用服務(wù)的風(fēng)險
每個應(yīng)用在單位時間所能接受和處理的請求量是有限的,如果受到惡意請求,讓惡意用戶獨自占用了大量請求處理資源,就會導(dǎo)致其他人畜無害的正常用戶的請求無法及時響應(yīng)。
因此,需要一套動態(tài)熱Key 檢測機制,通過對需要檢測的熱Key規(guī)則進行配置,實時監(jiān)聽統(tǒng)計熱Key數(shù)據(jù),當(dāng)無預(yù)期的熱點數(shù)據(jù)出現(xiàn)時,第一時間發(fā)現(xiàn)他,并針對這些數(shù)據(jù)進行特殊處理。如本地緩存、拒絕惡意用戶、接口限流 / 降級等。
3.2 如何進行熱點探測?
首先我們要定義一下如何才能算是一個熱點,我們知道熱點產(chǎn)生的條件是2個:一個時間,一個流量。那么根據(jù)這個條件我們可以簡單定義一個規(guī)則:比如 1 秒內(nèi)訪問 1000 次的數(shù)據(jù)算是熱數(shù)據(jù),當(dāng)然這個數(shù)據(jù)需要根據(jù)具體的業(yè)務(wù)場景和過往數(shù)據(jù)進行具體評估。
對于單機應(yīng)用,檢測熱數(shù)據(jù)很簡單,直接在本地為每個Key創(chuàng)建一個滑動窗口計數(shù)器,統(tǒng)計單位時間內(nèi)的訪問總數(shù)(頻率),并通過一個集合存放檢測到的熱 Key。
而對于分布式應(yīng)用,對熱 Key 的訪問是分散在不同的機器上的,無法在本地獨立地進行計算,因此,需要一個獨立的、集中的熱 Key 計算單元。
我們可以簡單理解為:分布式應(yīng)用節(jié)點感知熱點規(guī)則配置,將熱點數(shù)據(jù)進行上報,工作節(jié)點進行熱點數(shù)據(jù)統(tǒng)計,對于符合閾值的熱點進行推送給客戶端,應(yīng)用收到熱點信息進行本地緩存等策略這五個步驟:
1. 熱點規(guī)則:配置熱Key的上報規(guī)則,圈出需要重點監(jiān)測的Key
2. 熱點上報:應(yīng)用服務(wù)將自己的熱Key訪問情況上報給集中計算單元
3. 熱點統(tǒng)計:收集各應(yīng)用實例上報的信息,使用滑動窗口算法計算Key的熱度
4. 熱點推送:當(dāng)Key的熱度達到設(shè)定值時,推送熱Key信息至所有應(yīng)用實例
5. 熱點緩存:各應(yīng)用實例收到熱Key信息后,對Key值進行本地緩存(此步驟根據(jù)具體業(yè)務(wù)策略調(diào)整)
4、Burning
理解完熱點探測原理以后,我們來聊聊得物的熱點探測中間件Burning。
作為潮流互聯(lián)網(wǎng)電商平臺,得物的電商業(yè)務(wù)高速發(fā)展,突發(fā)性的熱點數(shù)據(jù)不斷的沖擊著我們的系統(tǒng)服務(wù),比如大促秒殺,熱點商品,等等。針對于這種突發(fā)性的大流量,單純的機器擴容并不是一個有效的解決手段,我們需要一個集熱點探測,熱點感知,熱點數(shù)據(jù)推送,熱點數(shù)據(jù)預(yù)熱,熱點監(jiān)控分析等功能于一體的熱點探測中間件,因此Burning應(yīng)運而生。
4.1 價值意義
Burning作為得物的熱點探測中間件,提供可供業(yè)務(wù)方接入的SDK包和管理臺規(guī)則配置,用于對熱點數(shù)據(jù)的實時性監(jiān)控,探測,操作和本地緩存等。主要解決了以下問題:
- 實時熱點感知:能實時監(jiān)控?zé)狳c數(shù)據(jù),包含熱Key,熱數(shù)據(jù),熱接口等,秒級上報集群統(tǒng)一計算
- 本地數(shù)據(jù)預(yù)熱:對于特定場景可以通過動態(tài)本地緩存配置,防止流量突增導(dǎo)致Redis或DB數(shù)據(jù)流量壓力過大導(dǎo)致系統(tǒng)雪崩
- 周期熱點統(tǒng)計:對熱點數(shù)據(jù)進行周期性統(tǒng)計分析,標(biāo)記出熱Key規(guī)則及分布比例等,可以幫助業(yè)務(wù)方進行針對性優(yōu)化治理和營銷策略選擇
- 系統(tǒng)安全治理:可以通過熱點Key探測分析,對于刷子用戶,問題IP,機器人和爬蟲進行標(biāo)識,可實時熔斷存在安全風(fēng)險的請求,提高系統(tǒng)安全和可用性
4.2 關(guān)鍵指標(biāo)
為滿足高并發(fā)場景,熱點探測中間件Burning在設(shè)計的時候,重點關(guān)注了如下指標(biāo):
1.實時性:熱點問題往往具備突發(fā)性,客戶端必須能夠?qū)崟r發(fā)現(xiàn)可疑熱Key并推送給計算單元進行探測
2.高性能:熱點探測往往需要處理大量的熱點探測請求和熱點計算,因此熱點探測中間件的性能要求較高,才能滿足巨量的并發(fā)并有效降低成本
3.準(zhǔn)確性:熱點探測需要精準(zhǔn)的探測符合規(guī)則熱Key,實時監(jiān)聽規(guī)則的變化,正確的進行熱Key上報和熱Key計算
4.一致性:熱點探測需要保證應(yīng)用實例的本地緩存熱Key一致,當(dāng)熱Key變更導(dǎo)致value失效時,應(yīng)用需要同時進行失效來保證數(shù)據(jù)一致性,不能出現(xiàn)數(shù)據(jù)錯誤
5.可擴展:熱點探測需要統(tǒng)計和計算的Key量級很大,而且存在突發(fā)流量的情況,統(tǒng)一計算集群需要具備水平擴展的能力
4.3 架構(gòu)設(shè)計
Burning的架構(gòu)設(shè)計遵循了以上熱點探測的技術(shù)原理,同時借鑒了jd-hotKey的設(shè)計思路,主要分為Burning-Admin、Burning-Worker、Burning-Config、Burning-Client四個模塊:
- Burning-Admin (熱點探測管理臺):與Worker節(jié)點Netty長鏈接通信,提供不同維度的應(yīng)用管理和熱點規(guī)則配置,提供查詢熱點數(shù)據(jù)統(tǒng)計,規(guī)則和熱點數(shù)據(jù)監(jiān)控大盤,提供工作集群信息查詢及客戶端節(jié)點信息查詢,提供本地緩存動態(tài)配置及熱點信息實時通知
- Burning-Worker(熱點集中計算單元):無狀態(tài)server端,與管理臺和客戶端進行Netty長鏈接通信,獲取規(guī)則,滑動窗口計算熱點,將熱點記錄推送到管理臺展示和客戶端處理
- Burning-Config(熱點配置中心):作為熱點、規(guī)則配置中心和注冊中心,將規(guī)則配置下發(fā)到Worker節(jié)點和客戶端,通過Raft算法進行系統(tǒng)高可用一致性保證
- Burning-Client(熱點客戶端SDK):與Worker節(jié)點建立Netty長鏈接通信,監(jiān)聽配置中心配置變化定時推送熱Key數(shù)據(jù),獲取熱Key推送本地內(nèi)緩存設(shè)置,與Redis-client無縫集成及其他ORM框架無縫集成
4.4 鏈路流程
熱點探測主要包含以下幾個主要流程:
- 用戶在管理后臺(Burning-Admin)進行熱點規(guī)則配置并進行熱點數(shù)據(jù)實時監(jiān)控
- 管理后臺(Burning-Admin)將規(guī)則配置信息上傳給配置中心(Burning-Config)
- 配置中心(Burning-Config)將熱點規(guī)則下發(fā)給客戶端(Buring-Client)和工作節(jié)點(Burning-Worker)
- 客戶端(Burning-Client)獲取到規(guī)則, 將指定規(guī)則的熱Key定時上報給工作節(jié)點(Burning-Worker)
- 工作節(jié)點(Burning-Worker)獲取到上報的熱Key后進行滑動時間窗口計算,對于滿足閾值的熱點推送給客戶端(Burning-Client)
- 客戶端(Burning-Client)拿到熱點數(shù)據(jù)后,進行對應(yīng)的本地緩存配置
4.5 核心代碼
- 客戶端啟動器ClientStarter,啟動配置中心和注冊中心,Worker建連,注冊事件監(jiān)聽,設(shè)置app_name、port、caffeine緩存大小、cache配置、監(jiān)控配置等
public synchronized static void startPipeline(BurningCommonProperties burningCommonProperties) {
if (STARTED.get() == Boolean.FALSE) {
DwLogger.info("start pipeline");
// 設(shè)置參數(shù)上下文
setToContext(burningCommonProperties);
// 配置中心啟動
EtcdConfigFactory.buildConfigCenter(burningCommonProperties.getConfigServer());
ConfigStarter starter = EtcdConfigStarter.getInstance();
starter.start();
// 注冊中心啟動
RegisterFactory.buildRegisterCenter(burningCommonProperties);
RegisterStarter registerStarter = RegisterStarter.getInstance();
registerStarter.start();
// 熱點探測啟動
DetectFactory.startDetect(burningCommonProperties.getPushPeriod());
// 開啟worker重連器
WorkerRetryConnector.retryConnectWorkers();
// 注冊事件監(jiān)聽
registEventBus();
// 開啟監(jiān)控
MetricsFactory.startMetrics();
STARTED.set(Boolean.TRUE);
}
}- 客戶端進行熱Key判斷,如果符合規(guī)則就上報給Worker節(jié)點計算,同時進行統(tǒng)計計數(shù)
public static Object dynamicGetValue(String key, KeyType keyType) {
try {
//如果沒有為該key配置規(guī)則,就不用上報key
Boolean dynamicRule = dynamicRule(key);
if (dynamicRule == null) {
return null;
}
Object userValue = null;
ValueModel value = getValueSimple(key);
if (value == null) {
HotKeyPusher.push(key, keyType);
} else {
//臨近過期了,也發(fā)
if (isNearExpire(value)) {
HotKeyPusher.push(key, keyType);
}
Object object = value.getValue();
//如果是默認(rèn)值,也返回null
if (object instanceof Integer && Constant.MAGIC_NUMBER == (int) object) {
userValue = null;
} else if (Boolean.FALSE.equals(dynamicRule)) {
userValue = null;
} else {
userValue = object;
}
}
//統(tǒng)計計數(shù)
MetricsFactory.metrics(new KeyHotModel(key, value != null));
return userValue;
} catch (Exception e) {
DwLogger.error(DwHotKeyStore.class, "get value error");
return null;
}
}- Worker節(jié)點啟動nettyServer,用于各個業(yè)務(wù)服務(wù)實例進行長連接,接收客戶端上報數(shù)據(jù)
public void startNettyServer(int port) throws Exception {
//boss單線程
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
//worker節(jié)點組
EventLoopGroup WorkerGroup = new NioEventLoopGroup(CpuNum.WorkerCount());
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, WorkerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.option(ChannelOption.SO_BACKLOG, 1024)
//保持長連接
.childOption(ChannelOption.SO_KEEPALIVE, true)
//出來網(wǎng)絡(luò)io事件,如記錄日志、對消息編解碼等
.childHandler(new ChildChannelHandler());
//綁定端口,同步等待成功
ChannelFuture future = bootstrap.bind(port).sync();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
bossGroup.shutdownGracefully (1000, 3000, TimeUnit.MILLISECONDS);
WorkerGroup.shutdownGracefully (1000, 3000, TimeUnit.MILLISECONDS);
}));
//等待服務(wù)器監(jiān)聽端口關(guān)閉
future.channel().closeFuture().sync();
} catch (Exception e) {
DwLogger.error("netty server start error.", e);
} finally {
//優(yōu)雅退出,釋放線程池資源
bossGroup.shutdownGracefully();
WorkerGroup.shutdownGracefully();
}
}- Worker節(jié)點通過監(jiān)聽客戶端上報,異步消費隊列Client消息
public void beginConsume() {
while (true) {
try {
HotKeyModel model = QUEUE.take();
if (model.isRemove()) {
iKeyListener.removeKey(model, KeyEventOriginal.CLIENT);
} else {
iKeyListener.newKey(model, KeyEventOriginal.CLIENT);
}
//處理完畢,將數(shù)量加1
totalDealCount.increment();
} catch (Exception e) {
DwLogger.error("consumer error.", e);
}
}
}- 如果是新增一個Key,就生成滑動窗口,基于時間窗口數(shù)據(jù)判斷是否熱Key
@Override
public void newKey(HotKeyModel hotKeyModel, KeyEventOriginal original) {
//cache里的key
String key = buildKey(hotKeyModel);
String name = StringUtils.isBlank(hotKeyModel.getGroup()) ? hotKeyModel.getAppName() : hotKeyModel.getGroup();
//判斷是不是剛熱不久
Object o = hotCache.getIfPresent(key);
if (o != null) {
return;
}
SlidingWindow slidingWindow = checkWindow(hotKeyModel, key, name);
//看看hot沒
boolean hot = slidingWindow.addCount(hotKeyModel.getCount());
if (!hot) {
//如果沒hot,重新put,cache會自動刷新過期時間
CaffeineCacheHolder.getCache(name).put(key, slidingWindow);
} else {
hotCache.put(key, 1);
//刪掉該key
CaffeineCacheHolder.getCache(name).invalidate(key);
//開啟推送
hotKeyModel.setCreateTime(SystemClock.now());
//當(dāng)開關(guān)打開時,打印日志。大促時關(guān)閉日志,就不打印了
if (ConfigStarter.LOGGER_ON) {
DwLogger.info(NEW_KEY_EVENT + hotKeyModel.getKey());
}
//分別推送到各client和etcd
for (IPusher pusher : iPushers) {
pusher.push(hotKeyModel);
}
}
}
- 如果是刪除一個Key,這里刪除包含客戶端發(fā)消息刪除,本地線程掃描過期Key和管理臺刪除
@Override
public void removeKey(HotKeyModel hotKeyModel, KeyEventOriginal original) {
//cache里的key
String key = buildKey(hotKeyModel);
String name = StringUtils.isBlank(hotKeyModel.getGroup()) ? hotKeyModel.getAppName() : hotKeyModel.getGroup();
hotCache.invalidate(key);
CaffeineCacheHolder.getCache(name).invalidate(key);
//推送所有client刪除
hotKeyModel.setCreateTime(SystemClock.now());
DwLogger.info(DELETE_KEY_EVENT + hotKeyModel.getKey());
for (IPusher pusher : iPushers) {
pusher.remove(hotKeyModel);
}
}
- Worker計算完成后將結(jié)果異步推送給Client,通過app進行分組批量推送
@PostConstruct
public void batchPushToClient() {
AsyncPool.asyncDo(() -> {
while (true) {
try {
ListtempModels = new ArrayList<>();
//每10ms推送一次
Queues.drain(hotKeyStoreQueue, tempModels, 10, 10, TimeUnit.MILLISECONDS);
if (CollectionUtil.isEmpty(tempModels)) {
continue;
}
Map> allAppHotKeyModels = Maps.newHashMap();
Map> allGroupHotKeyModels = Maps.newHashMap();
//拆分出每個app的熱key集合,按app分堆
for (HotKeyModel hotKeyModel : tempModels) {
if (StringUtils.isNotBlank(hotKeyModel.getGroup())) {
ListgroupModels = allGroupHotKeyModels.computeIfAbsent(hotKeyModel.getGroup(), (key) -> new ArrayList<>());
groupModels.add(hotKeyModel);
} else {
ListoneAppModels = allAppHotKeyModels.computeIfAbsent(hotKeyModel.getAppName(), (key) -> new ArrayList<>());
oneAppModels.add(hotKeyModel);
}
}
CustomizedMetricsProcessor processor = CustomizedMetricsProcessor.builder(MetricsConstant.BURNING_NETTY_OUT).build();
// group hot key push
pushGroup(processor, allGroupHotKeyModels);
// app hot key push
pushApp(processor, allAppHotKeyModels);
} catch (Exception e) {
DwLogger.error("push to client error.", e);
}
}
});
}
4.6 最佳實踐
Burning提供了2種使用方式,一是通過原生方法調(diào)用,二是通過聲明式注解@EnableBurning , 以下對使用注解進行熱點探測的部分場景提供最佳實踐:
1. 進行熱點判斷,用于熱點攔截和自定義處理實現(xiàn)
@Component
public class Cache {
@EnableBurning(prefix = "hot_Key_", cache = false, hitHandler = ExceptionHitHandler.class)
public String getResult2(String Key) {
return "這是一個測試結(jié)果" + Key;
}
}
2. 命中熱點規(guī)則處理類,可進行自定義實現(xiàn)hitHandler接口(注意cache=false)
public class ExceptionHitHandler implements HitHandler {
@Override
public Object handle(String Key, ProceedingJoinPoint joinPoint) {
//此處可自定義實現(xiàn)
throw new RuntimeException("對不起,您沒有權(quán)限訪問: " + Key);
}
}3. 用于Redis緩存熱點探測
@Component
public class Cache {
@Resource
private RedisTemplateRedisTemplate;
@EnableBurning
public String getResult(String Key) {
return RedisTemplate.opsForValue().get(Key);
}
}
4. 用于MySQL熱數(shù)據(jù)緩存
@Repository
public class SmsSignRepo {
@Autowired
private SmsSignMapper smsSignMapper;
@EnableBurning(prefix = "SMS_SIGN", dynamic = false, KeyType = DATABASE_Key)
public ListgetAll() {
Example example = new Example(SmsSign.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("status", 1);
return smsSignMapper.selectByExample(example);
}
}
4.7 性能表現(xiàn)
4.7.1 Worker節(jié)點性能壓測
上游40個測試調(diào)用實例共同調(diào)用的場景下,并發(fā)數(shù)800,遞進壓測
壓測結(jié)果:1個4C8G工作節(jié)點每秒可平穩(wěn)處理約15W個key的熱點探測,成功率大于99.999%,worker節(jié)點CPU平均占用為80%,內(nèi)存占用60%
4.7.2 Client業(yè)務(wù)應(yīng)用性能壓測
DB場景壓測
Client配置為4C8G,120個并發(fā)請求,壓測時長10min?
- 原生未接入Burning的DB操作接口場景
壓測結(jié)果:未接入burning,處理總請求數(shù)約112萬,平均TPS約1500,平均RT約63MS。CPU在壓測滿載情況下100%,內(nèi)存平均使用48%
- 接入Burning的DB操作接口場景
壓測結(jié)果:接入burning后,處理總請求數(shù)457萬(對比未接入Burning增加345萬),平均TPS約5800(對比未接入Burning增加4300),平均RT約8MS(對比未接入Burning下降55MS)。CPU在壓測滿載情況下100%,內(nèi)存平均使用50%(對比未接入上升2%,本地緩存消耗)
Redis場景壓測
Client配置為4C8G,120個并發(fā)請求,壓測時長10min
- 原生未接入Burning的Redis操作接口場景
壓測結(jié)果:未接入burning,處理總請求數(shù)約298萬,平均TPS約3800,平均RT約14MS。CPU在壓測滿載情況下100%,內(nèi)存平均使用48%
- 已接入Burning的Redis操作接口場景
壓測結(jié)果:已接入burning,處理總請求數(shù)約443萬(對比未接入增加145萬),平均TPS約5700(對比未接入上升1900),平均RT約8MS(對比未接入下降6ms)。CPU在壓測滿載情況下100%,內(nèi)存平均使用48%,基本持平
4.7.3 壓測報告
- Burning工作節(jié)點單機每秒處理15萬個key的探測請求,CPU穩(wěn)定在80%左右,基本無任何異常
- 客戶端應(yīng)用接入burning后,對應(yīng)用實例本身CPU負(fù)載基本無影響,內(nèi)存占用上升主要取決于指定的本地緩存大小,接入后接口性能提升明顯,QPS明顯上升,RT明顯下降
5、總結(jié)
熱點問題在互聯(lián)網(wǎng)場景中屢屢出現(xiàn),特別是電商業(yè)務(wù)的需求場景,例如對于大促期間或者活動搶購期間的某個爆品,可能會出現(xiàn)在幾秒時間內(nèi)流入大量的流量,由于商品數(shù)據(jù)在Redis cluster場景下會按照hash規(guī)則被存放在某個Redis分片上,那么這個瞬間流量也有可能出現(xiàn)打掛Redis分片,導(dǎo)致系統(tǒng)雪崩。所以我們要善于利用熱點探測中間件進行熱Key探測,通過預(yù)置本地緩存解決突發(fā)流量導(dǎo)致的系統(tǒng)瓶頸,也能通過熱點數(shù)據(jù)監(jiān)控分析進行針對性的系統(tǒng)調(diào)優(yōu)。
得物熱點探測組件Burning上線至今,支持了數(shù)十個交易核心鏈路服務(wù),在滿足基礎(chǔ)熱點探測的前提下,Burning還支持本地緩存壓測標(biāo)/染色標(biāo)識別能力,客戶端本地Ecache/Caffeine緩存模式選擇,熱點規(guī)則Group聚合統(tǒng)計等擴展能力。應(yīng)用服務(wù)接入Burning后對于熱點數(shù)據(jù)探測及數(shù)據(jù)獲取性能顯著提高,通過預(yù)熱&實時本地緩存,極大的降低了下層緩存集群和數(shù)據(jù)庫的負(fù)載壓力,為業(yè)務(wù)服務(wù)的健康運作保駕護航。?
網(wǎng)站欄目:得物熱點探測技術(shù)架構(gòu)設(shè)計與實踐
鏈接分享:http://www.dlmjj.cn/article/dpeodhg.html


咨詢
建站咨詢
