zoukankan      html  css  js  c++  java
  • EJB+memcache

    首先我们通过下图 了解到memcache在系统中处于大概什么的位置


    然后我们了解下Memcached简介
    1.1. 什么是Memcached  Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
    它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
    Memcached基于一个存储键/值对的HashMap,它并不提供冗余(复制其HashMap条目),当某个服务器停止运行或崩溃了,所有存放在服务器上的键/值对都将丢失。
    但目前Memcached的客户端和代理程序可以提供多服务器的并联方式,可以提供一定的处理能力。
    1.2. Memcached与其他分布式缓存的区别  Memcached与其它常用的分布式缓存(例如EhCache、OSCache、JBoss Cache)最主要的区别在于Memcached采用集中式缓存方式(即一台或多台缓存服务器为所有应用系统提供缓存能力),自身不提供集群能力,不提供缓存复制功能;而其他分布式缓存系统采用分布式缓存方式,各个应用系统内部提供数据缓存的能力,
    多个缓存间采用组播或点对点的方式进行缓存同步。 

    在性能上来看,Memcached比其它分布式缓存系统低一半以上(未考虑大量数据在其它缓存系统进行复制的影响);但从管理方面来看,Memcached的缓存采用集中管理的模式,应用系统可以水平扩展,

    而其它分布式缓存在水平扩展的同时,必须同时调整缓存复制策略,一旦应用服务器节点大量扩展,对于缓存服务器间的数据复制将成几何数增加。

    然后我们从官网http://memcached.org/下载 适合自身系统的memcache安装包

    下载好之后解压

    因为我是windows 操作

    所以解压后 直接CMD到改目录

    到memcached根目录 
    1、安装 
    memcached.exe –d install  

    2、启动 
    memcached.exe -d start 

    现在来试试是否可以连接: 

    使用方法为“telnet ip 端口号”,登录后使用“stats”命令 
    cmd下 
    telnet 192.168.1.135 11211(注意:这里只能用IP 不能用 localhost 或127.0.0.1  11211端口默认的) 

    然后使用:stats命令可以看到memcached的使用情况如下: 

    time: 1255537291 服务器当前的unix时间戳 
    total_items: 54 从服务器启动以后存储的items总数量 
    connection_structures: 19 服务器分配的连接构造数 
    version: 1.2.6 memcache版本 
    limit_maxbytes: 67108864 分配给memcache的内存大小(字节) 
    cmd_get: 1645 get命令(获取)总请求次数 
    evictions: 0 为获取空闲内存而删除的items数(分配给memcache的空间用满后需 要删除旧的items来得到空间分配给新的items) 
    total_connections: 19 从服务器启动以后曾经打开过的连接数 
    bytes: 248723 当前服务器存储items占用的字节数 
    threads: 1 当前线程数 
    get_misses: 82 总未命中次数 
    pointer_size: 32 当前操作系统的指针大小(32位系统一般是32bit) 
    bytes_read: 490982 总读取字节数(请求字节数) 
    uptime: 161 服务器已经运行的秒数
    curr_connections: 18 当前打开着的连接数 
    pid: 2816 memcache服务器的进程ID 
    bytes_written: 16517259 总发送字节数(结果字节数)
    get_hits: 1563 总命中次数 
    cmd_set: 54 set命令(保存)总请求次数 
    curr_items: 28 服务器当前存储的items数量

    3.一些常用命令

    -p 监听的端口
    -l 连接的IP地址, 默认是本机
    -d start 启动memcached服务
    -d restart 重起memcached服务
    -d stop|shutdown 关闭正在运行的memcached服务
    -d install 安装memcached服务
    -d uninstall 卸载memcached服务
    -u 以的身份运行 (仅在以root运行的时候有效)
    -m 最大内存使用,单位MB。默认64MB
    -M 内存耗尽时返回错误,而不是删除项
    -c 最大同时连接数,默认是1024
    -f 块大小增长因子,默认是1.25
    -n 最小分配空间,key+value+flags默认是48
    -h 显示帮助

    到此整个的memcache安装结束

    那么该怎么样集成到EJB呢?

    客户端调用有两种

    一种是java_memcached-release_2.6.3依赖于此包

    二种是alisoft-xplatform-asf-cache-2.5.1依赖于此包

    我选择的是第二种原因是阿里软件的架构师岑文初进行封装的。里面的注释都是中文的,比较好详情http://www.infoq.com/cn/articles/memcached-java

    重点我就讲这种结合EJB的使用

    首先对xxxEJB引入alisoft-xplatform-asf-cache-2.5.1.jar

    然后配置memcache.xml文件 记住一定要放在classpath下否则找不到

    <memcached>
        <!--memcached Client的配置,也就是一个IMemcachedCache的配置。Name必须填,表示Cache的名称,socketpool必须填,
        表示使用的远程通信连接池是哪一个,参看后面对于socketpool的定义。后面都是可选的,第三个参数表示传输的时候是否压缩,第四个参数表示默认的编码方式 -->
     <client name="mclient1" socketpool="pool1" compressEnable="true" defaultEncoding="UTF-8" >
            <!--errorHandler></errorHandler可定义错误处理类,一般不需要定义 -->
        </client>
        <client name="mclient2" socketpool="pool2" compressEnable="true" defaultEncoding="UTF-8" >
        </client> 
         <!--socketpool是通信连接池定义,每一个memcached Client要和服务端交互都必须有通信连接池作为底层数据通信的支持,name必填,表示名字,
         同时也是memcached client指定socketpool的依据,failover表示对于服务器出现问题时的自动修复。
         initConn初始的时候连接数,minConn表示最小闲置连接数,maxConn最大连接数,maintSleep表示是否需要延时结束(最好设置为0,如果设置延时的话那么就不能够立刻回收所有的资源,
         如果此时从新启动同样的资源分配,就会出现问题),nagle是TCP对于socket创建的算法,socketTO是socket连接超时时间,aliveCheck表示心跳检查,确定服务器的状态。
         Servers是memcached服务端开的地址和ip列表字符串,weights是上面服务器的权重,必须数量一致,否则权重无效  -->
        <socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.1.137:11211</servers>
            <weights>5</weights>
        </socketpool> 
        <socketpool name="pool2" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.0.53:11211</servers>
            <weights>5</weights>
        </socketpool>
         <!--虚拟集群设置,这里将几个client的cache设置为一个虚拟集群,当对这些IMemcachedCache作集群操作的时候,就会自动地对集群中所有的Cache作插入,寻找以及删除的操作,做一个虚拟交互备份  -->
        <cluster name="cluster1">
            <memCachedClients>mclient1,mclient2</memCachedClients>
        </cluster>           
    </memcached>

    然后创建一个类进行对象初始化

     //缓存管理器变量 
        private ICacheManager manager; 
        //缓存变量 
        private IMemcachedCache cache; 
         
        //缓存名称 
        /********************************单例模式(饿汉式)  begin***********************************************/ 
         
        private  static CacheHandler cacheHandler=new CacheHandler(); 
        /**
         * 私有构造函数
         */ 
        private CacheHandler(){ 
            System.out.println("---------------创建单例 begin--------------"); 
            initCache(); 
            System.out.println("---------------创建单例 end--------------"); 
        } 
        public static CacheHandler getInstance(){ 
            return cacheHandler; 
        } 
        /********************************单例模式(饿汉式)  end***********************************************/ 
         
        /**
         * @MethodName  : initCache
         * @Description : 初始化缓存
         */ 
        private void initCache(){ 
            //1.创建cachemanager 
         manager=CacheUtil.getCacheManager(IMemcachedCache.class,MemcachedCacheManager.class.getName());;
            //如果cache是空,則手動創建 
            if(cache==null){ 
       manager.start();
       cache = (IMemcachedCache) manager.getCache("mclient1");
            } 
        } 
        /**
         * @MethodName  : getCache
         * @Description : 外部通过get方法拿到cache后,可清空cache
         * @return
         */ 
        public IMemcachedCache getCache() { 
            return cache; 
        } 
        
        /**
         * @MethodName  : clearCache
         * @Description : 清理缓存
         */ 
        public void clearCache(){ 
            if(cache!=null){ 
                cache.clear();
            } 
        }

    因为我是测试 所以利用EJB的拦截器

    首先创建一个类对查询的方法进行缓存

    @AroundInvoke 
        public Object processCache(InvocationContext context) throws Exception{ 
            String targetName = context.getTarget().getClass().getName(); 
            String methodName = context.getMethod().getName(); 
            Object[] arguments =context.getParameters(); 
            Object result; 
            //获取缓存对象 
            IMemcachedCache cache = CacheHandler.getInstance().getCache(); 
            //如果方法名以find、query、或get开头则执行缓存策略 
            if(methodName.startsWith("find") || methodName.startsWith("get") || methodName.startsWith("query")){ 
                String cacheKey = getCacheKey(targetName, methodName, arguments); 
                Object element = cache.get(cacheKey); 
                if (element == null) { 
                    result = context.proceed(); // 执行目标方法,并保存目标方法执行后的返回值 
                    cache.put(cacheKey, result);
                    element=result;
                    System.out.println("==========================createCache-->" + cacheKey); 
                } else { 
                    System.out.println("==========================hit Cache-->" + cacheKey); 
                } 
                return element; 
            } 
             
            //否则直接执行目标方法 
            return context.proceed(); 
        } 
         
        /**
         * @MethodName  : getCacheKey
         * @Description : 获得cache key的方法,cache key是Cache中一个Element的唯一标识 cache key包括
         * 包名+类名+方法名+各个参数的具体指,如com.jiwu.service.UserServiceImpl.getAllUser
         * @param targetName    类名
         * @param methodName    方法名
         * @param arguments     方法实参数组
         * @return                      cachekey
         */ 
        private String getCacheKey(String targetName, String methodName, 
                Object[] arguments) { 
            StringBuffer sb = new StringBuffer(); 
            sb.append(targetName).append(".").append(methodName); 
            if ((arguments != null) && (arguments.length != 0)) { 
                for (int i = 0; i < arguments.length; i++) { 
                    if(arguments[i] instanceof String[]){ 
                        String[] strArray = (String[])arguments[i]; 
                        sb.append("."); 
                        for(String str : strArray){ 
                            sb.append(str); 
                        } 
                    }else{ 
                        sb.append(".").append(arguments[i]); 
                    } 
                     
                } 
            } 
             
            return sb.toString(); 
        }

    然后manager引用的时候 只要在类上引用即可 例如以下

    @Interceptors(CacheInterceptor.class)
    public class AdminManagerImpl implements IAdminManager

    这样的话就会对该类中所有的find,get,query 开始的方法进行拦截 缓存

    由此整个EJB和memcache已关联,部署的时候还需要在deploy 同等目录的LIB下放入引用alisoft-xplatform-asf-cache-2.5.1.jar

    OK启动你的JBOSS 打上你的断点看是否已经成功

  • 相关阅读:
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 获取指定进程的输入命令行
    dotnet 获取指定进程的输入命令行
    PHP sqrt() 函数
    PHP sinh() 函数
    PHP sin() 函数
    PHP round() 函数
  • 原文地址:https://www.cnblogs.com/jiwuyf/p/3795865.html
Copyright © 2011-2022 走看看