richcms可以支持电脑版本和移动版两个站点,比如常见的:www.baidu.com和m.baidu.com两个站点,richcms作为一个cms系统,需要同步数据缓存,此文章详细说明如何实现。
从部署角度来说,www和m是两个独立的进程,甚至可以跑在不同的服务器上(连接同样的mysql和redis)。他们之间的缓存同步操作,使用内部的http api来完成。
处理机制一:
判断主站点(www)是否需要API操作m的缓存,如果有需要,写入缓存清理队列(使用mysql来完成)。
// KeyToCacheQueue 把key存储到队列中
//
// 打开条件:有移动站点,而且当前站点是主站点
func KeyToCacheQueue(key string) {
conf, _ := new(ConfigCache).GetConfig()
//有配置移动点域名,而且是主站点,移动站点参数关闭时
if conf.MobileDomain != "" && constname.IsPrimarySite() && !constname.IsSecondSite() {
err := model.CreateCacheQueue(key)
if err != nil {
logx.Errorf("Create cache queue err: %v", err)
}
}
}
清理缓存的API实现:
type Result struct {
Keys []string `json:"keys"`
}
// CacheRemove 清理cache的api
func CacheRemove(c *gow.Context) {
key := c.GetString("key")
if key == "" {
c.DataJSON(1, "缺少key")
return
}
key, _ = url.QueryUnescape(key)
cacheKeys, err := cache.MC.GetKeys()
if err != nil {
c.DataJSON(1, fmt.Sprintf("获取缓存错误:%v", err))
return
}
keys := make([]string, 0)
for _, v := range cacheKeys {
if strings.Contains(v, key) {
_ = cache.MC.RemoveCache(v)
keys = append(keys, v)
}
}
c.DataJSON(Result{
Keys: keys,
})
}
缓存清理操作(通过缓存定时任务)
func (m *CacheTask) clear(item *model.CacheQueue, addr, token string) error {
addr = fmt.Sprintf("%s?key=%s", addr, url.QueryEscape(item.CacheKey))
return m.httpReq(addr, token)
}
func (m *CacheTask) httpReq(addr, token string) error {
req, err := http.NewRequest("GET", addr, nil)
if err != nil {
return err
}
req.Header.Add("token", token)
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err1 := client.Do(req)
if err1 != nil {
return err1
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
body, err2 := io.ReadAll(resp.Body)
if err2 != nil {
return err2
}
logx.Infof("缓存清理返回值: %s", string(body))
return nil
}