memcache实现网站公用计数器

最近项目中碰到了一个计数器的实现问题,网上查了很多资料也没有一个完整的实现。所以自己查找xmemcache client和memcache相关的API和说明,找到了一个比较完美的实现方法。
关键类:net.rubyeye.xmemcached.Counter
相关API
技术分享
实现思路:
获取:
获取的时候默认从memcache中获取,初次获取没获得的话加载数据库获取值,并初始化计数器的值。
更新
先从memcache中获取计数器的值,没有获取到得的话加载数据库获取值,并初始化计数器的值。
然后将计数器加1,获取操作后的返回值,如果是100的整数倍就更新到数据库
以下是关键实现类的代码

package com.liu.memcache.tools;

import java.io.IOException;

import net.rubyeye.xmemcached.Counter;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
import net.rubyeye.xmemcached.utils.AddrUtil;

public class MemCachedTools {
    private static final MemCachedTools instance = new MemCachedTools();

    /**
     * instance
     * 
     * @return
     */
    public static MemCachedTools getInstance() {
        return instance;
    }

    private static String memcached_address = ConfigUtil.getInstance()
            .getString("memcached_address");
    private static String memcached_head=ConfigUtil.getInstance()
    .getString("memcached_head");


    /**
     * 值增加1
     * @param key
     * @return 
     */
    public long increaseValue(String key){
        long addResult=0;
        String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                    AddrUtil.getAddresses(memcached_address));
            builder.setSessionLocator(new KetamaMemcachedSessionLocator());
            MemcachedClient memcachedClient = builder.build();
            Counter counter=memcachedClient.getCounter(memKey);
            addResult=counter.incrementAndGet();

            try {
                // close memcached client
                memcachedClient.shutdown();
            } catch (IOException e) {
                System.err.println("Shutdown MemcachedClient fail");
                e.printStackTrace();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            // return ERROR;
        }
        System.out.println("================"+addResult);
        return addResult;
    }

    /**
     * 初始化计数器
     * @param key
     * @param defaultValue
     */
    public void initCounter(String key,long defaultValue){
        String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                    AddrUtil.getAddresses(memcached_address));
            builder.setSessionLocator(new KetamaMemcachedSessionLocator());
            MemcachedClient memcachedClient = builder.build();
            Counter counter=memcachedClient.getCounter(memKey,defaultValue);
            counter.set(defaultValue);
            try {
                // close memcached client
                memcachedClient.shutdown();
            } catch (IOException e) {
                System.err.println("Shutdown MemcachedClient fail");
                e.printStackTrace();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            // return ERROR;
        }
    }

    /**
     * 获取计数器的值
     * @param key
     * @return
     */
    public long getCounterValue(String key){
        String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
        long ret=0;
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                    AddrUtil.getAddresses(memcached_address));
            builder.setSessionLocator(new KetamaMemcachedSessionLocator());
            MemcachedClient memcachedClient = builder.build();
            Counter counter=memcachedClient.getCounter(memKey);
            ret= counter.get();
            try {
                // close memcached client
                memcachedClient.shutdown();
            } catch (IOException e) {
                System.err.println("Shutdown MemcachedClient fail");
                e.printStackTrace();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            // return ERROR;
        }
        return ret;
    }

}

操作计数器实现类

package com.liu.counter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.liu.memcache.tools.MemCachedTools;

/**
 * @author chao.liu
 * @date 2015-03-06
 * 
 */
public class CounterService {
    protected Log log = LogFactory.getLog(getClass());

    public long getStatisticsData() {
        String memKey = "count";
        Long count = null;
        try {
            count = (Long) MemCachedTools.getInstance().getCounterValue(memKey);
        } catch (Exception e) {
        }
        if (count == 0) {
            try {
                // TODO:从数据库加载,此处省略
                count = 120L;
            } catch (Exception e) {
            }
            MemCachedTools.getInstance().initCounter(memKey, count);
        } else {
            // TODO:输出到前台的处理
            log.info("StatisticsService.getStatisticsData  get data to memcached ...............");
        }
        return count;
    }

    /**
     * 更新统计数据
     * 
     * @param channelID
     * @param moduleID
     * @return
     */
    public String updateStatisticsData() {
        String memKey = "count";
        String res = "1";
        Long count = null;
        try {
            count = (Long) MemCachedTools.getInstance().getCounterValue(memKey);
        } catch (Exception e) {
        }
        if (count == 0) {// 空的时候从数据库加载
            // TODO:从数据库加载,此处省略
            count = 120L;
            MemCachedTools.getInstance().initCounter(memKey, count);
        }
        long addRes = MemCachedTools.getInstance().increaseValue(memKey);
        try {
            if (addRes != 0) {
                if (addRes % 100 == 0) {
                    // 每100条更新到数据库一次
                    // update to DB operation
                }
            }
        } catch (Exception e) {
            res = "0";
        }
        return res;
    }

    public static void main(String[] args) {
        CounterService ss=new CounterService();
        System.out.println("当前计数条数是:"+ss.getStatisticsData());
        ss.updateStatisticsData();
        System.out.println("加1后计数条数是:"+ss.getStatisticsData());
    }
}

运行效果:
当前计数条数是:123
================124
加1后计数条数是:124

代码下载:
http://download.csdn.net/detail/shanhuhau/8508929

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。