为了账号安全,请及时绑定邮箱和手机立即绑定

Java操作Redis(一)

标签:
Java NoSql Redis

https://img1.sycdn.imooc.com//5d41b0640001587906660958.jpg

Java客户端Jedis集成了Redis的相关命令操作,它是Java语言操作Redis数据库的桥梁。

一、Jedis的获取

在项目的pom.xml文件中引入Jedis依赖,最新版本是3.1.0,如下:

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.1.0</version>
</dependency>


二、Jedis的使用

1、 连接Redis数据库,代码如下:

import redis.clients.jedis.Jedis;
/**
 * Java客户端Jedis连接Redis数据库
 * 
 * @author liuhefei
 * 2018年9月16日
 */
public class JedisTest {
    public static void main(String[] args) {
        //创建Jedis实例,连接本地Redis服务
        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println("连接成功");
        //查看服务是否运行
        System.out.println("服务正在运行: "+jedis.ping());
    }
}

2、Jedis常用API,代码如下:

import redis.clients.jedis.Jedis;
/**
 * Jedis API操作实例
 * 
 * @author liuhefei
 * 2018年9月16日
 */
public class JedisAPITest {
    public static void main(String[] args) {
        //创建Jedis实例,连接Redis本地服务
        Jedis jedis = new Jedis("127.0.0.1",6379);
        //设置Redis数据库的密码
        //System.out.println(jedis.auth("123456"));
        //获取客户端信息
        System.out.println(jedis.getClient());
        //清空Redis数据库,相当于执行FLUSHALL命令
        System.out.println(jedis.flushAll());
        //查看Redis信息,相当于执行INFO命令
        System.out.println(jedis.info());
        //获取数据库中key的数量,相当于执行DBSIZE命令
        System.out.println(jedis.dbSize());
        //获取数据库名字
        System.out.println(jedis.getDB());
        //返回当前Redis服务器的时间,相当于执行TIME命令
        System.out.println(jedis.time());
    }
}

3、Jedis事务

开启Redis事务的步骤:

(1)使用MULTI命令开启事务

(2)事务命令入队

(3)使用EXEC命令执行事务

实例代码1,如下:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
/**
 * Jedis事务
 * 
 * @author liuhefei
 * 2018年9月16日
 */
public class Jedis_TransactionTest {
    public static void main(String[] args) {
        //创建Jedis实例,连接Redis本地服务
        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println("开启Redis事务");
        //1.使用MULTI命令开启事务
        Transaction transaction = jedis.multi();
        //2.事务命令入队
        transaction.set("userName", "liuhefei"); //设置键userName
        transaction.set("age", "24");  //设置键age
        transaction.set("city", "shenzhen");  //设置键city
        transaction.get("userName");  //获取键userName的值
        //将userName键所存储的值加上增量5,将会报错,事务执行失败
        //原因是:值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误
        transaction.incrBy("userName", 5);  
        //将age键所存储的值加上增量5,事务正确执行
        transaction.incrBy("age", 5);
        //3.使用EXEC命令执行事务
        transaction.exec();
        //取消执行事务
        //transaction.discard();
        System.out.println("Redis事务执行结束");
        //获取事务中的值
        System.out.println("用户名:"+jedis.get("userName"));
        System.out.println("年龄:"+jedis.get("age"));
        System.out.println("所在城市:"+jedis.get("city"));
    }
}

实例代码2,如下:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
/**
 * Jedis事务
 * 假如我的银行卡中余额是100,我要购买一本价值40元的图书和一个价值70的书包, 
 * 先去购买图书,购买之后,我的余额为60,
 * 再去购买书包,此时将会购买失败,因为银行卡余额不足,导致购买失败
 * 
 * 付款方是账户A,收款方是账户B
 * 
 * @author liuhefei 2018年9月16日
 */
