使用图形化界面和Jedis操作redis

图形化界面

图形界面的客户端Redis Desktop Manager,可以看到每个redis里边存了多少key

jedis的使用

在content-service的pom中添加对jedis的依赖

建一个测试类cn.e3mall.jedis.JedisTest

public class JedisTest {

    /**
     * 连接单机版
     * @throws Exception
     */
    @Test
    public void testJedis() throws Exception{
        //创建一个链接Jedis对象,参数:host,port
        Jedis jedis=new Jedis("192.168.25.130",6379);
        //直接使用jedis操作redis,所有jedis的命令都对应一个方法
        jedis.set("test123","my first jedis test");
        String string=jedis.get("test123");
        System.out.println(string);
        //关闭连接
        jedis.close();

    }


    /**
     * 连接单机版,用连接池
     * @throws Exception
     */
    @Test
    public void testJedisPool() throws Exception{
        //创建一个连接池对象,两个参数host,port
        JedisPool jedisPool=new JedisPool("192.168.25.130",6379);
        //从连接池获得一个连接,就是一个jedis对象
        Jedis jedis=jedisPool.getResource();
        //使用jedis操作redis
        String string=jedis.get("test123");
        System.out.println(string);
        //关闭连接,每次使用完后关闭连接。连接池回收资源
        jedis.close();
        //关闭连接池
        jedisPool.close();
    }


    /**
     * 操作redis集群
     * @throws Exception
     */
    @Test
    public void testJedisCluster()throws Exception{
        //创建一个JedisCluster对象。他自带连接池。有一个参数nodes是一个set类型。set中包含若干个HostAndPort对象
        Set<HostAndPort> nodes=new HashSet<>();
        nodes.add(new HostAndPort("192.168.25.130",7001));
        nodes.add(new HostAndPort("192.168.25.130",7002));
        nodes.add(new HostAndPort("192.168.25.130",7003));
        nodes.add(new HostAndPort("192.168.25.130",7004));
        nodes.add(new HostAndPort("192.168.25.130",7005));
        nodes.add(new HostAndPort("192.168.25.130",7006));

        JedisCluster jedisCluster=new JedisCluster(nodes);
        //直接使用jedisCluster对象操作jedis
        jedisCluster.set("test","123");
        String string=jedisCluster.get("test");
        System.out.println(string);
        //关闭JedisCluster对象
        jedisCluster.close();
    }

}

现在有单机版和集群版,那我们平时开发的时候用单机版还是集群版呢,平时开发的时候用单机版就可以了,没必要弄六七台服务器就为连个redis,等上线的时候再用集群版。

但发现操作集群版和单机版用的代码不一样啊,到时候切换的时候会很麻烦。

怎么才能不改代码呢?

面向接口编程

之前写dao层的时候为啥要先写一个接口再写实现类呢,就是为了以后如果要改实现类的话直接切换过去就行了。
现在定义一个接口,我们用的时候用这个接口,到时候具体用哪个实现类在spring的配置文件中配置一下就行了。以后切换单机和集群的收代码就不用动了,修改配置文件就可以了。

接口JedisClient

public interface JedisClient {

    String set(String key, String value);
    String get(String key);
    Boolean exists(String key);
    Long expire(String key, int seconds);
    Long ttl(String key);
    Long incr(String key);
    Long hset(String key, String field, String value);
    String hget(String key, String field);
    Long hdel(String key, String... field);
}

单机版工具类,JedisClientPool

public class JedisClientPool implements JedisClient {

    private JedisPool jedisPool;

    public void setJedisPool(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    @Override
    public String set(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.set(key, value);
        jedis.close();
        return result;
    }

    @Override
    public String get(String key) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get(key);
        jedis.close();
        return result;
    }

    @Override
    public Boolean exists(String key) {
        Jedis jedis = jedisPool.getResource();
        Boolean result = jedis.exists(key);
        jedis.close();
        return result;
    }

    @Override
    public Long expire(String key, int seconds) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.expire(key, seconds);
        jedis.close();
        return result;
    }

    @Override
    public Long ttl(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.ttl(key);
        jedis.close();
        return result;
    }

    @Override
    public Long incr(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.incr(key);
        jedis.close();
        return result;
    }

    @Override
    public Long hset(String key, String field, String value) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hset(key, field, value);
        jedis.close();
        return result;
    }

    @Override
    public String hget(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.hget(key, field);
        jedis.close();
        return result;
    }

    @Override
    public Long hdel(String key, String... field) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hdel(key, field);
        jedis.close();
        return result;
    }

}

集群版工具类

public class JedisClientCluster implements JedisClient {


    private JedisCluster jedisCluster;

    public void setJedisCluster(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }

    @Override
    public String set(String key, String value) {
        return jedisCluster.set(key, value);
    }

    @Override
    public String get(String key) {
        return jedisCluster.get(key);
    }

