Redis非关系型数据库

JAVA学习网 2019-04-03 11:54:05

1.简介

 

Redis是一个基于内存的Key-Value非关系型数据库,由C语言进行编写。

Redis一般作为分布式缓存框架、分布式下的SESSION分离、分布式锁的实现等等。

Redis速度快的原因:基于内存、单线程、多路复用。 

 

 

2.Redis数据结构

 

Redis中提供了五种数据结构,分别是String、Hash、List、Set、ZSet,每种数据结构底层都是通过字符串来进行实现。

 

2.1 String

Key对应的Value是一个字符串类型。

#设置字符串类型的Key
set key value

#仅当Key不存在时设置字符串类型的Key
setnx key value

#设置字符串类型的Key并添加过期时间
setex key second value

#获取Key对应的Value
get key

#让Key对应的Value值递增1
incr key

#让Key对应的Value值递减1
decr key

#让Key对应的Value递增指定的数值
incrby key num

#让Key对应的Value递减指定的数值
decrby key num

#往Key对应的Value中追加字符串
append key str

*在使用set、append命令时,如果Key不存在则创建,否则替换Key对应的Value值。

*在使用incr、incrby、decr、decrby命令时,如果Key不存在则初始化为0后再进行操作,如果Key对应的Value不是数值类型字符串,那么将会报错。

 

2.2 Hash

Key对应的Value是一个哈希类型,每个哈希类型中都包含若干个键值对(属性名与属性值)

#往Hash中添加一个属性
hset key field value

#仅当Key不存在时往Hash中添加一个属性
hsetnx key field value

#往Hash中添加多个属性
hmset key field1 value1 field2 value2

#获取Hash中指定的一个属性
hget key field

#获取Hash中指定的多个属性
hmget key field1 field2

#获取Hash中所有的属性
hgetall key

#让Hash中指定的属性递增指定的数值(属性值必须是数值类型)
hincrby key field num

#判断Hash中指定的属性是否存在
hexists key field

#获取Hash中属性的个数
hlen key

#获取Hash中所有的属性名
hkeys key

#获取Hash中所有的属性值
hvals key

#删除Hash中指定的多个属性
hdel key field1 field2

*在使用hset、hmset命令时,如果Key不存在则创建,否则往Key对应的Hash中添加属性,如果属性名相同则替换属性值。

*Hash中只有hincryby命令,没有类似String的incr、decr、decrby命令。

*当使用hdel命令删除了Hash中的所有属性,那么此时Key也会被删除。

 

2.3 List

Key对应的Value是一个List类型(有序可重复),Redis中的List使用链表的方式进行实现,因此其在插入和删除操作时性能要比顺序表的高(头指针指向链表的第一个结点)

#从链表的左侧添加元素
lpush key value

#从链表的右侧添加元素
rpush key value

#仅当Key存在时从链表的左侧添加元素
lpushx key value

#仅当Key存在时从链表的右侧添加元素
rpushx key value

#获取链表中指定索引范围的元素(从链表的左侧开始遍历,包括begin和end的位置,如果end为-1表示倒数第一个元素)
lrange key begin end

#从链表的左侧弹出一个元素
lpop key

#从链表的右侧弹出一个元素
rpop key

#获取链表中元素的个数
llen key

#删除链表中指定个数个Value(若count为正数,则从链表的左侧开始删除指定个数个Value,若count为负数,则从链表的右侧开始删除指定个数个Value,若count为0,则删除链表中所有指定的Value)
lrem key count value

#设置链表中指定索引的值
lset key index value

#从链表的右侧弹出元素并将其放入到其他链表的左侧(一般用在消息队列的备份)
rpoplpush key otherKey

*当使用lpush、rpush命令时,如果Key不存在则创建,否则往Key对应的链表中追加元素。

*通过Redis的List可以实现队列和栈结构,当遵循lpush、rpop时,此时为队列结构,当遵循lpush、lpop时,此时为栈结构。

 

2.4 Set

Key对应的Value是一个Set(无序不可重复)

