小 T 導讀:在TDengine Database還沒(mei)推(tui)出(chu)之前,「每人店」一直(zhi)使用MySQL來(lai)存(cun)儲平臺各(ge)種硬件采集的(de)數(shu)據(ju)。為(wei)了提(ti)高數(shu)據(ju)展(zhan)示(shi)效果,后臺再(zai)將采集到的(de)愿數(shu)據(ju)進行各(ge)個(ge)維度的(de)計(ji)(ji)算(suan)(suan),這樣的(de)計(ji)(ji)算(suan)(suan)導致(zhi)MySQL頻繁讀寫,為(wei)了保(bao)證各(ge)個(ge)維度數(shu)據(ju)的(de)一致(zhi)性,采用了MySQL事(shi)務,性能大受影響,經常(chang)會出(chu)現事(shi)務死鎖(suo),后切換(huan)至TDengine Database,各(ge)個(ge)維度的(de)數(shu)據(ju)都不需要再(zai)計(ji)(ji)算(suan)(suan),直(zhi)接(jie)統計(ji)(ji)結果,省去了很多步驟。
1 使用場景簡介
1.1 業務場景介紹
每(mei)人店(dian)給客(ke)戶提供的服務之一就是(shi)(shi)店(dian)鋪的智(zhi)(zhi)能(neng)化管理(li),通(tong)過在(zai)(zai)各個(ge)門店(dian)安(an)裝(zhuang)我(wo)們的各類智(zhi)(zhi)能(neng)硬件傳(chuan)感設(she)備,統(tong)計客(ke)流等信(xin)息(xi)并進(jin)行數(shu)(shu)據(ju)(ju)展(zhan)示。一個(ge)非(fei)常常見的場景(jing)是(shi)(shi)進(jin)出店(dian)客(ke)戶數(shu)(shu)統(tong)計,并進(jin)行實時狀(zhuang)態顯示和歷(li)史數(shu)(shu)據(ju)(ju)分(fen)析。智(zhi)(zhi)能(neng)設(she)備采集會(hui)四個(ge)指標:采集數(shu)(shu)據(ju)(ju)的時間戳、1分(fen)鐘內(nei)進(jin)店(dian)人數(shu)(shu)、1分(fen)鐘內(nei)出店(dian)人數(shu)(shu)、滯留人數(shu)(shu)。通(tong)常我(wo)們每(mei)天的在(zai)(zai)線(xian)設(she)備數(shu)(shu)在(zai)(zai)2.3萬(wan)(wan)個(ge)左右,每(mei)分(fen)鐘上報一次,每(mei)天有3312萬(wan)(wan)條數(shu)(shu)據(ju)(ju),數(shu)(shu)據(ju)(ju)都是(shi)(shi)永久保存,因此數(shu)(shu)據(ju)(ju)量(liang)積累起來是(shi)(shi)非(fei)常大的。終端(duan)設(she)備原始數(shu)(shu)據(ju)(ju)字段如下:
| 采集字段 | 數據類型 | 說明 |
| data_time | TIMESTAMP | 數據采集時間 |
| data_in | INT | 進店人數 |
| data_out | INT | 出店人數 |
| data_create | BIGINT | 數據寫入系統時間 |
| data_delay | BIGINT | 延時毫秒 |
注:延時毫秒(Kafka收到數據時間戳-設(she)備(bei)統計時間戳),主要用來統計設(she)備(bei)的(de)網絡穩定性和數據完(wan)整性
在TDengine Database還(huan)沒有推出(chu)之(zhi)前(qian),我們(men)(men)一直使用的(de)是MySQL來存(cun)儲我們(men)(men)每(mei)人店平臺的(de)各(ge)種硬(ying)件采(cai)集(ji)的(de)數據(ju)。數據(ju)展示時需要按(an)照(zhao)時間范圍顯示客(ke)流量,比如查詢(xun)和(he)顯示安踏(ta)在深圳市某一個門(men)店過去(qu)一個月每(mei)小時的(de)客(ke)流量情況(kuang)。為了(le)提高數據(ju)展示效(xiao)果和(he)效(xiao)率,我們(men)(men)后(hou)臺將采(cai)集(ji)到的(de)設備數據(ju)進行各(ge)個時間維度的(de)計(ji)算,比如從MySQL中定時讀出(chu)數據(ju),按(an)照(zhao)小時、天、月統計(ji)后(hou)的(de)結果再不斷寫(xie)入MySQL,這(zhe)樣的(de)做法導致MySQL頻繁地讀寫(xie),同時還(huan)要設計(ji)復雜的(de)按(an)時間、商家等分(fen)庫(ku)分(fen)表的(de)邏輯,維護起來是非常麻(ma)煩的(de)。為了(le)保證(zheng)各(ge)個維度數據(ju)的(de)一致性(xing),我們(men)(men)還(huan)使用到了(le)MySQL事務,性(xing)能大受影(ying)響(xiang),經(jing)常會出(chu)現(xian)事務死鎖的(de)發生。
直(zhi)到(dao)TDengine的(de)出(chu)現,為(wei)之眼前(qian)一亮,我(wo)們(men)(men)只需要將(jiang)接收到(dao)的(de)每分鐘(zhong)客(ke)流采(cai)集數據(ju),按照設備(bei)(bei)分表存(cun)(cun)儲(chu),并且給每個設備(bei)(bei)對應(ying)的(de)表打上商家、門店(dian)編號(hao)、設備(bei)(bei)ID的(de)標簽即(ji)可。各個時間維度(du)的(de)數據(ju)都(dou)不(bu)需要我(wo)們(men)(men)再計算后存(cun)(cun)儲(chu)一次(ci)了,直(zhi)接通過TDengine的(de)降采(cai)樣interval語法(fa)來統(tong)計結果,省去(qu)了我(wo)們(men)(men)很多的(de)步驟(zou)。目(mu)前(qian)我(wo)們(men)(men)已(yi)經將(jiang)之前(qian)存(cun)(cun)入(ru)MySQL的(de)設備(bei)(bei)數據(ju)寫(xie)入(ru)TDengine,調(diao)整(zheng)后的(de)系統(tong)整(zheng)體架構如下:

硬件設備(bei)采集(ji)的(de)數據通(tong)過物聯(lian)網(wang)網(wang)關傳遞(di)過來,寫(xie)(xie)入(ru)到Kafka(為(wei)什么用(yong)Kafka而不直接(jie)寫(xie)(xie)入(ru)到TDengine中,因(yin)為(wei)原有架(jia)構已經上線,所以直接(jie)在計算(suan)模(mo)塊上增(zeng)加TDengine的(de)寫(xie)(xie)入(ru))中,然后(hou)通(tong)過新增(zeng)一個(ge)Flink計算(suan)模(mo)組來消(xiao)費Kafka數據,并(bing)調用(yong)TDengine的(de)寫(xie)(xie)入(ru)接(jie)口再(zai)將(jiang)數據寫(xie)(xie)入(ru)到時序庫。上層再(zai)接(jie)我們的(de)用(yong)戶交互APP以及其他數據服務API。
1.2 查詢示例
項(xiang)目(mu)正式上線在2020的(de)1月初,線上時已經導入TDengine的(de)數據(ju)存儲規(gui)模(mo)大(da)概在200G左右,每天的(de)數據(ju)增量在16G左右。
應用(yong)系(xi)統的常規查(cha)(cha)詢(xun)在(zai)24QPS左右(you),基本都(dou)是(shi)按照(zhao)時(shi)間范圍來查(cha)(cha)詢(xun)。業(ye)務(wu)場景(jing)的需求不(bu)會要(yao)求用(yong)戶時(shi)時(shi)刻(ke)(ke)刻(ke)(ke)對數據(ju)進(jin)行(xing)查(cha)(cha)詢(xun),大部分用(yong)戶還是(shi)通過(guo)我們提供的API獲(huo)取數據(ju),然后結(jie)合自身的內部系(xi)統進(jin)行(xing)數據(ju)分析。整體查(cha)(cha)詢(xun)的速度響(xiang)應都(dou)在(zai)幾十(shi)毫秒級別。
前面介紹過(guo),我們最典(dian)型的一個(ge)查詢場(chang)景是(shi)根(gen)據(ju)對某(mou)(mou)商戶的某(mou)(mou)個(ge)門店進行一段(duan)時間內的客流統計(ji)。在MySQL中(zhong)需要對每個(ge)設備(bei)提前做好計(ji)算并(bing)存(cun)入結果表(biao),在TDengine中(zhong),數(shu)據(ju)存(cun)入后就可以(yi)直接查詢,而(er)且響應非常快。我們在TDengine中(zhong)建立(li)一個(ge)門進設備(bei)數(shu)據(ju)的超級表(biao)traffic_data,表(biao)結構如下:
Field | Type | Length | Note |
==============================================================================
data_time |TIMESTAMP | 8| |
data_in |INT | 4| |
data_out |INT | 4| |
data_delay |BIGINT | 8| |
merchant_id |BIGINT | 8|tag |
instance_id |BIGINT | 8|tag |
passageway_id |BIGINT | 8|tag |
其中data_time, data_in, data_out, data_delay我(wo)們(men)在前面表(biao)(biao)(biao)格(ge)中有(you)說明,這(zhe)里重點說一(yi)下三個(ge)(ge)tag(TDengine超級表(biao)(biao)(biao)標(biao)簽(qian))。TDengine的(de)設(she)(she)計思路是每個(ge)(ge)設(she)(she)備(bei)(bei)(bei)一(yi)張(zhang)表(biao)(biao)(biao),表(biao)(biao)(biao)中存(cun)儲設(she)(she)備(bei)(bei)(bei)采集過(guo)來的(de)數據(ju),表(biao)(biao)(biao)上可以(yi)打標(biao)簽(qian),用來對設(she)(she)備(bei)(bei)(bei)進(jin)行描述。所有(you)同類型設(she)(she)備(bei)(bei)(bei)的(de)表(biao)(biao)(biao)會(hui)有(you)相同的(de)表(biao)(biao)(biao)結(jie)構,可以(yi)放到一(yi)張(zhang)超級表(biao)(biao)(biao)下面,但(dan)這(zhe)些子(zi)表(biao)(biao)(biao)會(hui)有(you)不同的(de)標(biao)簽(qian)值。
對于我(wo)們(men)(men)的場(chang)景而言,我(wo)們(men)(men)對每個門(men)店統(tong)計設備建立一張(zhang)表(biao),并(bing)打上三個標簽(qian)商家信息(xi)merchant_id,門(men)店信息(xi)instance_id,出入口信息(xi)passageway_id。在(zai)查(cha)詢(xun)時(shi),我(wo)們(men)(men)往往需要(yao)統(tong)計一段(duan)時(shi)間內的客(ke)(ke)流狀況,比如查(cha)看過去(qu)一段(duan)時(shi)間內,某(mou)個門(men)店按小時(shi)統(tong)計的進(jin)出客(ke)(ke)流量。
我(wo)(wo)(wo)們在沒有使(shi)用(yong)(yong)TDengine前(qian),數據的(de)(de)(de)(de)查詢(xun)都依賴后(hou)(hou)臺的(de)(de)(de)(de)Flink計(ji)算程(cheng)序,需(xu)要(yao)后(hou)(hou)臺的(de)(de)(de)(de)計(ji)算完成后(hou)(hou)才能展示給(gei)用(yong)(yong)戶(hu)(hu),這樣(yang)(yang)會帶來(lai)一定(ding)的(de)(de)(de)(de)延(yan)時(shi)(shi)性,畢(bi)竟多(duo)了(le)一層應用(yong)(yong)就多(duo)了(le)一層出錯的(de)(de)(de)(de)可能。因此我(wo)(wo)(wo)們平臺在設(she)計(ji)之初就確定(ding)了(le)幾種固定(ding)的(de)(de)(de)(de)維(wei)(wei)度(5分鐘,半小時(shi)(shi),小時(shi)(shi),天)來(lai)存(cun)儲(chu),這樣(yang)(yang)的(de)(de)(de)(de)設(she)計(ji)雖然(ran)能滿足(zu)用(yong)(yong)戶(hu)(hu)的(de)(de)(de)(de)需(xu)求(qiu),但(dan)是(shi)這樣(yang)(yang)的(de)(de)(de)(de)設(she)計(ji)讓用(yong)(yong)戶(hu)(hu)只能通(tong)過我(wo)(wo)(wo)們的(de)(de)(de)(de)確定(ding)的(de)(de)(de)(de)維(wei)(wei)度來(lai)查詢(xun),假設(she)某個用(yong)(yong)戶(hu)(hu)突(tu)然(ran)說(shuo)需(xu)要(yao)一個我(wo)(wo)(wo)們平臺沒有設(she)計(ji)的(de)(de)(de)(de)維(wei)(wei)度時(shi)(shi)就無(wu)法滿足(zu)了(le),要(yao)滿足(zu)就需(xu)要(yao)計(ji)算程(cheng)序和存(cun)儲(chu)模塊一起修改(gai),大大的(de)(de)(de)(de)增(zeng)加(jia)了(le)研(yan)發的(de)(de)(de)(de)工作(zuo)量。而TDengine作(zuo)為(wei)時(shi)(shi)序數據庫的(de)(de)(de)(de)降(jiang)采樣(yang)(yang)功能interval的(de)(de)(de)(de)使(shi)用(yong)(yong)讓我(wo)(wo)(wo)們就不(bu)需(xu)要(yao)擔心(xin)這樣(yang)(yang)的(de)(de)(de)(de)需(xu)求(qiu)了(le)。
下面(mian)簡(jian)單的(de)(de)介紹下使(shi)用(yong)(yong)TDengine查詢數(shu)據,就不(bu)去區分什么簡(jian)單查詢和聚合查詢了,對(dui)于TDengine的(de)(de)使(shi)用(yong)(yong)也(ye)只能算是初入(ru)門(men)(men)(men)不(bu)敢過(guo)多描述,以(yi)免貽笑(xiao)大方。我們的(de)(de)數(shu)據主要是根據門(men)(men)(men)店(dian)來劃分的(de)(de),即通過(guo)設備(bei)與門(men)(men)(men)店(dian)的(de)(de)綁(bang)定來確定門(men)(men)(men)店(dian)的(de)(de)數(shu)據,所以(yi)我們TDengine存儲(chu)時超級表(biao)設計的(de)(de)標(biao)簽也(ye)是:商(shang)戶(hu)->門(men)(men)(men)店(dian)->出入(ru)口。
這類(lei)查詢在TDengine中可以用一條SQL語句搞定:
select sum(data_in) as data_in, sum(data_out) as data_out from traffic_data where ("$condition") and data_time >= "$start" and data_time <= "$end" interval($interval) group by instance_id order by data_time desc;
這(zhe)個(ge)查(cha)詢是對(dui)從(cong)$start時刻(ke)到(dao)$end時刻(ke)中,各個(ge)門店(dian)的每個(ge)$interval的時間窗口(kou)內的進(jin)店(dian)人數(shu)、出店(dian)人數(shu)。其中where語句(ju)中的$condition還可(ke)對(dui)商家(merchant_id)或者指定的幾個(ge)店(dian)鋪(instance_id)進(jin)行過濾篩選,實現的Java代碼如下。
Connection connection = null;
Statement ps = null;
ResultSet resultSet = null;
try {
TDengineSettingDto setting = feignCoreService.getTDenginSetting(TDengineConf._TDENGINE_TYPE_DATA_TRAFFIC);
if (setting != null) {
DruidDataSource dataSource = TDengineDataSource.getDataTrafficDataSource(setting.getHost(), setting.getPort(), setting.getDatabase(), setting.getUsername(), setting.getPassword());
connection = dataSource.getConnection();
if (connection != null) {
String condition = "";
for (int i = 0; i < instanceIds.size(); i++) {
long instanceId = instanceIds.get(i);
if (i < (instanceIds.size() - 1)) {
condition += " instance_id = " + instanceId + " or ";
} else {
condition += " instance_id = " + instanceId + " ";
}
}
String interval = DataDimEnum.getInterval(dim);
String sql = "select sum(data_in) as data_in, sum(data_out) as data_out from traffic_data where ("+condition+") and data_time >= "+start+" and data_time <= "+end+" interval("+interval+") group by instance_id order by data_time desc";
logger.info("查詢listWhereInstanceAndTimeGroupByInstanceAndTime客流SQL: " + sql);
ps = connection.createStatement();
resultSet = ps.executeQuery(sql);
if (resultSet != null) {
List<TrafficInstanceDto> list = new ArrayList<TrafficInstanceDto>();
while (resultSet.next()) {
TrafficInstanceDto vo = new TrafficInstanceDto();
vo.setDataTime(resultSet.getLong("ts"));
vo.setInstanceId(resultSet.getLong("instance_id"));
int dataIn = resultSet.getInt("data_in");
if(dataIn<0){
dataIn = 0;
}
int dataOut = resultSet.getInt("data_out");
if(dataOut<0){
dataOut = 0;
}
vo.setTrafficIn(dataIn);
vo.setTrafficOut(dataOut);
list.add(vo);
}
return list;
}
}
}
} catch (SQLException e) {
logger.error("查詢TDengine門店客流數據失敗: {}, {}, {}, {}", instanceIds, start, end, dim, e);
} finally {
try {
if (resultSet != null) {
resultSet.close();
}
} catch (SQLException e) {
logger.error("關閉TDengine連接池ResultSet失敗", e);
}
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
logger.error("關閉TDengine連接池PreparedStatement失敗", e);
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
logger.error("關閉TDengine連接池Connection失敗", e);
}
}
簡(jian)簡(jian)單(dan)(dan)單(dan)(dan)幾行(xing)代碼即可實現各(ge)種維度的數據查詢,是(shi)不是(shi)相(xiang)當簡(jian)單(dan)(dan),根本不需要(yao)修改任何(he)架構。
但我們使(shi)用(yong)(yong)時也發現一個問題(ti),使(shi)用(yong)(yong)TDengine做月(yue)數據查(cha)(cha)詢時interval(1n)數據會不(bu)對(dui),因(yin)為TDengine的月(yue)并(bing)非自然月(yue),默認就是(shi)30天,而31天的月(yue)份(fen)數據會不(bu)全,所(suo)以我們對(dui)月(yue)份(fen)的查(cha)(cha)詢單獨(du)做了處理(li),即先(xian)取到(dao)月(yue)份(fen)的開(kai)始日期和結(jie)束日期,然后(hou)再進行時間段(duan)sum,最(zui)后(hou)用(yong)(yong)程序(xu)來實現統計結(jie)果(guo)的展示,整體影響不(bu)大。
1.3 資源開銷對比
整個系統(tong)自上(shang)線來(lai),并發量(liang)不(bu)算很大,但是對查詢的性能確(que)實(shi)有顯(xian)著(zhu)的提升,用兩張圖來(lai)對比(bi)下一(yi)目了然。

