• php和java的memcached使用的兼容性问题解决过程


    1. 背景:

      php 使用memcached客户端设置一个key,java使用java-memcached-client去读,报错如下:

    ERROR|com.whalin.MemCached.MemCachedClient:-1|++++ exception thrown while trying to get object from cache for key: glt7hpcdi1ggo03l9qknu8a755

    2. 网上搜索,发现最多的解释:

       在memcached中,不同的客户端在set或者add值时,对命令的第二个参数的使用是不一致的
    <command name> <key> <flags> <exptime> <bytes>
    <data block>
    JAVA客户端flags字段填写的都是32,不是32的是无法通过java客户端get出来的
    所以在通过memcached admin进行数据set时,需要显示指定flags值为32
    set testkey 32 0 5
    12345
    如此放入缓存后,通过java客户端是可以取出来的。
     
    3. 可选的解决方案,1)从php端设置flag 2)从java端取的时候使用flag 3)使用别的客户端绕过这个障碍 。方案1,php端没有封装php的memcached客户端,调用在系统中随处可见,故该方案不可行,最起码风险比较大,成本高。方案2,研究了一下使用的memcached客户端,没法发现使用flag标示的地方,本身客户端如果自己去写的话,风险也不小。方案3,网上有人提到过使用spy memcached client可以避过,故尝试一下。
    4. 解决步骤:
      

    4.0. 增加spymemcached依赖

                <dependency> <groupId>net.spy</groupId> <artifactId>spymemcached</artifactId> <version>2.12.0</version> </dependency>

    4.1. 配置memcached的ip地址

       分别在dev,test,idc,prod的app-config.properties文件下添加memcached的ip地址:

       dev,test:memcache_ip=192.168.1.10:11211

      idc:memcache_ip=172.16.4.10:11211

     prod:memcache_ip=172.16.0.10:11211

     

    4.2. 配置memcached实例:

    app-cached.xml文件增加:

    <bean id="springContextHolder" class="com.test.bean.SpringContextHolder" /> <bean id="memcachedClient" class="net.spy.memcached.spring.MemcachedClientFactoryBean">      <property name="servers" value="${memcache_ip}"/>      <property name="protocol" value="BINARY"/>      <property name="transcoder">        <bean class="net.spy.memcached.transcoders.SerializingTranscoder">          <property name="compressionThreshold" value="1024"/>        </bean>      </property>      <property name="opTimeout" value="1000"/>      <property name="timeoutExceptionThreshold" value="1998"/>      <property name="useNagleAlgorithm" value="false"/>    </bean>

     

    4.3. 新增类SpringContextHolder

    import java.util.Map;
    import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;
    /** *  * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext. **/
    public class SpringContextHolder implements ApplicationContextAware {
     private static ApplicationContext applicationContext;
     /** *  * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. */
     public void setApplicationContext(ApplicationContext applicationContext) {
     SpringContextHolder.applicationContext = applicationContext;
     }
     /** *  * 取得存储在静态变量中的ApplicationContext. */
     public static ApplicationContext getApplicationContext() {
     checkApplicationContext();
     return applicationContext;
     }
     /** *  * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. */
     @SuppressWarnings("unchecked") public static <T> T getBean(String name) {
     checkApplicationContext();
     return (T) applicationContext.getBean(name);
     }
     /** *  * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. *  * 如果有多个Bean符合Class, 取出第一个. */
     @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) {
     checkApplicationContext();
     Map beanMaps = applicationContext.getBeansOfType(clazz);
     if (beanMaps != null && !beanMaps.isEmpty()) {
     return (T) beanMaps.values().iterator().next();
     } else {
     return null;
     }
     }
     private static void checkApplicationContext() {
     if (applicationContext == null) {
     throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
     }
     }
    }

    4.4.增加MemcacheUtil 

    import com.test.bean.SpringContextHolder;import net.spy.memcached.MemcachedClient;
    public class MemcacheUtil {    public static MemcachedClient getMemCachedClient() {        return SpringContextHolder.getBean("memcachedClient");}}

     

    4.5 测试代码

    public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "classpath:spring-memcached-spy.xml"); MemcachedClient client=MemcacheUtil.getMemCachedClient();  //MemcachedClient client =(MemcachedClient)context.getBean("memcachedClient"); Object obj=client.get("glt7hpcdi1ggo03l9qknu8a755");  System.out.println(obj); }

    注意事项:

    使用spy memcached客户端,在key-value对中,如果value是对象的话,则读取不到,是string的话则可以读取。故建议使用时key-value约定为string类型。value为对象的话,可以考虑转成json串。

     
  • 相关阅读:
    【分治法】线性时间选择(转)
    【分治法】最接近点对问题(转)
    概率DP入门总结 16题(转)
    动态规划初探及什么是无后效性? (转)
    第15章DP(转)
    整数快速乘法/快速幂+矩阵快速幂+Strassen算法 (转)
    矩阵乘法的理解(转)
    算法导论第4章习题与思考题(转)
    Transaction Script模式
    注册服务
  • 原文地址:https://www.cnblogs.com/davidwang456/p/5229871.html
Copyright © 2020-2023  润新知