redis的使用:

1)redis相比mysql,速度比较快,用户体验好。

2)不经常变化的数据,可以使用redis存储,比如公司介绍等。

3)在mysql中操作后,存储到数据库中;下次在获取数据的时候,先从redis中查询,如果有就直接获取,如果没有在查询数据库。

4)过期时间设置:过期后,就会删除此条数据;然后数据只能从mysql中查询。

 

redis配置文件:redis.conf   dump.rdb

ShardedJedis:Redis集群客户端对象 

 

1、把用户信息缓存到redis中,Redis 存入对象怎么做到的,把对象属性存入到map集合中,获取的时候从map集合映射成对象。

2、值的数据类型,只能是String类型,怎么会有int类型呢?

3、如何刷redis缓存中的数据?缓存不一致,如何把redis中的数据和mysql中保持一致;单机的话,单线程执行,所以一般都是晚上刷数据,防止影响业务的执行;但是如果是集群Cluster的话,就不存在这个问题。

 

实际开发中的使用:

 

/**
     * 获取配置文件信息
     *
     * @param key
     * @return
     */
    public String getProperties(String key) throws IOException {
        //获取存储的二进制文件,然后进行反序列化成对象
        //把key变成二进制字节码文件,主要用于保密,不让别人识别。
        byte[] bytes = get("app_properties".getBytes());
        Properties pro = (Properties) SerializeUtil.unserialize(bytes);
        if (Utils.isObjectEmpty(pro)) {
            //如果配置文件不存在,就进行创建
            pro = new Properties();
            //加载三个配置文件
            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("resources/smsTemplete.properties"));
            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("resources/rechargeTemplete.properties"));
            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("resources/stationTemplete.properties"));
            SerializeUtil.serialize(pro);
            setex("app_properties".getBytes(), 7200, SerializeUtil.serialize(pro));
            pro = (Properties) SerializeUtil.unserialize(get("app_properties".getBytes()));
            if (key == null) {
                return "";
            } else {
                //从配置文件中读取数据,而非从缓存中读取数据
                return pro.getProperty("key");
            }

        } else {
            if (key == null) {
                return "";
            } else {
                //从配置文件中读取数据,而非从缓存中读取数据
                return pro.getProperty("key");
            }
        }
    }
/**
     * 获取redis中缓存的数据
     * @param key 字节数组(保密作用)
     * @return 自己数组
     */
    public byte[] get(byte[] key){
        byte[] result =null;
        //获取ShardedJedis对象,如果不存在,返回null
        ShardedJedis redisClient = redisDataSource.getRedisClient();
        if (redisClient==null){
            return result;
        }
        boolean broken=false;
        try {
            result = redisClient.get(key);
        }catch (Exception e){
            broken=true;
        }finally {
            redisDataSource.returnResource(redisClient,broken);
        }
        return result;
    }

 

Redis的使用

 

package testRedis;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.ScanResult;

public class TestRedisStudent {

	// 新建web动态项目
	// 通过java程序访问Redis数据库
	// 获取单一的Redis对象来操作数据库
	// 把jedis的操作封装成工具类
	// 在当前里中写main()进行测试
	// 把配置放到配置文件中,配置文件的加载
	// 通过命令行操作Redis语句
	// 如何把redis与具体的项目逻辑结合使用(常用的逻辑)
	// 如何设置缓存的定时刷新? 什么业务需求,如何设置10分钟刷新一次

	@Test
	public void testConnRedis() {
		// 连接到Redis数据库(如果连接超时,可能是网络的问题,也可能是端口没有开)
		Jedis jedis = new Jedis("192.168.1.227", 6379);
		jedis.auth("redis123");
		// 存储数据和获取数据 (存进去是什么,取出来也是什么)
		jedis.set("username", "陈如水");
		String username = jedis.get("username");
		System.out.println(username);
	}

	// 通过Redis连接池获取jedis对象
	@Test
	public void testRedisPool() {
		// 创建一个Redis连接池,并对它进行设置
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(50);// 最大连接数,连接全部用完,进行等待
		poolConfig.setMinIdle(10); // 最小空余数
		poolConfig.setMaxIdle(30); // 最大空余数
		JedisPool pool = new JedisPool(poolConfig, "192.168.1.227", 6379);
		// 从jedis中获取连接资源,并进行权限认证
		Jedis jedis = pool.getResource();
		jedis.auth("redis123");
		// Redis如何存储对象? 把对象转化成json字符串;任何数据都能转成json字符串
		jedis.set("xxx", "123");
		System.out.println(jedis.get("xxx"));
		// 关闭资源放回到连接池中
		jedis.close();
		// 真正在开发中,不需要管理连接池资源的,关闭了别人就没法用了。
		pool.close();
	}

