Redis

redis 关系网 树 redis和关系型数据库的区别_数据库

Redis介绍

NoSQL和关系型数据库的区别

  • 在关系型数据库数据都是存放在表中,有分类存放,连接查询,主键,外键等概念
  • NoSQL泛指非关系型数据库,采用区别于关系型数据库的设计,主要是针对关系型数据库性能瓶颈来设计的,专门处理关系型数据库不擅长做的业务场景,不同的NoSQL针对的点不一样,大致分为以下几类:
  • 键值存储: Redis 多用于项目的高速缓存
  • 文档存储: MongoDB 广泛用于社交类应用
  • 文件存储: FastDFS 多用于以文件为载体的在线服务,如相册网站/视频网站等等
  • 列式存储: HBase 主要用于数据分析领域

Redis的数据结构

Redis是属于键值存储的NoSQL数据库,该数据库主要是提供高性能的键值存储,可以简答的理解为是一个极其高性能的超大Map,由于这种数据库的数据结构比较简单,所以没有关系型数据库那么多的功能,如:

  • Redis中事务只有成功,没有失败
  • 没有表的概念和表相关的操作
  • 单线程执行,没有线程安全问题

Redis支持的数据类型:

  • string
  • hash
  • list
  • set
  • zset

Redis的优势

性能极高 – Redis能支持超过 10W次每秒的读写频率。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
丰富的特性 – Redis还支持 publish/subscribe(发布/订阅), 通知, key 过期等等特性。

下面是官方的bench-mark数据:
测试完成了50个并发执行100000个请求。
设置和获取的值是一个256字节字符串。
Linuxbox是运行Linux2.6,这是X3320Xeon2.5ghz。
文本执行使用loopback接口(127.0.0.1)。
结果:读的速度是110000次/s,写的速度是81000次/s。

Redis支持的数据类型

string类型

普通的字符串类型,表示一个简单值

redis 关系网 树 redis和关系型数据库的区别_Redis_02

命令
set key value -> 存入键值对
get key -> 根据键取出值
getset key value -> 返回旧值后存入新值
incr key -> 把值递增1
decr key -> 把值递减1
incrby key num -> 偏移值
append key 'value' -> 原值后拼接新内容
setnx key value -> 存入键值对,键存在时不存入
setex key timeout value -> 存入键值对,timeout表示失效时间,单位s
ttl ->可以查询出当前的key还剩余多长时间过期
setrange key index value -> 修改键对应的值,index表示开始的索引位置
mset k1 v1 k2 v2 ... -> 批量存入键值对
mget k1 k2 ... -> 批量取出键值
del key -> 根据键删除键值对

hash类型

hash类型 / hash对象,其实就是Map类型,其内部又可以有多个键值对,可以用于存储对象

redis 关系网 树 redis和关系型数据库的区别_Redis_03

命令
hset key hashkey hashvalue -> 存入一个hash对象
hget key hashkey -> 根据hash对象键取去值
hincrby key hashkey 递增值 -> 递增hashkey对应的值
hexists key hashkey -> 判断hash对象是含有某个键
hlen key -> 获取hash对象键的数量
hkeys key -> 获取hash对象的所有键
hvals key -> 获取hash对象的所有值
hgetall key -> 获取hash对象的所有数据
hdel key hashkey -> 根据hashkey删除hash对象键值对
同样有hsetnx,其作用跟用法和setnx一样

list类型

list类型更多的倾向队列,能直接操作首尾元素

redis 关系网 树 redis和关系型数据库的区别_spring_04

命令
rpush key value -> 往列表右边添加数据
lpush key value -> 往列表左边添加数据
lpop key -> 弹出列表最左边的数据
rpop key -> 弹出列表最右边的数据
lrange key start end -> 范围显示列表数据,全显示则设置0 -1 
linsert key before/after refVal newVal -> 参考值之前/后插入数据
lset key index value -> 根据索引修改数据
lrem key count value -> 在列表中按照个数删除数据
ltrim key start end -> 范围截取列表
lindex key index -> 根据索引取列表中数据
llen key -> 获取列表长度

set类型

跟Java中的set集合性质一样,底层使用哈希表实现的,存入的元素是无序不可重复的,我们可以通过Redis提供的命令来取交集,并集,差集

命令
sadd key value -> 往set集合中添加元素
smembers key -> 列出set集合中的元素
srem key value -> 删除set集合中的元素
spop key count -> 随机弹出集合中的元素
sdiff key1 key2 -> 返回key1中特有元素
sdiffstore var key1 key2 -> 返回key1中特有元素存入另一个set集合
sinter key1 key2 -> 返回两个set集合的交集
sinterstore var key1 key2 -> 返回两个set集合的交集存入另一个set集合
sunion  key1 key2 -> 返回两个set集合的并集
sunionstore var key1 key2 -> 返回两个set集合的并集存入另一个set集合
smove key1 key2 value -> 把key1中的某元素移入key2中
scard key -> 返回set集合中元素个数
sismember key value -> 判断集合是否包含某个值
srandmember key count -> 随机获取set集合中元素

zset类型