#往Set中添加元素
sadd key value

#删除Set中指定的元素
srem key value

#查看Set中的元素
smembers key

#判断Set中是否包含某个元素
sismemeber key value

#返回Set中元素的个数
scard set

#返回两个Set的交集
sinter set1 set2

#返回两个Set的并集
sunion set1 set2

#返回Set1中Set2没有的元素(补集)
sdiff set1 set2

#将Set1和Set2的交集放入到新的Set中
sinterstore destSet set1 set2

#将Set1和Set2的并集放入到新的Set中
sunionstore destSet set1 set2

#将Set1中Set2没有的元素放入到新的Set中
sdiffstore destSet set1 set2

*在使用sadd命令时,如果Key不存在则创建,否则往Key对应的Set中追加元素。

 

2.5 ZSet

Key对应的Value是一个带分数的Set(有序不可重复),其中分数可以相同但Value不能相同。

#往ZSet中添加元素
zadd key score value

#获取ZSet中指定Value的分数
zscore key value

#返回ZSet中元素的个数
zcard key

#获取ZSet中指定索引范围的元素(包括begin和end的位置,end为-1时表示倒数第一个元素)
zrange key begin end

#获取ZSet中指定索引范围的元素以及分数,返回的元素按照分数从小到大排序
zrange key begin end withscores

#获取ZSet中指定索引范围的元素以及分数,返回的元素按照分数从大到小进行排序
zrevrange key begin end withscores

#获取ZSet中指定分数范围的元素(包括begin和end的位置)
zrangebyscore key begin end

#获取ZSet中指定分数范围的元素并限制返回的个数
zrangebyscore key begin end limit num

#返回ZSet中指定分数范围元素的个数
zcount key begin end

#删除ZSet中指定的元素
zrem key value

#删除ZSet中指定分数范围的元素(包括begin和end的位置)
zremrangebyscore key begin end

#让ZSet中指定元素的分数递增指定的值
zincrby key score value

*当使用zadd命令时,如果Key不存在则创建,否则往Key对应的ZSet中添加元素。 

*Set、ZSet中没有类似String、Hash、List的,当Key不存在或存在时才进行操作的命令。 

 

2.6 通用命令

#查看Redis中的Key(支持通配符,*代表任意个字符,?代表任意一个字符)
keys pattern

#删除Key
del key

#判断Key是否存在
exists key

#对Key进行重命名
rename oldKey newKey

#对Key设置过期时间
expire key seconds

#查看Key的有效时间(若Key没有设置过期时间则返回-1)
ttl key

#查看Key的类型
type key

 

 

3.Redis事务

 

Redis中提供了事务的功能,Redis会将事务中的所有命令当做一个原子执行,即一个事务在执行时不会被其他命令所干扰。

#开启事务
multi

#执行事务
exec

#放弃事务
discard

*在Shell中事务与客户端进行绑定,当一个客户端开启了事务后,该客户端事务之后的命令都将放入一个新的队列中,使用exec命令执行事务,其他客户端的命令并不会进入此事务,在Jedis中通过Transaction实例封装一个事务,不受影响。

 

 

4.Redis持久化

 

由于Redis是基于内存的Key-Value非关系型数据库,因此当Redis服务挂掉后由于内存被释放会导致数据丢失,此时可以使用Redis的持久化功能。

 

4.1 RDB持久化方式

RDB持久化方式即Redis每隔一定时间,就会将当前内存中的所有Key-Value写入到磁盘文件中(全量写入),当Redis服务重启时,读取RDB文件自动进行数据的恢复。

RDB持久化方式是默认开启的,可以通过redis.conf配置文件中修改相关配置。

#在900秒内如果至少有1个Key发生变化,那么执行一次写入操作
save 900 1

#在300秒内如果至少有10个Key发生改变,那么执行一次写入操作
save 300 10

#在60秒内如果至少有10000个Key发生改变,那么执行一次写入操作
save 60 10000

#rdb文件的保存路径(相对于redis.conf文件)
dir ./

