Redis技术总结

Redis的基本内容

1.  什么是redis

    a) Nosql 泛指非关系型数据库(基于键值对,不需要SQL层解析,性能高,易扩展,内存存储,读写速度快,低成本)

    b) Redis是nosql产品,其他的比如:mangoDB等,redis是开源的高性能键值对数据库

    c) 拓展:关系型数据库(oracle,mysql)支持多表复杂查询,事物支持等

2.    redis的特性

        

3.    redis的应用场景

    实现缓存(主流缓存技术:redis和Memcached),实现消息列队(利用redis的存储列表类型),分布式锁

    二者谁的性能更高?

            单纯从缓存命中的角度来说,是Memcached要高,Redis和Memcache的差距不大

            但是,Redis提供的功能更加的强大

    二者的区别是什么?

            Memcache是多线程

            Redis是单线程

4.    Redis的多数据库:

        redis中默认支持16个数据库,对外是以0开始的数字命名,可以通过参数databases来修改数据库个数,连接后默认选择0号数据库,可以通过select 1来选择1号数据库!各个数据库之前并不是完全隔离的,可以通过flushall来清空所有数据库,通过flushDB来清空当前数据

5.    Redis的持久化

    a.    Redis支持2种持久化(半持久化RDB和全持久化AOF方式)

RDB持久化:指定时间间隔内将内存数据集以快照形式写入磁盘,以二进制文件保存,文件名默认:dump.rdb,redis重启后自动读取其中文件

AOP持久化:redis执行的每一个写操作命令,都会把它记录并追加到appendonly.aof文件文件中,当redis重启时,将会读取AOF文件进行“重放”以恢复

    b.    如何实现持久化以及优缺点:

实现RDB:在redis.conf配置文件中:save N M表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。也可以手动执行save或者bgsave(异步)做快照。是默认的持久化方式

      如:save 900 1 表示:900秒之内,如果超过1个key被修改,则发起快照保存;

      优点:RDB 可以最大化Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作

       缺点:不能完全保证数据持久化,因为是定时保存,所以当redis服务down掉,就会丢失一部分数据,而且数据量大,fork子进程可能导致服务停止服务几毫秒到1秒,会影响性能

       实现AOF:在redis.conf配置文件中,将appendonly修改为yes(默认为no)

      优点:数据完整性好,可以配置策略什么时候从硬盘缓存写到硬盘AOF文件中(效率不同)

                      appendfsyncalways     #每次有数据修改发生时都会写入AOF文件。

                      appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。

                      appendfsyncno          #从不同步。高效但是数据不会被持久化。

      缺点:AOF文件比RDB文件大,AOF性能比RDB差

      RDB ,AOF原理,运作方式 更多请参考:http://redisdoc.com/topic/persistence.html

6.    Redis的基本命令

KEYS * 获取所有的键名列表(KEYS pattern (pattern可以是?:一个字符,*:任意个字符,[a-f]:a-f之间任意一个字符),\x:匹配字符x)
EXISTS key:判断key是否存在,存在返回1,不存在返回0
DEL key([k1,k2]):删除key,支持多个key,返回删除的个数
TYPE key([k1,k2]):获取key所对应值得类型,支持多个key(string,hash,list,set,zset)
HELP  TAB键

7.    Redis的字符串数据类型

可以储存任意形式的字符串类型,二进制数据,json化对象,字节数组等,一个字符串类型存储的最大数据容量为512M

常用方法:

SET key value [NX|XX] [EX seconds] [PX milliseconds] 
set(key, value, nxxx, expx, time)
	EX:设置过期时间(单位秒)
	PX:设置过期时间(单位毫秒)
	NX:只有key不存在的时候设置value
	XX:只有key存在的时候设置value