	/**
	 * 测试jedisPoolUtils的使用
	 */
	@Test
	public void testJedisPoolUtils() {
		Jedis jedis = JedisPoolUtils.getJedis();
		jedis.set("utils", "测试数据");
		System.out.println(jedis.get("utils"));
	}

	/**
	 * 用于存取HashMap的值
	 * hset() hget() hdel()方法的使用,可以正常取出的
	 */
	@Test
	public void testJedisHashMap() {
		Jedis jedis = JedisPoolUtils.getJedis();
		jedis.hset("myhash", "username", "crs");
		//删除某一个键值对
		//jedis.hdel("myhash", "username");
		String result = jedis.hget("myhash", "username");
		System.out.println(result);
	}
	
	/**
	 * 操作list集合
	 * lpush()在头部添加元素,rpush()在尾部添加元素
	 * lrange()取出集合中的元素,返回值数数组。
	 * -1表示链表尾部的数据
	 */
	@Test
	public void testJedisList(){
		Jedis jedis = JedisPoolUtils.getJedis();
		//在头部添加元素,最后一个元素是null
		//jedis.lpush("array", "1","tst","null");
		List<String> lrange = jedis.lrange("array", 0, -1);
		for (String item : lrange) {
			System.out.println(item);
		}
		//取出头部的第一个元素lpop();取出尾部的第一个元素rpop()
		//String lpop = jedis.rpop("array");
		//System.out.println(lpop);
		
		//返回集合列表中元素的个数,取列表中的数据不会改变列表的长度
		//Long longth = jedis.llen("array");
		//System.out.println(longth);
	}
	
	/**
	 * 测试set集合的使用
	 * sadd()往集合中添加数据,smembers()从集合中取出数据
	 * smembers() 获取集合里面的数据
	 * scard() 获取集合的长度
	 * srem() 删除集合中的指定元素
	 * sismember() 返回值是boolean类型,是否是集合中的成员?
	 * set集合里面的交集、并集、差集运算
	 * set集合与list集合的区别:无须,不可以重复。
	 */
	@Test
	public void testSet(){
		Jedis jedis = JedisPoolUtils.getJedis();
		jedis.sadd("test", "1","2","3","4");
		Set<String> smembers = jedis.smembers("test");
		for (String item : smembers) {
			System.out.println(item);
		}	
		Long scard = jedis.scard("test");
		System.out.println("set集合的长度"+scard);
		//删除集合中指定的元素
		jedis.srem("test", "1");
		Long scard2 = jedis.scard("test");
		System.out.println(scard2);
		Set<String> smembers2 = jedis.smembers("test");
		System.out.println("---------------------");
		for (String item : smembers2) {
			System.out.println(item);	
		}
		Boolean sismember = jedis.sismember("test", "2");
		if(sismember){
			System.out.println("数据存在");
		}
	}
	
	/**
	 * SortSet集合的使用
	 * zadd() 添加数据
	 * zscore() 获取指定元素的成绩
	 * zcard() 获取集合的长度
	 * zrem() 删除集合中的指定元素
	 * 
	 */
	@Test
	public void testSortSet(){
		Jedis jedis = JedisPoolUtils.getJedis();
		HashMap<String,Double> hashMap = new HashMap<String,Double>();
		hashMap.put("a", (double) 100);
		hashMap.put("b", (double) 80);
		hashMap.put("c", (double) 50);
		jedis.zadd("myScore", hashMap);
		//获取指定成员的分数
		Double zscore = jedis.zscore("myScore", "c");
		System.out.println("获取的分数是"+zscore);
		//获取成员的数量(这个里面有多少对成员)
		Long zcard = jedis.zcard("myScore");
		System.out.println("成员的数量:"+zcard);
		//删除指定的成员
		Long zrem = jedis.zrem("myScore", "c");
		System.out.println(zrem);
	}
	
	/**
	 * keys的通用操作:其实就是对键key的通用性操作。
	 * 返回所有的key,
	 * 删除指定的key,
	 * 判断指定的key是否存在,
	 * 对Key进行重命名,
	 * 设置key的过期时间
	 */
	@Test
	public void testCommonKeys(){
		Jedis jedis = JedisPoolUtils.getJedis();
		//jedis.rename(oldkey, newkey)
		//jedis.ttl(key) 以秒为单位返回 key 的剩余过期时间。
		//jedis.type(key)
		//jedis.expire(s, seconds) //设置key的过期时间
		//redis连接指定的数据库
		//jedis.select(index) 0--15
	}
	
	
}

 

