Redis学习_第三章(Redis的基本操作和Redis数据连接池java实现)

目录

 

1:redis基本操作

1.1:redis命令操作

1.2:代码操作

2:redis连接池

2.1引入jar包

2.2 redis.properties配置文件

2.3 连接池代码通用代码

2.4多线程类

2.4测试方法

2.5输出结果和分析


1:redis基本操作

我们知道Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

无论是在windows后者是lunix环境上安装好redis后,我们对redis进行操作一般有两种方,

1.1:redis命令操作

这一种操作一般用于对redis进行一些查询,bug追踪,实施人员维护查询等等情况吧,对于程序开发来说,不采用这种方法,但是这种方法也有自己在特殊情况的用途

String操作方法如下:其他方法类似,如果想详细了解命令的操作方法,请参考Redis 数据类型 | 菜鸟教程

实例:

redis 127.0.0.1:6379> SET name "runoob"
OK
redis 127.0.0.1:6379> GET name
"runoob"

1.2:代码操作

代码操作,主要介绍Java代码操作redis,这种方式是程序开发的主流

在代码中引入maven依赖

    <!-- redis依赖jar -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.1</version>
    </dependency>

代码操作如下:

package com.thit.redis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;

public class Test1 {
	
	private Jedis jedis=null;
	@Before
	public void initJedis(){
		//连接本地的 Redis 服务 默认端口号是6379
		//阿里云地址
		jedis=new Jedis("地址", 6379);
		//jedis.auth("123456");
		System.out.print("连接成功:");
		System.out.println(jedis.ping());
	}
	
	/**
	 * string类型数据的增删改查
	 */
	@Test
	public void Stringtest(){
		//新增
		jedis.set("name", "张三");
		jedis.set("name1", "李四");
		System.out.println("redis存储的字符串为:"+jedis.get("name"));
	    System.out.println("redis存储的字符串为:"+jedis.get("name1"));
	    
	    //修改拼接键
	    jedis.append("name", "今年18岁!");
	    System.out.println("redis存储的字符串为:"+jedis.get("name"));

	    //设置过期时间
		jedis.expire("name", 10);//设置过期时间  以秒为单位
		//直接删除
		jedis.del("name");
		System.out.println("redis存储的字符串为:"+jedis.get("name"));
	}
//	连接成功
//	PONG
//	redis存储的字符串为:张三
//	redis存储的字符串为:李四
//	redis存储的字符串为:张三今年18岁!
//	redis存储的字符串为:null

	/**
	 * list类型数据的增删改查
	 * 
	 */
	@Test
	public void Listtest(){
		//不删除的话list会不断插入重复元素
		jedis.del("list1");
		//新增
		jedis.lpush("list1", "尼克.罗宾","女","28.5","西西里岛");
		//修改
		System.out.println("获取Lisi数据的移除并且获取第一个元素:"+jedis.lpop("list1"));
		//在头部添加元素
		jedis.lpushx("list1", "在头部插入太元素");
		jedis.lpush("list1", "在头部插入太元素1","在头部插入太元素2");
		//获取数据
		System.out.println("获取Lisi数据长度:"+jedis.llen("list1"));
		System.out.println("获取Lisi数据"+jedis.lrange("list1", 0, -1));
	}
//	连接成功:PONG
//	获取Lisi数据的移除并且获取第一个元素:西西里岛
//	获取Lisi数据长度:6
//	获取Lisi数据[在头部插入太元素2, 在头部插入太元素1, 在头部插入太元素, 28.5, 女, 尼克.罗宾]

	/**
	 * hash类型数据的增删改查
	 */
	@Test
	public void Hashtest(){
		
		//新增
		Map<String, String> map=new HashMap<String, String>();
		map.put("name", "张全蛋");
		map.put("address", "北京海淀区");
		map.put("phone", "113788849231");
		map.put("sex", "男");
		jedis.hmset("hash1", map);
		
		System.out.println("返回散列中的条目:"+jedis.hlen("hash1"));
		System.out.println("返回key是够存在:"+jedis.exists("hash1"));
        System.out.println("user对象中的所有key-set:" + jedis.hkeys("hash1"));//返回user对象中的所有key
        System.out.println("user对象中的所有value-list:" + jedis.hvals("hash1"));//返回map对象中的所有value


		
		//获取得到hash的单个值和获取多个值
		System.out.println(jedis.hget("hash1", "name"));
		List<String> ls=jedis.hmget("hash1", "address","phone","sex");
		for (String string : ls) {
			System.out.println("个人信息:"+string);
		}
		//删除map里面的某一个值
		System.out.println("address删除前:"+jedis.hget("hash1", "address"));
		jedis.hdel("hash1", "address");
		System.out.println("address删除后:"+jedis.hget("hash1", "address"));
		//删除整个key的所有值
		jedis.del("hash1");
		System.out.println("hash1删除后:"+jedis.hget("hash1", "name"));
	}
	
//	返回散列中的条目:4
//	返回key是够存在:true
//	user对象中的所有key-set:[name, address, phone, sex]
//	user对象中的所有value-list:[张全蛋, 男, 北京海淀区, 113788849231]
//	张全蛋
//	个人信息:北京海淀区
//	个人信息:113788849231
//	个人信息:男
//	address删除前:北京海淀区
//	address删除后:null
//	hash1删除后:null
	
	
	
	
	 /**
     * jedis操作Set
     * set具有无序性。存储无序数据
     */
    @Test
    public void Settest(){
        //添加
        jedis.sadd("set1", "茉莉","88元","中国","秋季","花香","温室");
        //获取set的值
        System.out.println("获取set的值:"+jedis.smembers("set1"));
        //查询长度
        System.out.println("获取set的值:"+jedis.scard("set1"));
        //移除指定元素
        jedis.srem("set1", "茉莉");
        System.out.println("获取set的值:"+jedis.smembers("set1"));
    }
    
//    连接成功:PONG
//    获取set的值:[茉莉, 花香, 88元, 中国, 温室, 秋季]
//    获取set的值:6
//    获取set的值:[花香, 88元, 中国, 温室, 秋季]

    
    