SETEX key seconds value  :设置值的同时设置key的过期时间(秒)相当于SET mykey value +EXPIRE mykey seconds
PSETEX key milliseconds valu:PSETEX和SETEX一样,唯一的区别是到期时间以毫秒为单位,而不是秒
SETNX key value :当key不存在的时候设置值,存在的时候不操作
SET key value
GET key 
INCR key :将key中存储的数值+1,返回的是递增后的值。如果该key不存在,则初始化key为0。如果类型不对或者不是整数,则报错
INCRBY key i: 将key中存储的数值+i
DECR key: 将key中存储的数值-1
DECRBY key i: 将key中存储的数值-i
APPEND key value:将key中存储的值追加上value	
STRLEN key:获取key中存储的值得长度
MSET k1,v1,k2,v2
MGET k1,k2
GETSET key newValue :将key对应的value值设置成newValue,并返回老的value

8.    Redis的散列数据类型(hash)

        数据结构:Map<String,Map<String,String>>:适合存储对象

            

        常用命令:

HSET key field value (不区分插入或更新操作,插入返回1,更新返回0)

HGET key field

HMSET key f1 v1 f2 v2…

HMGET key f1 f2..

HGETALL key 获取所有的

HEXISTS key field 判断value是否存在

HSETNX key field value: 插入数据(数据不存在,同HSET),不做任何操作(当数据存在时)

HINCRBY key field i:将key filed 对应的value值增加i

HDEL key f1 f2.. :删除,返回删除的个数

HKEYS key :获取字段名(即key 对应所有的field)

HVALS key :获取字段值(即key 对应所有的value)

HLEN key :获取字段的数量(即key 对应所有的field的数量)

9.    Redis的列表数据类型

        数据结构:Map<String, List<String>>

        

    列表数据结构类型栈结构,用于存储简单的字符串类型的列表,按照插入顺序排序,先插入的在底部,最后插入的在头部

                Lpush : 先插入的最右边,最后插入的最左边

                Rpush:先插入的最左边,最后插入的最后边

    常用方法:

      

LPUSH keyv1 v2 .. :将1个或多个值从左边依次插入,先插入v1在后边,再插入v2在左边 (右:RPUSHkey v1 v2 )

      LPOP key :从左边移除列表第一个元素并返回 (右边移除: RPOP key)

      LPUSHX keyv1 v2:将1个或多个值从左边插入到已经存在的列表中

LINDEX key index :通过索引获取列表中元素(最后插入的索引为0,依次往前推,负数表示从后往前,-1表示最后一个,-2表示倒数第二个,没有RINDEX)

LRANGE keyiStart iStop :通过索引范围(闭区间[ ])获取列表中元素(没有RRANGE)

LSET keyindex value :通过索引设置列表的元素的值

LTRIM keyiStart iStop :保留索引范围内(闭区间)的元素,其他元素删除

LREM keycount value :从列表中删除字段值为value的元素,删除个数是count的绝对值(count>0从左边删除,count=0全部删除,count<0从右边删除)

RPOPLPUSH resource destination:原子性的返回并移除resource 列表中最后一个元素(尾部)并把它添加到destination列表的第一个位置(列表头部)

例如:假设 source 存储着列表a,b,c, destination存储着列表 x,y,z。执行 RPOPLPUSH 得到的结果是 source 保存着列表 a,b ,而 destination 保存着列表 c,x,y,z。

如果 source 不存在,那么会返回 nil 值,并且不会执行任何操作。 如果 source 和 destination 是同样的,那么这个操作等同于 移除列表最后一个元素并且把该元素放在列表头部, 所以这个命令也可以当作是一个旋转列表的命令。

BLPOP key1key2.. timeout : 移除并获取列表的第一个元素,如果列表没有元素,则会一直阻塞列表知道等待超时或者发现可弹出元素(timeout=0则会一直等待),先从key1对应的列表取,取到就返回key1和对应的元素,没有去取key2,同前一个。

BRPOP key1key2.. timeout : 移除并获取列表的最后一个元素,如果列表没有元素,则会一直阻塞列表知道等待超时或者发现可弹出元素

LINSERT keyBEFORE/AFTER target value : 在key对应的列表中找target元素,找到后在他之前或之后插入value元素 

LLEN key :返回列表长度