JedisPoolUtils的封装:

 

在实际的开发中,是通过Spring的配置文件进行配置的

 

package testRedis;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 操作Redis的工具类
 * @author chenrushui
 *
 */
public class JedisPoolUtils {
	
	public static JedisPool pool=null;
	
	/**
	 * 静态代码块只执行一次
	 */
	static{
		//加载配置文件
		InputStream in = JedisPoolUtils.class.getClassLoader().getResourceAsStream("redis.properties");
		//创建配置文件对象
		Properties prop = new Properties();
		try {
			//加载文件流
			prop.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(Integer.parseInt(prop.get("redis.MaxTotal").toString()));//最大连接数,连接全部用完,进行等待
		poolConfig.setMinIdle(Integer.parseInt(prop.get("redis.MinIdle").toString())); //最小空余数
		poolConfig.setMaxIdle(Integer.parseInt(prop.get("redis.MaxIdle").toString())); //最大空余数
		pool = new JedisPool(poolConfig,prop.get("redis.host").toString(),Integer.parseInt(prop.get("redis.port").toString()));
	}
	
	/**
	 * 对外提供静态方法
	 * @return
	 */
	public static Jedis getJedis(){
		Jedis jedis = pool.getResource();
		jedis.auth("redis123");
		return jedis;
	}
	
}

 

 

 

互联网数据目前基本使用两种方式来存储:关系数据库或者非关系型数据库key-value。

Redis是完全开源免费的,是一个高性能的key-value数据库。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型(值可以是五种数据类型)。在部分场合可以对关系数据库起到很好的补充作用。

 

Redis 有以下三个特点:

1)Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。它是一个memory database,因为它的高性能都是基于内存操作的基础。

2)Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

3)Redis支持数据的备份,即master-slave模式的数据备份。对Redis的作用的不同解读决定了你对Redis的使用方式。

 

redis支持各种不同方式的排序。

redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。(十分钟刷新一次) 

 

RedisDesktopManager可视化的软件使用:

1)点击Connect to Redis Server,连接到Redis服务器。地址和端口号6379,给该连接七个名字。

2)点击Test Connection 来进行连接检测。

3)连接之后,在左侧有0-15个db库,Redis默认的数据库!

4)选中一个数据库,双击打开;如果里面没有数据,就是空的。

5)在选择的数据库上面右键单击,会弹出一个对话框。可以选择Add new key!~~再弹出的对话框中添加一组Key-Value 数据进去。

6)点击save之后,会提示你是否从新加载这个数据库!~选择是,这时你就可以看到你选择的数据库中有刚刚添加的Key了!

7)双击那个Key(nihao),它会在右侧的部分将Key 与 Value都展示出来,并且对Key有一些相应的操作。

 

目的:

1)使用Redis命令操作常用数据结构的数据存取(Redis基本的数据类型,数据类型的不同会导致数据存储方式的不同)

2)在java程序中通过Jedis连接Redis。

 

NoSql:不仅仅是数据库;泛指非关系型数据库(mongDB,Redis);读写性能非常好(因为数据结构简单,没有关系,数据之间无关系);内存数据库,可以实现数据的持久化;无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。

为什么会出现NoSql数据库?对数据库高并发读写的需求。

三高:高并发,高负载,高可用。

键值对型数据库:优点;快速查询,缺点存储的数据缺少结构化。

 

Value的数据类型,key的数据类型一般是String。Redis支持的数据类型

Redis应用场景  发红包不能延迟。

启动n台服务器session如何共享?

Redis启动成功的标志是什么?

Redis的配置文件

前端启动模式,后端启动模式。

启动Redis的时候指定配置文件的路径

通过java程序访问Redis数据库。

各种数据库的驱动肯定不同

 

非关系型数据库的使用,

如何通过java语言进行操作?通过连接池操作  代码如何去写

如何处理缓存问题?

基于键值对进行数据的存储。

如何在Idea中使用Redis?如何通过java程序访问Redis?

 

把一个对象放到另一个对象里面

或者把一个集合放到另一个对象里面

数据库查询语句的处理。(多表联查的处理,如何让你写的代码是可以测试的)

 

Redis是一个开源的支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。

redis是一个key-value存储系统。它支持五种存储类型,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。

在此基础上,redis支持各种不同方式的排序,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

 

内存数据库。

在部分场合可以对关系数据库起到很好的补充作用。

 

1.关系型数据库和nosql数据库

