獲取地區數據的api接口(程序代碼見文末),原先的實現是初次http請求時一次性加載到內存變量裏,之後的調用則直接從內存變量讀取。這樣雖然快,但弊端顯而易見,當數據有更新,只能經過重啓站點服務的方式搞定。
因此,要改造。
直覺想到的是用redis緩存。web
在coding的時候,忽然以爲仍是從內存上作文章多好啊,畢竟讀內存是最快的方式了。因而,想到了一個辦法,每到整點清空數據變量。代碼以下。使用地區數據的地方再也不直接訪問areaStr變量,而是調用getAreaStr()方法。redis
import org.joda.time.DateTime; private static String areaStr = ""; private String getAreaStr(){ //整點清除數據,從新調用rpc並加載到內存 int minuteOfHour = DateTime.now().getMinuteOfHour(); if (0 == minuteOfHour) { areaStr = ""; } if (StringUtil.isBlank(areaStr)) { log.info("初始化地區數據到內存"); //rpc請求 areaStr = threeLevelClient.selectAreaList(); } return areaStr; }
還沒等自測,我就意識到不對頭了。這是web接口啊,那整點沒有http請求的話,豈不是就達不到刷新數據的預期了!
仍是不忘初心的好!就用redis來搞。——考慮到數據量大,我仍是作了點改動:把數據放到內存裏,經過redis來控制內存數據的刷新。api
private static String areaStr = ""; private static JedisCluster jc = JedisClusterUtil.getJedisCluster(); // 地區數據量大(2712條),不宜直接放到redis裏。這裏經過redis控制內存數據的刷新。 private void resetAreaStr() { final String areaStr_Key = "payment_api_areaStr"; String value = jc.get(areaStr_Key); if (StringUtils.isBlank(value)) { areaStr = threeLevelClient.selectAreaList(); jc.setex(areaStr_Key, 300, "1"); log.info("重置redis緩存:" + areaStr_Key); } if (StringUtils.isBlank(areaStr)) { log.info("初始化地區數據到內存"); //rpc請求 areaStr = threeLevelClient.selectAreaList(); } }
這樣無疑是不錯的方案了。使用areaStr以前調用resetAreaStr()方法便可。緩存
@RequestMapping("cityQuery") public void cityQuery(HttpServletResponse response) throws Exception { // log.debug("payment_api----獲取地區列表:{}", areaStr); resetAreaStr(); List<JSONObject> areaList = JSON.parseArray(areaStr, JSONObject.class); List<Map<String, String>> showAreaList = new ArrayList<>(); areaList.forEach(one -> { Map<String, String> bankInfo = new HashMap<>(); bankInfo.put("provinceName", one.getString("provinceName")); bankInfo.put("areaName", one.getString("areaName")); showAreaList.add(bankInfo); }); log.info("集合size:{}", areaList.size()); WebUtil.outputJson(showAreaList, response); }