10.     Redis的集合数据类型

          数据结构Map<String,set<String>>

          Redis集合数据类型是String类型的无序集合集合成员是唯一的,不能出现重复的数据(插入重复元素,redis会忽略操作)

          结构图如下


                
常用方法:
SADD key m1 m2.. :向key对应的集合中添加多个元素
SREM key m1 m2..  : 移除key对应集合中的多个元素
SPOP key :随机移除集合中的一个元素
SMEMBERS key :返回集合中的所有元素
SCARD key :返回集合中元素的个数
SISMEMBER key member : 判断member是否是集合元素
SMOVE resource destination member : 将resource集合的member元素移到destionation中
SDIFF key1 [key2..] : 以key1为基准,返回key1有且[key2 key3..等]没有的元素
SINTER key1 [key2…] :返回所有集合的交集!
SINTERSTORE destination key1 [key2..] :获取所有集合的交集并存储在destionation集合中
SUNION key1 [key2…] :返回所有集合的并集
SUNIONSTORE destination key1 [key2..] : 获取所有集合的交集并存储在destionation集合中

11.     Redis的有序集合类型

        数据结构Map<String,zSet<String>>

        是String类型的元素的集合,不允许重复的值,每个元素都关联一个double类型的分数,分数可以重复,redis有序集合按照分数从小到大排序。

        Redis有序集合默认是升序的,分数越小排名越靠前,即分数越低元素下标越小

命令格式	说明
ZADD key score1 member1 [score2 member2 ...]	添加一个或多个成员到有序集合,或者如果它已经存在更新其分数
ZRANGE key start stop [WITHSCORES]	把集合排序后,返回名次在[start,stop]之间的元素。 WITHSCORES是把score也打印出来
ZREVRANGE key start stop [WITHSCORES]	倒序排列(分数越大排名越靠前),返回名次在[start,stop]之间的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset n]	集合(升序)排序后取score在[min, max]内的元素,并跳过offset个,取出n个
ZREM key member [member ...]	从有序集合中删除一个或多个成员
ZRANK key member	确定member在集合中的升序名次
ZREVRANK key member	确定member在集合中的降序名次
ZSCORE key member	获取member的分数
ZCARD key	获取有序集合中成员的数量
ZCOUNT key min max	计算分数在min与max之间的元素总数
ZINCRBY key increment member	给member的分数增加increment
ZREMRANGEBYRANK key start stop	移除名次在start与stop之间的元素
ZREMRANGEBYSCORE key min max	移除分数在min与max之间的元素

12.     设置redis的生存时间

        缓存设置生存时间,到期自动销毁

EXPIRE key seconds

TTL key :查看生存时间(-1 表示没有生存时间,永久存储,-2表示数据已经被删除,>0的数字表示剩余的秒数)

PERSIST key :消除生存时间(重新设置值也会清空生存时间)

Redis的java客户端操作

1.    java的客户端Redis支持主要通过jedis的支持(需要导入jedis的依赖),jedis是redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用

        通过jedis的API来操作redis键值对,设置,获取等操作!

a.    直接使用jedis:创建jedis对象并指定ip和端口,通过jedis来设置或者获取值

//通过jedis操作redis
public class JedisDemo {
	
	public static void main(String[] args) {
		Jedis jedis = new Jedis("112.162.184.15",6379);
		jedis.set("a", "1");
		System.out.println(jedis.get("a"));
		//pool.returnResource(jedis);
		jedis.close();//新版本 关闭的时候自动还给连接池
		pool.close();

	}

b .     从连接池中获取jedis : 构建连接池配置信息并指定最大连接数,构建连接池对象指定连接池配置信息,IP,端口,然后从连接池中获取jedis连接来操作!用完后要把jedis连接返回给连接池并关闭连接池。

//通过连接池jedisPool操作jedis
public class JedisDemo {
	