	 /**
     * jedis操作sorted set
     * set具有无序性。存储无序数据
     * Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
		不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
		有序集合的成员是唯一的,但分数(score)却可以重复。
		集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
     */
    @Test
    public void sortedSettest(){
        //添加
        jedis.zadd("Zset", 0, "a");
        jedis.zadd("Zset", 3, "b");
        jedis.zadd("Zset", 8, "c");
        jedis.zadd("Zset", 99, "d");
        jedis.zadd("Zset", 7, "a");
       //分值越小 排序越靠前
        System.out.println(jedis.zrange("Zset", 0, 7));//查询
        System.out.println(jedis.zcard("Zset"));//查询长度
    }

}

以上就是jedis代码最】对redis不同数据类型,String、Hash、List、Set、Sorted set的具体操作。

2:redis连接池

我们知道redis是一种key-value形式的内存数据,他的访问速度非常快速高效,我们大量高频发查询的业务情景很多,这种情况下,我们的消耗主要的反复的对redis建立连接的过程,而不是redis连接后的查询过程,所以类比常规数据库,数据库连接池技术就会变得非常必要。

2.1引入jar包

		<!-- redis依赖jar -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.8.1</version>
		</dependency>
		<!-- redispool依赖jar -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
			<version>2.0</version>
		</dependency>

2.2 redis.properties配置文件


#*****************jedis连接参数设置*********************
#redis服务器ip
redis.ip=地址
#redis服务器端口号
redis.port=6379
#redis访问密码
redis.passWord=test123
#与服务器建立连接的超时时间毫秒
redis.timeout=3000
#************************jedis池参数设置*******************
#jedis的最大连接数,连接池在同一时间能够分配的最大活动连接的数量
jedis.pool.MaxTotal=20
#最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,
#表示即使没有数据库连接时依然可以保持10空闲的连接,而不被清除,随时处于待命状态
jedis.pool.maxIdle=10
#连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建,默认值0
jedis.pool.minIdle=0
#初始化连接数:连接池启动时创建的初始化连接数量,默认值0
jedis.pool.initialSize=0

#jedis池没有连接对象返回时,等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。
#如果超过等待时间,则直接抛出JedisConnectionException
jedis.pool.maxWait=3000
#从池中获取连接的时候,是否进行有效检查
jedis.pool.testOnBorrow=true
#归还连接的时候,是否进行有效检查
jedis.pool.testOnReturn=true

2.3 连接池代码通用代码