关系型数据库是基于关系表的数据库,最终会将数据持久化到磁盘上,而nosql数据库是基于特殊的结构,并将数据存储到内存的数据库。从性能上而言,nosql数据库要优于关系型数据库,从安全性上而言关系型数据库要优于nosql数据库,所以在实际开发中一个项目中nosql和关系型数据库会一起使用,达到性能和安全性的双保证。

 

2.为什么要使用Redis?

对数据库高并发读写的需求。每秒钟上万次的读写请求,硬盘IO无法承受。

对海量数据的高效率存储和访问的需求。

对数据库的高可扩展性和高可用性的需求。

 

Redis的数据结构

Map之间是没有关系的,所以查询数据时速度很快。

五种数据类型的区别是什么?值类型是五种。

List集合与set集合的区别是什么  有序的set集合    hash值:双列集合   单列集合和双列集合

使用Java操作Redis需要jedis-2.1.0.jar.

如果需要使用Redis连接池的话,还需commons-pool-1.5.4.jar,

  

jedis的连接池使用

 

刷新缓存

 

1、通过java程序访问Redis数据库。

1)获取连接对象,Jedis jedis=new Jedis();通过构造函数设置主机地址和端口号。

如何需要连接远程的Redis,需要在防火墙中配置Redis的端口为6379。如何进行配置呢?

Redis存储与获取数据不涉及编解码问题,存的时候是什么样,取也是什么样。

不同版本的jar包和源码包也是可以进行绑定的。

把数据通过json包转化成json字符串进行存储。

2、Jedis连接池的使用:通过jedis的连接池pool获取连接对象。  JedisPoolConfig

1)创建连接池配置对象;数据库连接池常见配置项

2)创建redis连接池,连接池配置文件

最大闲置个数:超过30个闲置的连接,就关闭其余的连接。

最小闲置个数:至少要有10个闲置连接,如果闲置连接不够用,就会创建。

最大连接数(超过最大连接数,可能会出现连接超时)。

3)从连接池中获取连接资源。

4)关闭资源

3、把Redis常用操作封装成工具类:JedisPoolUtils

通过加载配置文件的形式 加载连接池参数信息

4、在Ecplise中如何加载配置文件?

5、Jedis的数据类型  value支持五种数据结构,关于key的定义要符合规范。

 

String类型的数据:最大存储512M的数据;存入与获取的数据相同。

赋值:如果该Key存在,就覆盖值,总是返回ok。

取值:如果值不存在,返回nil;如果数据类型不是String,获取时将会报错。

删除键值对:del username

数字增减:incr num;必须是数字类型的字符串,其他的字符串会报错的,相当于i++。

Decr mun; 如果键不存在,帮你创建,初始值为0;

 

append关键字的使用:

1)append主要用于拼接字符串,append username chenrushui把字符串chenrushui追加拼接到username对应的value中。

2)返回值是拼接以后的字符个数

 

二、Hash值(HashMap类型,值是键值对类型)。

三、list值,底层实现是数组。

四、set集合:无顺序,不能有重复元素;可以判断某一元素是否存在。

 

存储hash值:map集合,值是一个键值对。new HashMap()

hset() 为指定的key设置键值对

hget() 获取指定的key的键值对

hmset()

Hmget()

取出键对应的value中所有的键值对

hgetall()

hdel()

 

一个Redis实例可以有16个数据库,可以选择某一个数据库进行存取操作。默认使用第0个数据库。

移库:将当前库的k移到1库中去

1)把这个键值对数据移动到另一个数据库中;

2)以前的数据库中就没有移走的键值对了;

key *; select 1; move utils 1

 

redis客户端工具常用的命令使用  dbsize info ping等等

 

redis订阅与消息发布

一接收到消息就进行某种操作

1)订阅某个频道,2)发布某些信息,3)订阅者收到消息怎么处理

发布什么,别人就会收到什么。

订阅频道与批量订阅频道 subscribe s* 批量订阅以s开头的频道

 

Redis事务

1)multi :开始事务,其后执行的命令都将被存入命令队列,直到执行exec时,这些命令才被原子性的执行,类似于begin transaction。

2)discard :事务回滚

3)exec :提交事务。

其实就像批处理,一批命令一起处理,中间的某一条可能执行失败。 queued:排队。

 

jredis 保存list jedis 存储对象_数据

 


redis配置文件:redis.conf   dump.rdb

ShardedJedis:Redis集群客户端对象 

 

Redis适用于高并发的递增、递减功能

递增指令:incr(默认从0开始)

递减指令:decr(默认从0开始,递减会出现负数,这点跟memcache不一样,mc到0)

适用场景:高并发生成订单号,秒杀类的业务逻辑等。 不会存在并发问题,是原子操作。

redis计数器限制:原子计数器,防止并发请求。