    @Override
    public Boolean exists(String key) {
        return jedisCluster.exists(key);
    }

    @Override
    public Long expire(String key, int seconds) {
        return jedisCluster.expire(key, seconds);
    }

    @Override
    public Long ttl(String key) {
        return jedisCluster.ttl(key);
    }

    @Override
    public Long incr(String key) {
        return jedisCluster.incr(key);
    }

    @Override
    public Long hset(String key, String field, String value) {
        return jedisCluster.hset(key, field, value);
    }

    @Override
    public String hget(String key, String field) {
        return jedisCluster.hget(key, field);
    }

    @Override
    public Long hdel(String key, String... field) {
        return jedisCluster.hdel(key, field);
    }

}

把这三个类添加到common的cn.e3mall.common.jedis包中

然后把content的pom文件中对jedis的依赖剪切到common的pom中

再在content的cn.e3mall.jedis中建立一个测试类JedisClientTest

public class JedisClientTest {

    @Test
    public void testJedisClient()throws Exception{
        //初始化spring容器
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
        //从容器中获得JedisClient对象
        JedisClient jedisClient=applicationContext.getBean(JedisClient.class);
        jedisClient.set("mytest","jedisClient");
        String string=jedisClient.get("mytest");
        System.out.println(string);
    }
}

在其spring目录下建立一个配置文件applicationContent-reids.xml,用哪个实现类就把哪个的注释解开,代码不用变。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

    <!--连接jedis单机版-->
    <!--<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">-->
        <!--<property name="jedisPool" ref="jedisPool"/>-->
    <!--</bean>-->

    <!--<bean id="jedisPool" class="redis.clients.jedis.JedisPool">-->
        <!--<constructor-arg name="host" value="192.168.25.130"/>-->
        <!--<constructor-arg name="port" value="6379"/>-->
    <!--</bean>-->

    <!--连接redis集群-->
    <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
        <property name="jedisCluster" ref="jedisCluster"/>
    </bean>

    <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.130"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean>
            </set>
        </constructor-arg>
    </bean>

</beans>

在项目中加缓存

推荐加在服务层,因为以后只要调用了这个服务就有缓存。

修改content-service的contentServiceImpl.java中的getContentListByCid方法

@Autowired
private JedisClient jedisClient;

@Value("${CONTENT_LIST}")
private String CONTENT_LIST;

 @Override
    public List<TbContent> getContentListByCid(long cid) {
        /*
        查询缓存和添加结果到缓存出错了都不应该报错,应该try-catch
        因为不用缓存也可以正常使用。出错之后不应该影响正常的逻辑。但应该打印一下日志
         */
        //查询缓存
        try {
            //如果缓存中有直接响应结果
            String json=jedisClient.hget(CONTENT_LIST,cid+"");
            if(StringUtil.isNotEmpty(json)){
                List<TbContent> list=JsonUtils.jsonToList(json,TbContent.class);
                return list;
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        //如果没有查询数据库
        TbContentExample example=new TbContentExample();
        TbContentExample.Criteria criteria=example.createCriteria();
        criteria.andCategoryIdEqualTo(cid);
        List<TbContent> tbContents = contentMapper.selectByExampleWithBLOBs(example);
        //把结果添加到缓存
        /*
            我会将一堆东西都存入redis中。我应该分一下类。
            用哈希,大key为CONTENT_LIST,field为cid,value为List<TbContent>
            这里把CONTENT_LIST存到了配置文件中resource.properties,然后我要加载这个配置文件,但
            <context:property-placeholder location="classpath:conf/*.properties" />,这个只能写一个,
            于是就改成了*.properties
         */
        try {
            jedisClient.hset(CONTENT_LIST,cid+"", JsonUtils.objectToJson(tbContents));

        }catch (Exception e){
            e.printStackTrace();
        }

        return tbContents;
    }

添加一个conf/resource.properties

#内容列表在redis中缓存的key
CONTENT_LIST=CONTENT_LIST

修改applicationContent-dao.xml

<!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:conf/*.properties" />

缓存同步

问题,比如我更改了 数据库,但是缓存中没改,下次查还是从缓存中查,那查出来的结果还是以前的。

解决方案:每次更改了数据库后都把相应的缓存中的东西删除。这样缓存中没有了,下次查的时候就会去数据库中查了,然后再添加新的缓存数据。

更改content-service中ContentServiceImpl.java中的addContent方法

@Override
    public TaotaoResult addContent(TbContent content) {
        //将内容插入到内容表
        content.setCreated(new Date());
        content.setUpdated(new Date());
        //插入到数据库
        contentMapper.insert(content);
        //缓存同步,删除缓存中对应的数据
        jedisClient.hdel(CONTENT_LIST,content.getCategoryId().toString());
        return TaotaoResult.ok();
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值