和set基本一样,但他是有序的

命令
zadd key num name -> 存入数值和名称
zrange key start end -> 按照数值升序输出名称
zrangebyscore key min max [withscores] -> 按照数值范围升序输出名称
zrevrange key start end -> 按照数值降序输出名称
zrevrangebyscore key max min [withscores] -> 按照数值范围降序输出名称
zrem key name -> 删除名称和数值
zincrby key num name -> 偏移名称对应的数值
zrank key name -> 升序返回排名
zrevrank key name -> 降序返回排名
zremrangebyscore key max min [withscores] -> 根据分数范围删除元素
zremrangebyrank key start end -> 根据排名删除元素
zcard key -> 返回元素个数
zcount key min max -> 按照分数范围统计个数

Redis的管理命令

管理key的命令

exists key -> 判断某个key是否存在
expire key second -> 设置key的过期时间
persist key -> 取消key的过期时间
select index -> 切换数据库索引,范围是0 ~ 15共16个分区
move key index -> 把某个key-value移动到其他索引中
rename oldKey newKey -> 把oldKey重命名为newKey
info -> 查看当前服务器信息
flushdb -> 清空当前库中的数据
flushall -> 清空所有库中的数据

设置密码

修改安装目录/redis.windows-service.conf配置文件,在443行位置,去掉注释

#在443行位置
requirepass 密码

此时我们就需要通过密码认证才能执行命令

方式1: redis客户端中 auth 密码

方式2: 命令行中 redis-cli.exe -a 密码

集成

Jedis基本使用

redis 关系网 树 redis和关系型数据库的区别_spring_05

准备环境

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version> 
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <!-- SpringBoot整合Spring Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!-- redis的驱动包:jedis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- SpringBoot打包插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

代码

在jedis中,API方法名跟Redis命令名称是完全一样的,也就是说只要调用jedis对象对应的方法就能完成相应的操作

如:

set name bunny ===> jedis.set(“name”, “bunny”);

get name ===> String val = jedis.get(“name”);

@Test
public void testJedisPool() {
    // 1:创建Jedis连接池
    JedisPool pool = new JedisPool("localhost", 6379);
    // 2:从连接池中获取Jedis对象
    Jedis jedis = pool.getResource();
    /* 设置密码
	jedis.auth(密码); */
    // 3:TODO
    System.out.println(jedis);
    // 4:关闭资源
    jedis.close();
    pool.destroy();
}

集成Spring Data Redis

依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置

#application.properties
spring.redis.host=localhost #默认值
spring.redis.port=6379 #默认值
spring.redis.password=admin #根据情况配置

代码

//直接注入框架封装好的StringRedisTemplate
@Autowired
private StringRedisTemplate redisTemplate;

@Test
public void testRedisTemplate() {
    // 操作string
    redisTemplate.opsForValue().xx();
    // 操作hash
    redisTemplate.opsForHash().xx();
    // 操作list
    redisTemplate.opsForList().xx();
    // 操作set
    redisTemplate.opsForSet().xx();
    // 操作zset
    redisTemplate.opsForZSet().xx();
}

注意:以上的xx表示命令的名称,如:set / put / get 等

Redis的优缺点

Redis的优点

  1. 速度快
    因为在内纯中,类似hashMap,hashmap的优势是查找和操作的时间复杂度都是零。Redis本质是一个key-value类型的数据库,Memcached,整个数据库操作都在内存中进行,定期通过异步操作把数据库数据flush到硬盘进行保存。因为是存内存操作,redis的性能非常出色,每秒超过10万次读写操作。是已知性能最快的key-value数据库。
  2. 支持丰富的数据类型
    支持String、List、Set、Sorted Set、Hash。
    Redis的出色不仅仅是性能,Redis最大的魅力是支持多种数据结构,此外单个value的最大限制是1g,因此Redis的可以实现很多功能,比如用它的List做FIOF双向链表,实现一个轻量级的高性能消息队列。
  3. 丰富的特性
    支持发布订阅(publish/subscribe)功能、key过期策略、事务、支持多个DB等。在5.0增加了Stream功能,一个新的强大的支持多播的可持久化的消息队列。
  4. 持久化存储
    Redis 提供 RDB 和 AOF 两种数据的持久化存储方案,解决内存数据库最担心的万一Redis 挂掉,数据会消失掉。
    【全量】RDB 持久化,是指在指定的时间间隔内将内存中的数据集快照写入磁盘。实际操作过程是,fork 一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
    【增量】AOF持久化,以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

Redis的缺点

由于 Redis 是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小。虽然 Redis 本身有 Key 过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。

修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中,Redis 不能提供服务。

Redis 有几种数据“过期”策略

Redis 提供了 3 种数据过期策略:

  1. 定时删除:定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间到的时候,立即执行对键的删除操作。
  2. 惰性删除:惰性删除策略,是指放任键过期不管,每次从键空间获取键的时候才去检查取得的键是否过期,如果过期的话,就删除该键,如果不过期,就返回该键。
  3. 定期删除:定期删除策略,是指每隔一段时间,程序会对数据进行一次检查,删除里面的过期键。