Memcached 使用记录(以及解决数据不同步的问题的方案)

因为使用了memcached, 所以第一次查找的时候把内容缓存到了memcached里面去了,这样第二次查看的时候就是从memcached里面去取,但是有个坏处是可能第一次查找完,立即内容有更新了,所以导致取到的数据不是最新的。

解决数据不同步的问题

常规做法有两种:
1、数据有改变则在添加、更新、删除时数据的同时更新memcache
2、数据有改变则数据库有一个字段来标识更新时间,例如update_time。当有查询时候,把memcache里的update_time与数据库的update_time比较。如果发生变化则更新memcache

超期时间设置,应根据数据访问的频繁度和内存大小来权衡一下。


注意:memcache内存申请后,映像中不会被释放。它是通过 如果有一部分数据超时,则新写入的数据覆盖超时数据来完成重复使用的。那么理论上来讲,内存使用情况是数据被memcache占用最多的那一刻!


据说不是分布式的话就没必要弄什么memcached.还不如优化数据库.数据结构 来得实在点.

eg:数据有改变则在添加、更新、删除时数据的同时更新memcache的应用场景:

package com.school.business.impl;

import java.util.List;

import net.spy.memcached.MemcachedClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.school.business.NavigationManager;
import com.school.dao.NavigationMapper;
import com.school.domain.Navigation;
import com.school.domain.NavigationExample;
import com.school.stereotype.NavigationType;
import com.school.stereotype.YesNoStatus;

/**
 * {@link NavigationManager}接口的实现。
 * @author
 */
@Service
public class NavigationManagerImpl implements NavigationManager {

    private static final Logger LOG = LoggerFactory.getLogger(NavigationManagerImpl.class);

    @Autowired
    private NavigationMapper navigationMapper;

    @Autowired
    private MemcachedClient memcachedClient;

    @Override
    @SuppressWarnings("unchecked")
    public List<Navigation> getNavigations(String schoolId, NavigationType navigationType) {
        String key = this.getNavigationsMemcachedKey(schoolId, navigationType);
        Object obj = null;
        try {
            obj = memcachedClient.get(key);
        } catch (Exception e) {
            LOG.warn("getNavigations from Memcached error. Cause: ", e);
        }

        if (null != obj) {
            return (List<Navigation>) obj;
        } else {
            NavigationExample example = new NavigationExample();
            example.createCriteria().andSchoolIdEqualTo(schoolId).andTypeEqualTo(navigationType.getValue())
            .andStatusEqualTo(YesNoStatus.YES.getValue());
            example.setOrderByClause(" ordered ASC ");

            List<Navigation> navigations = navigationMapper.selectByExample(example);

            int exp = 60 * 60 * 10; // 10小时后过期//超期时间设置,应根据数据访问的频繁度和内存大小来权衡一下
            try {
                memcachedClient.set(key, exp, navigations);
            } catch (Exception e) {
                LOG.warn("set getNavigations to Memcached error. Cause: ", e);
            }

            return navigations;
        }
    }

    @Override
    public List<Navigation> getNavigations(NavigationExample example) {
        example.setOrderByClause(" ordered ASC ");
        return navigationMapper.selectByExample(example);
    }

    @Override
    public Navigation getNavigation(String navigationId) {
        return navigationMapper.selectByPrimaryKey(navigationId);
    }
//添加数据
    @Override
    public boolean addNavigation(String schoolId, Navigation navigation) {
        int rows = navigationMapper.insertSelective(navigation);

        try {
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.HEADER));
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.FOOTER));
        } catch (Exception e) {
            LOG.warn("addNavigation from Memcached error. Cause: ", e);
        }

        return (rows > 0);
    }
<span style="white-space:pre">	</span>//更新数据时,删掉memcached缓存
    @Override
    public boolean updateNavigation(String schoolId, Navigation navigation) {
        int rows = navigationMapper.updateByPrimaryKeySelective(navigation);

        try {
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.HEADER));
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.FOOTER));
        } catch (Exception e) {
            LOG.warn("updateNavigation from Memcached error. Cause: ", e);
        }

        return (rows > 0);
    }
// 删除数据
    @Override
    public boolean deleteNavigation(String schoolId, String navigationId) {
        int rows = navigationMapper.deleteByPrimaryKey(navigationId);

        try {
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.HEADER));
            memcachedClient.delete(this.getNavigationsMemcachedKey(schoolId, NavigationType.FOOTER));
        } catch (Exception e) {
            LOG.warn("deleteNavigation from Memcached error. Cause: ", e);
        }

        return (rows > 0);
    }

    /**
     * 构建缓存在Memcached中的Key。
     */
    private String getNavigationsMemcachedKey(String schoolId, NavigationType navigationType) {
        return schoolId + navigationType.getValue();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值