#rdb文件的名称
dbfilename dump.rdb

*使用RDB持久化方式有很大可能会发生Key的修改未来得及写入到磁盘中服务器就宕机了(可以调整默认的同步策略)

*RDB持久化方式由Redis进程执行fork操作创建子进程来完成,因此阻塞只会发生在fork阶段,客户端可以通过save、bgsave命令手动触发RDB操作,其中save命令会阻塞redis进程直到RDB持久化完成,而bgsave命令由redis进程fork子进程进行完成。

 

4.2 AOF持久化方式

AOF持久化方式即Redis将所有的Key-Value操作都写入到日志文件中(追加,增量写入),当Redis服务重启时,读取AOF文件自动进行数据的恢复。

AOF持久化方式提供了三种同步策略:每修改同步、每秒同步、不同步。

#开启AOF方式
appendonly yes

#AOF文件名
appendfilename "appendonly.aof"

#AOF同步策略
#每修改同步
appendsync always

#每秒同步
appendsync everysec

#不同步
appendsync no

*AOF持久化方式也是由Redis进程执行fork操作创建子进程来完成,并且当日志文件达到一定大小时Redis会对其压缩(重写)

*当同时使用RDB和AOF持久化方式时,数据的恢复将固定使用AOF的。

 

RDB持久化方式与AOF持久化方式的对比

1.文件大小:AOF持久化方式所产生的日志文件要比RDB持久化方式所产生的rdb文件要大。

2.安全性:AOF持久化方式数据丢失的可能性要比RDB持久化方式低。

3.效率:AOF持久化方式在进行数据恢复时的效率要比RDB持久化方式的低。

 

 

5.Redis的安装

 

1.下载Redis源码并进行解压

 

 

2.由于Redis是使用C语言编写的,因此需要安装gcc编译器,并使用make命令进行编译

make

 

3.进行redis的安装

make PREFIX=/usr/redis install

*安装完后生成bin目录,里面包含一些Redis的可执行命令。

 

4.将redis源码目录下的redis.conf配置文件复制到安装目录中,并将配置文件中的daemonize改为yes,通过后台的方式启动Redis

 

5.启动Redis Server

*Redis Server一个进程中,包含了若干个线程,但只有一个线程用于处理客户端的请求(Redis单线程处理任务,不会出现共享变量不一致的问题)

 

6.启动Redis Client

*Redis Server中包含16个数据库,编号从0~15,每个数据库之间的数据相互独立,客户端默认连接的是第一个数据库,可以通过select num命令修改连接的数据库。 

 

6.Java中使用Redis

 

Jedis是Redis官方推荐的Redis Java客户端类库。

 

1.导入依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.1</version>
</dependency>

 

2.获取Redis连接

//1.直接创建Jedis实例
Jedis jedis = new Jedis(String host , int port);

//2.通过Jedis连接池来管理连接
JedisPoolConfig poolConfig = new JedisPoolConfig();
//最大连接数
poolConfig.setMaxTotal(int num);
//最大空闲连接数
poolConfig.setMaxIdle(int num);

//创建连接池对象
JedisPool jedisPool = new JedisPool(poolConfig , String host , int port);
//获取Redis连接
Jedis jedis = jedisPool.getResource();

*当Redis连接使用完毕后需要手动关闭。

 

3.使用Jedis提供的API操作Redis。

 

/**
 * @Auther: ZHUANGHAOTANG
 * @Date: 2019/4/2 17:11
 * @Description:
 */
public class RedisUtils {

    private static final String host = "192.168.2.90";

    private static final int port = 6379;

    private static JedisPool jedisPool = null;

    static {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //最大连接数
        poolConfig.setMaxTotal(10);
        //最大空闲连接数
        poolConfig.setMaxIdle(5);
        //创建连接池对象
        jedisPool = new JedisPool(poolConfig, host, port);
    }

    public static Jedis getConnection() {
        return jedisPool.getResource();
    }

}

 

阅读(2327) 评论(0)