	public static void main(String[] args) {
		//构建连接池配置信息
		JedisPoolConfig config = new JedisPoolConfig();
		//设置最大连接数
		config.setMaxTotal(1024);
		//保存idle状态对象的最大个数
		config.setMaxIdle(200);
		//池内没有对象最大等待时间
		config.setMaxWaitMillis(1000);
		//当调用borrow Object方法时,是否进行有效性检查
		config.setTestOnBorrow(false);
		//当调用return Object方法时,是否进行有效性检查
		config.setTestOnReturn(false);
		//构建连接池
		JedisPool pool =new JedisPool(config, "10.116.184.15", 6376);
		Jedis jedis = pool.getResource();
		jedis.set("a", "1");
		System.out.println(jedis.get("a"));
		//pool.returnResource(jedis);
		jedis.close();//新版本 关闭的时候自动还给连接池
		pool.close();

	}

c.  redis的集群

     redis的分片式集群

            主要思想:采用哈希算法将redis数据的key进行散列,通过hash函数,特定的key会被映射到特定的redis节点,这样客户端就知道该指向那个redis节点

           分片:就是把数据拆分到多个redis实例的过程,这样每个redis实例将包含完整数据的一部分

           分片的方式:哈希分片

           哈希分片:适用于任何键,使用哈希函数将键名转换成一个数字,在对这个数字进行取模运算,得到的数字映射不同的redis 实例

           存在的问题:无法动态的增加或者减少节点,扩容麻烦,数据备份麻烦等

           Jedis的分片特点:采用一致性哈希算法,将key和节点name同时hashing,然后进行映射匹配,采用一致性哈希匹配而不是采用一般的哈希求模映射,主要原因是当增加或减少节点的时候,不会产生由于重新分配而造成的rehashing,一致性哈希算法只会影响相邻节点key的分配,影响较小。

public class ShardedJedisPoolDemo {

	    public static void main(String[] args) {
	        // 构建连接池配置信息
	        JedisPoolConfig config = new JedisPoolConfig();
	        //设置最大连接数
	        config.setMaxTotal(1024);
	        //保存idle状态对象的最大个数
		config.setMaxIdle(200);
		//池内没有对象最大等待时间
		config.setMaxWaitMillis(1000);
		//当调用borrow Object方法时,是否进行有效性检查
		config.setTestOnBorrow(false);
		//当调用return Object方法时,是否进行有效性检查
		config.setTestOnReturn(false);

	        // 定义集群信息
	        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
	        shards.add(new JedisShardInfo("127.0.0.1", 6379));
	        shards.add(new JedisShardInfo("192.168.29.112", 6379));

	        // 定义集群连接池
	        ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, shards);
	        ShardedJedis shardedJedis = null;
	        try {
	            // 从连接池中获取到jedis分片对象
	            shardedJedis = shardedJedisPool.getResource();
	            
//	            for (int i = 0; i < 100; i++) {
//	                shardedJedis.set("key_" + i, "value_" + i);
//	            }

		        System.out.println(shardedJedis.get("key_49"));
	            System.out.println(shardedJedis.get("key_7"));

	        } catch (Exception e) {
	            e.printStackTrace();
	        } finally {
	            if (null != shardedJedis) {
	                // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
	                shardedJedis.close();
	            }
	        }

	        // 关闭连接池
	        shardedJedisPool.close();

	    }
	}

    使用JedisCluster操作redis集群

