物聯網專案接收裝置實時資料的一個想法
場景是:若干裝置會每隔n秒,傳送p數量的資料到服務端,服務端消費資料的能力為每n秒c個資料。
如果 c >= p, 則服務端正常執行。
如果 c<p,則服務端面臨崩潰,越來越多的資料得不到消費,資料延遲會越來越高。
解決方法: 假設每4s 產生5個資料,服務端每4s消費4個資料
第0s到來的資料:0,1,2,3,4 (版本1)
第4s消費情況:已消費:0,1,2,3,未消費:4(版本1)
同時:裝置又發來資料:0,1,2,3,4 (版本2)
後續消費方式:4(版本2),0,1,2
相當於消費能力之外的資料丟棄,下一次消費優先選擇上次丟棄的資料
程式碼實現
public abstract class MapQueueElement<K extends Serializable> {
private long timestamp;
public long getTimestamp() {
return timestamp;
}
void markTime() {
if(timestamp==0l) {
timestamp=System.currentTimeMillis();
}
}
public abstract K eleKey();
}
public class MapQueue<K extends Serializable,E extends MapQueueElement<K>> {
public ConcurrentHashMap<K, E> dataMap;
private BlockingQueue<E> dataQueue;
/**
* 預設map容量
* 實際應該根據可能存在的資料物件的多少來設定,減少擴容
*/
public static final int DEFAULT_DATAMAP_CAPACITY = 16;
/**
* 預設佇列容量
*/
public static final int DEFAULT_DATAQUEUE_CAPACITY = Integer.MAX_VALUE;
public MapQueue(int dataMapCapacity) {
this.dataMap=new ConcurrentHashMap<K, E>(dataMapCapacity);
this.dataQueue=new LinkedBlockingQueue<E>();
}
public MapQueue(int dataMapCapacity,int dataQueueCapacity) {
this.dataMap=new ConcurrentHashMap<K, E>(dataMapCapacity);
this.dataQueue=new LinkedBlockingQueue<E>(dataQueueCapacity);
}
public MapQueue(int dataMapCapacity,BlockingQueue<E> dataQueue) {
this.dataMap=new ConcurrentHashMap<K, E>(dataMapCapacity);
this.dataQueue=dataQueue;
}
/**
* 執行緒安全的,得到資料直接put進來就可以
*/
public void put(E e) throws InterruptedException {
E mapE=dataMap.get(e.eleKey());
e.markTime();
dataMap.put(e.eleKey(), e);
if(mapE==null) {
dataQueue.put(e);
}
}
/**
* 程式裡不停的take資料,得到資料後放到定長執行緒池裡處理
*/
public E take() throws InterruptedException {
E queueE=dataQueue.take();
E mapE=dataMap.get(queueE.eleKey());
if(mapE!=null&&queueE.getTimestamp()<mapE.getTimestamp()) {//佇列裡的時間早於map裡的時間,使用map的資料,消費能力小於生產能力時,超出部分會走這裡
dataMap.remove(queueE.eleKey());
queueE=null;
return mapE;
}
dataMap.remove(queueE.eleKey());//消費能力大於等於生產能力時,會走這裡
return queueE;
}
}
測試方法
public class ProData extends MapQueueElement<String>{
private String key;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public ProData(String key) {
this.key = key;
}
@Override
public String eleKey() {
return key;
}
}
public class QueueTest {
public static void main(String[] args) throws InterruptedException {
MapQueue<String,ProData> mapQueue=new MapQueue<>(1024);
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
for(int i=0;i<5;i++) {
try {
mapQueue.put(new ProData(String.valueOf(i)));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},0, 4, TimeUnit.SECONDS);
while(true) {
ProData proData=mapQueue.take();
System.out.println(proData.getKey()+"當前時間:"+new Date(System.currentTimeMillis())+"---資料時間"+new Date(proData.getTimestamp()));
Thread.sleep(1000);
}
}
}
得到的結果也如我當初設想:
前提:消費能力c < 生產能力p
條件:c > p/2
結果:保證 前2c-p部分 的資料被實時消費,後面2個p-c部分 的資料 以0.5的概率被消費,保證每次消費能力(2c-p + p-c)= c
條件: c = p/2
結果:每次交替消費前後p/2的資料
條件:c < p/2
結果:不知道怎麼算,不過先到的消費頻率還是高一些
結語:大家看看這樣行不行。
相關文章
- 物聯網裝置的5個關鍵考慮因素
- 物聯網終端裝置——遠端資料採集儀
- 如何保護物聯網裝置
- 使用 EMQX Cloud 實現物聯網裝置一機一密驗證MQCloud
- 工業裝置資料快速接入華為雲物聯網平臺
- Android與物聯網裝置通訊-資料傳遞的本質Android
- 無所不在的JavaScript與物聯網裝置JavaScript
- 事件溯源在物聯網裝置資料同步中應用案例 - eventstore事件
- 物聯網專案落地困境
- 物聯網路卡能用於個人裝置嗎
- 物聯網資料
- 【無源物聯網】物聯網的下一個風口?
- 物聯網的資料方案
- 物聯網閘道器採集工業裝置資料實現遠端監控管理
- 物聯網裝置殭屍網路趨勢分析
- 物通博聯工業裝置資料平臺,助力實現裝置全生命週期智慧管理
- 從裝置聯網走向萬物互聯三大趨勢引領物聯網未來
- 騰訊IOT之樹莓派物聯網裝置樹莓派
- 物聯網路卡能不能更換裝置
- NB-IoT物聯網流量監測裝置
- 裝置接入物聯網平臺必知必會--裝置接入類
- 守護物聯網的邊界:從裝置開始從裝置結束
- 新能源專案中PLC資料採集物聯網可以實現什麼功能
- 日本政府計劃“入侵”公民的物聯網裝置
- 如何優化物聯網邊緣裝置的能源使用優化
- 專案實戰-物聯網平臺搭建-mqtt伺服器搭建(一)MQQT伺服器
- 如何使用物聯網裝置來確保兒童安全?
- 物聯網 IOT 裝置如何脫離資訊孤島?
- 為什麼物聯網可能需要一個全新的專用網路?
- 物聯網產品設計中的裝置升級功能
- 物聯網裝置可能使企業網路面臨威脅
- 超過1億個物聯網裝置容易受到黑客降級攻擊黑客
- 嚴重的ThroughTek SDK漏洞可讓駭客監視數百萬個物聯網裝置
- 談一談資料儲存與物聯網
- 阿里雲物聯網平臺裝置模擬器阿里
- Android與物聯網裝置通訊-概念入門Android
- 高通降低晶片能耗 讓物聯網裝置也用上LTE晶片
- 如何解決物聯網(IoT)裝置充電難題