package com.thit.redis.pool;
import java.io.IOException;
import java.util.Properties;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class Utilpool {
	private static JedisPool jedisPool=null;
	private static String pfile="redis.properties";
	//把redis连接对象放到本地线程中
	private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>();		
	//private修饰  不能通过new来创建类的实例
	private Utilpool() {}
	
	//初始话连接池参数
	static void init() {
		JedisPoolConfig config=new JedisPoolConfig();
		Properties properties=new Properties();
//		String path=Utilpool.class.getClassLoader().getResource("").getPath();
//		System.out.println("类加载路径:"+path);
		try {
			properties.load(Utilpool.class.getClassLoader().getResourceAsStream(pfile));
			//设置连接池最大连接
			config.setMaxTotal(Integer.valueOf(properties.getProperty("jedis.pool.MaxTotal")));
			//最大空闲连接:连接池中保持的最大空闲连接。超过最大连接会被释放
			config.setMaxIdle(Integer.valueOf(properties.getProperty("jedis.pool.maxIdle")));
			config.setMaxWaitMillis(Integer.valueOf(properties.getProperty("jedis.pool.maxWait")));
			jedisPool=new JedisPool(config, properties.getProperty("redis.ip"), Integer.valueOf(properties.getProperty("redis.port")), Integer.valueOf(properties.getProperty("redis.port")), null);		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	
	}
	
	//获取连接
	static Jedis getCon(){
		Jedis jedis =local.get();
		if(jedis==null) {
			if(jedisPool==null) {
				init();
			}
			jedis=jedisPool.getResource();
			local.set(jedis);
		}
		
		return jedis;

	}
	
	//关闭连接
	static void closeCon() {
		//从本地线程获取
		Jedis jedis=local.get();
		if(jedis!=null) {
			jedis.close();
			
		}
		local.set(null);
	}
	
	//关闭连接池
	static void closePool() {
		if(jedisPool!=null) {
			jedisPool.close();
			
		}
	}

	
}

2.4多线程类

便于同时开启50个线程模拟50个用户同时连接redis.

package com.thit.redis.pool;

import java.text.SimpleDateFormat;
import java.util.Date;


import redis.clients.jedis.Jedis;

/**
 * @author 79027
 *  继续Thread类
 */
public class ClientThread extends Thread  {
	 	int i = 0;  
	    public ClientThread(int i) {  
	        this.i = i;  
	    } 
	    //重写run方法
	    public void run() {  
	    	//获取连接
	    	Jedis jedis=Utilpool.getCon();
	        Date date = new Date();  
	        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");  
	        String time = sdf.format(date);  
	        jedis.set("key", time); 
	        try {
	        	String foo = jedis.get("key");        
		        System.out.println("【输出>>>>】key:" + foo + " 第:"+i+"个线程");
	        	//每一个随机休眠5秒,休眠结束关闭连接
				Thread.sleep((int)(Math.random()*5000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally {
				// 关闭连接
				Utilpool.closeCon();
			}
	    }  
}

2.4测试方法

package com.thit.redis.pool;

public class Test1 {
	public static void main(String[] args) {
		//初始化连接池
		System.out.println("=================");
		//初始化连接
		Utilpool.init();
		//同时50个线程进行访问
		for (int i = 0; i < 50; i++) {  
	        ClientThread t = new ClientThread(i); 
	        t.start();
	        } 
	}
		
}

2.5输出结果和分析

输出结果截图如下:

输出结果分析:

【输出>>>>】key:2018-11-23 17:25:32:984 第:12个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:19个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:9个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:10个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:13个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:2个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:6个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:17个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:5个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:15个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:18个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:1个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:14个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:16个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:3个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:8个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:0个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:4个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:7个线程
【输出>>>>】key:2018-11-23 17:25:32:984 第:11个线程

连接池20个链接被快速占满,这20个连接开始睡眠,但是睡眠时间是随机的,后30个链接根据等待时间3秒开始等待,
在这三秒中有的连接睡醒了,连接空闲出来 后三十个连连接中的16个进去了连接池拿到了连接,连接池始终是满的,一直连接睡醒,有连接进去

【输出>>>>】key:2018-11-23 17:25:33:193 第:42个线程
【输出>>>>】key:2018-11-23 17:25:33:284 第:30个线程
【输出>>>>】key:2018-11-23 17:25:33:284 第:28个线程
【输出>>>>】key:2018-11-23 17:25:33:318 第:29个线程
【输出>>>>】key:2018-11-23 17:25:33:624 第:27个线程
【输出>>>>】key:2018-11-23 17:25:33:928 第:25个线程

【输出>>>>】key:2018-11-23 17:25:34:066 第:22个线程
【输出>>>>】key:2018-11-23 17:25:34:231 第:21个线程
【输出>>>>】key:2018-11-23 17:25:34:443 第:23个线程
【输出>>>>】key:2018-11-23 17:25:34:515 第:44个线程
【输出>>>>】key:2018-11-23 17:25:34:991 第:41个线程
【输出>>>>】key:2018-11-23 17:25:34:991 第:20个线程

【输出>>>>】key:2018-11-23 17:25:35:323 第:43个线程
【输出>>>>】key:2018-11-23 17:25:35:417 第:40个线程
【输出>>>>】key:2018-11-23 17:25:35:417 第:39个线程
【输出>>>>】key:2018-11-23 17:25:35:604 第:38个线程
【输出>>>>】key:2018-11-23 17:25:35:604 第:37个线程

此处程序会报错,然后接着输出

三秒等待时间结束,还有14个连接等待超时时间3秒过后,13个程序超时显示报错,
偶尔一个程序在3秒等待时间的最后,有其他的连接释放,此连接进去了,进去时间在17:25:35:984之前


【输出>>>>】key:2018-11-23 17:25:35:902 第:35个线程

此时设置的睡眠时间还没有结束,等待睡眠时间结束,程序结束

注意:因为每次的休眠时间是随机的,所以每一次测试结果都是不同的,上述结果是对本人输出结果的分析。
本文主要参考了:

【Redis】Java中使用Jedis操作Redis(Maven导入包)、创建Redis连接池_谙忆-陈浩翔-CSDN博客_jedis maven

java操作redis(三):实现一个redis连接池并附测试_御前两把刀的专栏-CSDN博客_javaredis连接池

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值