public class Jedis_TransactionTest1 {
    // 创建Jedis实例
    private static Jedis jedis = new Jedis("127.0.0.1", 6379);
    /**
    * 购物
    * 
    * @param goodsName 购买的商品名称
    * @param balanceA 付款方余额
    * @param price 购买的商品价格
    * @param balanceB 收款方余额
    * @return
    * @throws InterruptedException
    * 
    * @author liuhefei 2018年9月16日
    */
    public boolean shopping(String goodsName, int balanceA, int price, int balanceB) throws InterruptedException {
        // 使用WATCH命令监视balanceA键
        jedis.watch("balanceA");
        // 获取Redis数据库中balanceA键的值,并转化为整形
        balanceA = Integer.parseInt(jedis.get("balanceA"));
        // 如果付款方余额小于所要购买的图书价格,则取消balanceA键的监控,提示余额不足,图书购买失败
        if (balanceA < price) {
            jedis.unwatch();
            System.out.println("余额不足,购买" + goodsName + "失败");
            return false;
        } else {
            System.out.println("*******开始购物*********");
            System.out.println("购买:" + goodsName);
            // 1.使用MULTI命令开启事务
            Transaction transaction = jedis.multi();
            // 2.事务命令入队
            transaction.decrBy("balanceA", price); // 付款方余额减去支付的金额
            transaction.incrBy("balanceB", price); // 收款方余额加上支付的金额
            // 3.使用EXEC命令执行事务
            transaction.exec();
            // 购买成功之后
            balanceA = Integer.parseInt(jedis.get("balanceA"));
            balanceB = Integer.parseInt(jedis.get("balanceB"));
            System.out.println(goodsName + "购买成功");
            System.out.println("付款方余额: " + balanceA);
            System.out.println("收款方余额: " + balanceB);
            
            return true;
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Jedis_TransactionTest1 goShopping = new Jedis_TransactionTest1();
        int balanceA = 0; // 付款方账户余额
        int balanceB = 0; // 收款方账户余额
        int bookPrice = 40; // 图书价格
        int bagPricae = 70; // 书包价格
        String goodsName1 = "图书";
        String goodsName2 = "书包";
        // 初始化银行卡余额为100
        jedis.set("balanceA", "100");
        
        System.out.println("去购买图书");
        goShopping.shopping(goodsName1, balanceA, bookPrice, balanceB);
        System.out.println("\n\n去购买书包");
        goShopping.shopping(goodsName2, balanceA, bagPricae, balanceB);
    }
}

4、Jedis主从复制

windows环境下:

Redis的安装目录结构如下图:

https://img1.sycdn.imooc.com//5d41ad710001634e10810962.jpg

复制两份redis.windows.conf文件,分别命名为:redis.windows-6379.conf和redis.windows-6380.conf,然后修改redis.windows-6380.conf文件中的端口信息为6380。

cmd命令进入Redis的安装目录下,开启两个窗口,分别执行以下命令启动这两个Redis服务,命令如下:

./redis-server 'D:\softPackage\redis\redis.windows - 6379.conf'

./redis-server 'D:\softPackage\redis\redis.windows - 6380.conf'

再开启两个新窗口,执行以下命令进入服务的客户端,命令如下:

./redis-cli -p 6379

./redis-cli -p 6380


当两个Redis服务都成功启动之后,执行以下Java代码,实现一个简单的主从复制功能,Jedis_MasterSlaveTest.java代码如下:

import redis.clients.jedis.Jedis;
/**
 * jedis实现主从复制
 * 
 * 
 * @author liuhefei
 * 2018年9月16日
 */
public class Jedis_MasterSlaveTest {

    public static void main(String[] args) {
        //创建Jedis实例,连接Redis本地服务
        Jedis jedis_master = new Jedis("127.0.0.1",6379);
        Jedis jedis_slave = new Jedis("127.0.0.1",6380);
        
        //设置6379服务器为主节点,使得6380为从节点
        jedis_slave.slaveof("127.0.0.1", 6379);
        //主节点写数据
        jedis_master.set("userName", "liuhefei");
        jedis_master.set("age", "24");
        //从节点读数据
        String userName = jedis_slave.get("userName");
        String age = jedis_slave.get("age");
        System.out.println("userName:"+userName+" ,age: " + age);
    }
}

5、Jedis连接池

Jedis pool工具类代码如下:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
 * Jedis连接池
 * 
 * 
 * @author liuhefei 2018年9月16日
 */
public class JedisPoolUtils {

    // Redis服务器IP
    private static String ADDR = "127.0.0.1";
    // Redis的端口号
    private static int PORT = 6379;
    // 可用连接实例的最大数目,默认值为8;
    // 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 1024;
    // 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 200;
    // 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 10000;
    // 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;
    //return 一个jedis实例给pool时,是否检查连接可用性(ping())
    private static boolean TEST_ON_RETURN = true;
    private static JedisPool jedisPool = null;
    
    /**
    * 初始化Redis连接池
    */
    public static JedisPool getJedisPoolInstance(){
        if(null == jedisPool){
            //同步锁
            synchronized (JedisPoolUtils.class)
            {
                if(null == jedisPool)
                {
                    //jedis连接池的配置
                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    poolConfig.setMaxTotal(MAX_ACTIVE);
                    poolConfig.setMaxIdle(MAX_IDLE);
                    poolConfig.setMaxWaitMillis(MAX_WAIT);
                    poolConfig.setTestOnBorrow(TEST_ON_BORROW);
                    poolConfig.setTestOnReturn(TEST_ON_RETURN);
                    jedisPool = new JedisPool(poolConfig, ADDR, PORT);
                }
            }
        }
        return jedisPool;
    }
    
    /**
    * 获取Jedis实例
    * 
    * @return
    */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
    * 释放jedis资源
    * 
    * @param jedis
    */
    public static void releaseResource(final Jedis jedis) {
        if (jedis != null) {
             jedisPool.close();
        }
      }
      
      public static void main(String[] args) {
        JedisPool jedisPool = JedisPoolUtils.getJedisPoolInstance();
        JedisPool jedisPool2 = JedisPoolUtils.getJedisPoolInstance();
        System.out.println(jedisPool == jedisPool2);
        Jedis jedis = null;
        try {
            //获取Jedis实例
            jedis = JedisPoolUtils.getJedis();
            jedis.set("message","Redis连接池");
            System.out.println(jedis.get("message"));
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //释放Jedis连接资源
            JedisPoolUtils.releaseResource(jedis);
        }
    }
}

本文来源于:《从零开始学Redis》高洪涛 刘河飞 编著

未完,待续!

点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.5万
获赞与收藏
8507

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消