简单且实用的本地缓存(国庆day2)

1 整体流程

在这里插入图片描述

2 代码实现

2.1 查询的整体实现代码

    /**
     * 获取记录等级列表
     *
     * @param businessId 租户id
     * @return List<RecordLevelParam>
     */
    @Transactional(rollbackFor = Exception.class)
    public List<RecordLevelParam> getRecordLevelList(String businessId) {
        synchronized (lock) {
            //1 该租户首次查询,初始化本地缓存
            if (!localStorage.containsKey(businessId)) {
                initialRecordLevelCache(businessId);
            }
            try {
                boolean isUpdate = checkUpdate(businessId);
                if (isUpdate) {
                    updateRecordLevelCache(businessId);
                }

            } catch (Exception e) {

            }
            Map<Integer, RecordLevelParam> recordLevelParamMap = localStorage.get(businessId);
            List<RecordLevelParam> recordLevelParams = new ArrayList<>();
            for (Map.Entry<Integer, RecordLevelParam> entity : recordLevelParamMap.entrySet()) {
                recordLevelParams.add(entity.getValue());
            }
            return recordLevelParams;
        }
    }

2.1.1 初始化缓存

 /**
     * 初始化等级缓存
     *
     * @param businessId 租户id
     */
    private void initialRecordLevelCache(String businessId) {
        synchronized (lock) {
            //1 从数据中查询等级信息
            List<RecordLevelParam> list = prepareRecordLevelParam(businessId);
            Map<Integer, RecordLevelParam> businessMap = new HashMap<>(list.size());
            //2 将等级信息保存到本地
            if (list != null && list.size() > 0) {
                list.forEach(recordLevelParam -> businessMap.put(recordLevelParam.getLevel(), recordLevelParam));
                localStorage.put(businessId, businessMap);
            } else {
                localStorage.put(businessId, new HashMap<>());
            }
            //3 获取当前租户修改等级的时间戳
            Long timeStamp = (Long) redisManager.hget(RECORD_LEVEL_REDIS_HASH_KEY, businessId);
            Long now = System.currentTimeMillis();
            if (null == timeStamp) {
                redisManager.hset(RECORD_LEVEL_REDIS_HASH_KEY, businessId, now);
                RECORD_LEVEL_CACHE_STAMP.put(businessId, now);
            } else {
                RECORD_LEVEL_CACHE_STAMP.put(businessId, timeStamp);
            }
        }
    }

2.1.2 是否更新本地缓存

   /**
     * 是否更新本地缓存
     *
     * @param businessId 租户id
     * @throws Exception 异常
     */
    private boolean checkUpdate(String businessId) throws Exception {
        Long redisStamp = (Long) redisManager.hget(RECORD_LEVEL_REDIS_HASH_KEY, businessId);
        Long cashStamp = RECORD_LEVEL_CACHE_STAMP.get(businessId);
        if (null == cashStamp) {
            throw new Exception("unfind: " + businessId);
        }
        //redis 时间戳大,数据新,需要更新内存
        return redisStamp > cashStamp;
    }

2.1.3 从缓存中获取数据

 Map<Integer, RecordLevelParam> recordLevelParamMap = localStorage.get(businessId);
            List<RecordLevelParam> recordLevelParams = new ArrayList<>();
            for (Map.Entry<Integer, RecordLevelParam> entity : recordLevelParamMap.entrySet()) {
                recordLevelParams.add(entity.getValue());
            }

2.2 修改的整体实现代码

  @Transactional(rollbackFor = Exception.class)
    public void updateBusinessLevel(String businessId, Integer recordLevel) throws Exception {

        // 更新缓存信息
        if (localStorage.containsKey(businessId)) {
            int level = recordLevel;
            localStorage.get(businessId).put(level, getRecordLevelByBusinessId(businessId, level));
            Long now = System.currentTimeMillis();
            redisManager.hset(RECORD_LEVEL_REDIS_HASH_KEY, businessId, now);
            RECORD_LEVEL_CACHE_STAMP.put(businessId, now);
        }
    }