這個是(shi)使(shi)用TDengine后服(fu)務器(qi)的資源使(shi)用情(qing)況,服(fu)務器(qi)上還(huan)允許了好幾個Java應用程序,一點壓力沒有(you),內存,CPU等都沒有(you)壓力。

這個是之(zhi)前相同數(shu)據(ju)負載情(qing)況下(xia)(xia),但沒有使用TD的時候服務(wu)器的壓力:CPU,內存,LoadAverage等都一直居高不下(xia)(xia),資(zi)源開銷的節省一目了(le)然。
2 采用TDengine帶來的收益
使用TDengine后,確實在數據(ju)查(cha)詢和性能上給(gei)我帶了不少的(de)驚喜。因(yin)為剛開始(shi)一直抱著(zhu)先試(shi)用下的(de)心(xin)態,所以并沒(mei)有對整個平(ping)臺的(de)架構進行(xing)大的(de)調整,直接在計算程(cheng)序(xu)上加(jia)一個模(mo)塊就(jiu)完成了,這樣的(de)修改也簡單,真(zhen)正(zheng)上線后發現(xian)確實強悍(han)啊,1月份(fen)上線到現(xian)在也一直沒(mei)管,也沒(mei)有任何故障(zhang),之前使用MySQL時(shi),經常數據(ju)庫故障(zhang),處(chu)理起來非常的(de)痛苦。
3 對社區的一些感想
一開始使用TDengine時,確實遇(yu)到(dao)(dao)不(bu)少的(de)(de)(de)(de)問(wen)題。最開始是(shi)在(zai)GitHub上看別人提的(de)(de)(de)(de)issue有(you)沒(mei)有(you),后來官方弄(nong)了個(ge)微信(xin)(xin)群(qun),遇(yu)到(dao)(dao)問(wen)題可以直接在(zai)微信(xin)(xin)群(qun)里溝通(tong),效率高(gao)了不(bu)少。在(zai)此特別感謝(xie)TDengine團(tuan)隊的(de)(de)(de)(de)廖(liao)博士耐心指導和關懷,期間(jian)幾次遇(yu)到(dao)(dao)TDengine內存泄漏(lou)的(de)(de)(de)(de)問(wen)題,都是(shi)他遠程解決的(de)(de)(de)(de)。目前線上運行的(de)(de)(de)(de)1.6.3.0還是(shi)根據他提供的(de)(de)(de)(de)文件編譯的(de)(de)(de)(de)。
后面也會(hui)考慮(lv)將 TDengine 擴展到更多業務和場景中(zhong),比如看看如何(he)應用TDengine到人(ren)臉(lian)識別這(zhe)塊(kuai)業務中(zhong)來。這(zhe)塊(kuai)目前TDengine倒是滿足,但是如果使用起來這(zhe)個就(jiu)龐大了(le),人(ren)臉(lian)識別將一個人(ren)視為一個終端設備,但是目前的開(kai)源版應該(gai)支撐不了(le)那(nei)么(me)大的量。
4 TDengine功能方面的期望與建議
通(tong)過(guo)這段(duan)時間(jian)的使用(yong),對TDengine還是(shi)期望能(neng)開放(fang)集群(qun)版本的開源,畢(bi)竟這樣性能(neng)等各方(fang)面都能(neng)更出色的體現(xian)出來。目(mu)前所在(zai)(zai)的行(xing)業是(shi)零(ling)售行(xing)業,只針對零(ling)售行(xing)業的使用(yong)存在(zai)(zai)的一(yi)些(xie)問題來說下:
1. 時間連貫性(xing),零售行業的數(shu)據(ju)(ju)(ju)其實不是(shi)連貫的(有(you)營業時間的劃(hua)分),所以(yi)我(wo)們使(shi)用時其實是(shi)將(jiang)(jiang)設(she)(she)備的數(shu)據(ju)(ju)(ju)分開(kai)存儲(chu)的,將(jiang)(jiang)設(she)(she)備所有(you)的元數(shu)據(ju)(ju)(ju)存儲(chu)到(dao)(dao)一(yi)個表中,然后將(jiang)(jiang)營業時間內的數(shu)據(ju)(ju)(ju)進行再(zai)存儲(chu)到(dao)(dao)一(yi)個虛擬的設(she)(she)備中。但是(shi)營業時間外的數(shu)據(ju)(ju)(ju)又(you)不可能丟棄。所以(yi)設(she)(she)備是(shi)會翻(fan)倍(bei)的。如果沿用TDengine的設(she)(she)計(ji)(一(yi)個設(she)(she)備一(yi)張表),這樣統計(ji)數(shu)據(ju)(ju)(ju)時有(you)時會不準。
2. 人(ren)(ren)臉(lian)(lian)識(shi)別應用,之前試過(guo)將(jiang)人(ren)(ren)臉(lian)(lian)識(shi)別的記錄存放到TDengine中(zhong),因為(wei)用的是開源版,發現一個(ge)人(ren)(ren)臉(lian)(lian)用戶(hu)一張表,這個(ge)表的數量(liang)太龐大(da)了,所(suo)以(yi)終止了人(ren)(ren)臉(lian)(lian)業務使(shi)用TDengine。
3. 熱(re)區(qu)采(cai)(cai)集,一(yi)個設(she)備采(cai)(cai)集的坐標(biao)數(shu)據太(tai)大,一(yi)次采(cai)(cai)集就有8萬個坐標(biao)點沒(mei)有合(he)適的數(shu)組(zu)字段類型可以存儲,希望后面可以支持。
總(zong)體上講(jiang),引(yin)入TDengine Database給我們(men)的(de)系(xi)統帶來(lai)了不(bu)少優(you)化的(de)地(di)方,后期我們(men)還會針對(dui)性的(de)刪(shan)減掉一些(xie)不(bu)再必要的(de)模塊(kuai),進一步瘦(shou)身(shen);也希望TDengine Database社區能(neng)持續繁(fan)榮,有(you)不(bu)斷的(de)優(you)化功能(neng)出來(lai)。
作者介紹:盧崇志,每人(ren)店(dian)研(yan)(yan)發經理,2014年加入深圳市曉舟科(ke)技有(you)限公(gong)司研(yan)(yan)發部,工作(zuo)至今,目前負責公(gong)司每人(ren)店(dian)產品(pin)的整體(ti)研(yan)(yan)發工作(zuo),包括(kuo)WEB端與移動端的研(yan)(yan)發工作(zuo)管(guan)理以(yi)及后端Java研(yan)(yan)發和(he)架構設計。
公司介紹:深圳市曉(xiao)舟科技(ji)(ji)有(you)限(xian)公司是一(yi)家(jia)致(zhi)(zhi)力于為千萬門店(dian)提(ti)供觸(chu)手(shou)可(ke)(ke)及的(de)(de)平等(deng)IT及大數據服務的(de)(de)高新(xin)(xin)科技(ji)(ji)企業,公司以專注(zhu)、極(ji)致(zhi)(zhi)、口碑、快(kuai)為運營準(zhun)則,旨在讓(rang)(rang)開店(dian)者可(ke)(ke)以輕松(song)的(de)(de)通(tong)過web、app等(deng)方式輕松(song)找到新(xin)(xin)零售升(sheng)級路徑(jing)。這些路徑(jing)并非簡單的(de)(de)產品組合,而是通(tong)過各種有(you)效創新(xin)(xin)軟硬件,從而完成(cheng)商品的(de)(de)生產、流通(tong)與(yu)銷(xiao)售過程的(de)(de)全(quan)系統改造,并通(tong)過運用大數據、人工智(zhi)能(neng)等(deng)先(xian)進(jin)技(ji)(ji)術手(shou)段(duan),重(zhong)塑業態結(jie)構與(yu)生態圈,從而讓(rang)(rang)顧客享受(shou)更(geng)佳的(de)(de)購物體驗。產品正式銷(xiao)售兩年(nian)多,公司系列產品已在全(quan)國上千個知(zhi)名連鎖品牌五萬多家(jia)門店(dian)實現(xian)覆(fu)蓋,這些知(zhi)名品牌包含(han)安踏、卡門、森馬、依(yi)妙、天(tian)虹、重(zhong)慶百貨(huo)等(deng)。
原文(wen)首發于://www.jianshu.com/p/5af2f6c256a6?from=groupmessage&isappinstalled=0


