	private static void init() throws Exception {
		// 获取REDISS配置
		Properties pro = SystemResourceUtil.getPropertisByName("redis.properties");
		// 初始化REDIS服务节点
		Set<HostAndPort> jedisClusterNodes = initJedisClusterNodes(pro);
		// 池初始化
		GenericObjectPoolConfig poolConfig = initGenericObjectPoolConfig(pro);

		jedisCluster = new JedisCluster(jedisClusterNodes, poolConfig);

	}
	//初始化redis的服务节点
	private static Set<HostAndPort> initJedisClusterNodes(Properties pro) {		
		String addressStr = pro.getProperty("redis.address");
		Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
		if (StringUtils.isNoneBlank(addressStr)) {
			// redis密码
			String pw = PasswordUtil.getPasswordByKey("redis.password");
			// 解析服务地址格式10.31.225.212:5762,10.31.225.213:5763,10.31.225.212:5764
			String[] addresses = addressStr.split(",");

			for (String address : addresses) {
				String[] s = address.split(":");
				jedisClusterNodes.add(new HostAndPort(s[0], Integer.parseInt(s[1]), pw));
			}
		} else {
			logger.error(" redis server address is null,check the redis.properties");
		}
		return jedisClusterNodes;
	}
		//初始化GenericObjectPool
	private static GenericObjectPoolConfig initGenericObjectPoolConfig(Properties pro) {
		String maxTotal = pro.getProperty("redis.maxTotal");
		String maxIdle = pro.getProperty("redis.maxidle");
		String maxWait = pro.getProperty("redis.maxwait");

		GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
		if (StringUtils.isBlank(maxTotal) || StringUtils.isBlank(maxIdle) || StringUtils.isBlank(maxWait)) {
			logger.warn("redis.properties is not config!");
		} else {
			poolConfig.setMaxTotal(Integer.parseInt(maxTotal));
			poolConfig.setMaxIdle(Integer.parseInt(maxIdle));
			poolConfig.setMaxWaitMillis(Long.parseLong(maxWait));
			poolConfig.setTestOnBorrow(Boolean.parseBoolean(pro.getProperty("redis.testonborrow")));
			poolConfig.setTestOnReturn(Boolean.parseBoolean(pro.getProperty("redis.testonreturn")));
		}
		return poolConfig;
	}
    redis.properties如下

#REDIS服务地址
redis.address=10.20.131.117:4772,10.20.131.118:4773,10.20.131.117:4774
#最大的实例个数
redis.maxtotal=1024
#保存idle状态对象的最大个数
redis.maxidle=200
#池内没有对象最大等待时间
redis.maxwait=1000
#当调用borrow Object方法时,是否进行有效性检查
redis.testonborrow=false
#当调用return Object方法时,是否进行有效性检查
redis.testonreturn=false
    利用jedis封装操作redis的工具类

d .  spring整合jedis,使用的时候注入 ShardedJedisPool,通过ShardJedisPool来获取.getResource()来获取ShardJedis操作redis

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	<!-- 连接池的配置信息 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大连接数,其他配置信息略 -->
		<property name="maxTotal" value="${redis.maxTotal}"></property>
	</bean>
	
	<!-- 集群连接池  -->
	<bean class="redis.clients.jedis.ShardedJedisPool">
		<constructor-arg index="0" ref="jedisPoolConfig"></constructor-arg>
		<constructor-arg index="1">
			<list>
				<bean class="redis.clients.jedis.JedisShardInfo">
					<constructor-arg index="0" value="${redis.node1.host}"></constructor-arg>
					<constructor-arg index="1" value="${redis.node1.port}"></constructor-arg>
				</bean>
			</list>
		</constructor-arg>
	</bean>
</beans>

e. 使用spring整合redis的spring-data-redis,是对jedis的封装,集成jedis的一些命令和方法,与spring整合,通过redisTemplate来操作!


<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  
    <context:property-placeholder location="classpath:redis.properties" />  
    <context:component-scan base-package="com.x.redis.dao">
    </context:component-scan>
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
        <property name="maxIdle" value="${redis.maxIdle}" />  
        <property name="maxActive" value="${redis.maxActive}" />  
        <property name="maxWait" value="${redis.maxWait}" />  
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />  
    </bean>  
      
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  
        p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"  p:pool-config-ref="poolConfig"/>  
      
    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">  
        <property name="connectionFactory"   ref="connectionFactory" />  
    </bean>         
      
    <bean id="userDAO" class="com.x.redis.dao.impl.UserDAOImpl" />   
</beans> 

此外:附加redis资料查询地址:

        http://www.redis.cn/commands.html

        http://www.redis.cn/topics/distlock(官方分布式锁的讲解)

        http://blog.csdn.net/liubenlong007/article/details/53782934(其他redis讲解的博客)





猜你喜欢

转载自blog.csdn.net/weixin_37598682/article/details/79635651
今日推荐