<think>嗯,用户问的是用Go语言获取节假日的方法。首先我得想想有哪些可能的途径。节假日数据通常来自官方发布的安排,比如中国的国务院办公厅每年会公布放假安排,但可能没有官方的API。所以可能需要用第三方接口或者爬虫抓取。 然后,第三方API的话,可能有一些免费的或者付费的,比如聚合数据、百度APIStore之类的,不过用户可能需要注册和获取API key。另外,开源项目可能有整理好的数据,比如awesome-holiday-cn这样的仓库,用户可以直接引用这些数据。 如果用户需要动态获取,可能需要自己维护一个节假日数据库,或者结合爬虫。比如每年年底抓取国务院的公告,解析出放假安排。这时候就需要用Go的HTTP库,比如net/http,然后解析HTML,可能用goquery这样的库。 另外,还要考虑节假日的类型,比如法定节假日和调休的工作日。比如国庆节放假7天,但前后的周末可能要上班。数据结构方面,可能需要一个结构体来存储日期、名称、是否是假期等信息。 还有,用户可能需要判断某一天是否是节假日,或者获取一段时间内的假期列表。这时候可以提供一个函数,传入时间参数,返回对应的信息。需要注意处理时区问题,通常使用中国时区CST。 然后,代码示例的话,可以展示如何从本地JSON文件加载数据,或者从HTTP获取数据。比如定义一个结构体,读取JSON数据,然后遍历查找匹配的日期。 还要提醒用户注意数据的更新问题,比如每年的节假日安排可能会有变化,需要定期更新数据源。如果使用第三方API,要考虑接口的稳定性和调用限制。 另外,开源项目可能有现成的Go库,比如github.com/axiaoxin-com/holiday,用户可以引用这些库来避免重复造轮子。需要检查这些库的维护状态和数据的准确性。 总结一下,获取节假日的几种方法:第三方API、爬虫抓取官方公告、使用开源数据或库。然后根据用户的需求,选择合适的方法,并提供相应的代码示例和注意事项。</think>在 Go 语言中获取节假日信息,可通过以下方式实现: 1. **第三方 API 接口** ```go package main import ( "io/ioutil" "net/http" ) func GetHoliday(apiKey, date string) ([]byte, error) { url := "https://api.example.com/holiday?date=" + date + "&key=" + apiKey resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) } // 使用示例 // data, _ := GetHoliday("YOUR_API_KEY", "2024-10-01") ``` 2. **本地数据存储** ```go // holiday.go type Holiday struct { Date string `json:"date"` Name string `json:"name"` IsOffDay bool `json:"is_off_day"` Description string `json:"description"` } func LoadHolidays() ([]Holiday, error) { file, _ := ioutil.ReadFile("holidays.json") var holidays []Holiday err := json.Unmarshal(file, &holidays) return holidays, err } // holidays.json [ { "date": "2024-01-01", "name": "元旦", "is_off_day": true, "description": "法定节假日" }, { "date": "2024-02-09", "name": "春节", "is_off_day": true, "description": "法定节假日" } ] ``` 3. **开源项目推荐** - [go-holiday](https://github.com/axiaoxin-com/holiday):包含中国节假日的 Go 语言实现 - [holidays-cn](https://github.com/LKI/holidays-cn):中国节假日数据集合 **实现建议:** 1. 使用 `time` 包处理日期格式 ```go import "time" func IsHoliday(t time.Time) bool { // 实现节假日判断逻辑 return false } ``` 2. 注意时区处理 ```go loc, _ := time.LoadLocation("Asia/Shanghai") date := time.Now().In(loc) ``` **注意事项:** 1. 国务院每年会调整放假安排,需及时更新数据 2. 区分法定节假日和调休工作日 3. 考虑缓存机制提高性能 4. 推荐结合自动更新机制: - 定时从政府网站抓取最新安排 - 使用 GitHub Actions 定期更新数据文件 建议优先使用官方数据源+本地缓存方案,既保证数据准确性又避免接口调用限制。对于需要实时数据的场景,可选择可靠的第三方 API 服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值