IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis -> 正文阅读

[大数据]Redis

一、 Redis简介

1 NoSQL简介

目前市场主流数据存储都是使用关系型数据库。每次操作关系型数据库时都是I/O操作,I/O操作是主要影响程序执行性能原因之一,连接数据库关闭数据库都是消耗性能的过程。尽量减少对数据库的操作,能够明显的提升程序运行效率。
针对上面的问题,市场上就出现了各种NoSQL(Not Only SQL,不仅仅可以使用关系型数据库)数据库,它们的宣传口号:不是什么样的场景都必须使用关系型数据库,一些特定的场景使用NoSQL数据库更好。
常见NoSQL数据库:
memcached :键值对,内存型数据库,所有数据都在内存中。
Redis:和Memcached类似,还具备持久化能力。
HBase:以列作为存储。
MongoDB:以Document做存储。

2 Redis简介

Redis是以Key-Value形式进行存储的NoSQL数据库。
Redis是使用C语言进行编写的。
平时操作的数据都在内存中,效率特高,读的效率110000/s,写81000/s,所以多把Redis当做缓存工具使用。
Redis以solt(槽)作为数据存储单元,每个槽中可以存储N多个键值对。Redis中固定具有16384。理论上可以实现一个槽是一个Redis。每个向Redis存储数据的key都会进行crc16算法得出一个值后对16384取余就是这个key存放的solt位置。
同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。

二、 Redis单机版安装

1.安装依赖C语言依赖

redis使用C语言编写,所以需要安装C语言库

# yum install -y gcc-c++ automake autoconf libtool make tcl 

2.上传并解压

把redis-5.0.5.tar.gz上传到/root/upload中
解压文件

# cd /root/upload
# tar zxf redis-5.0.5.tar.gz

3.编译并安装

进入解压文件夹

# cd /root/upload/redis-5.0.5/

编译

# make

安装

# make install PREFIX=/usr/local/redis

4.开启守护进程

复制cd /root/upload/redis-5.0.5/中redis.conf配置文件

# cp  redis.conf  /usr/local/redis/

修改配置文件

# cd  /usr/local/redis/
# vi  redis.conf

把daemonize的值由no修改为yes
在这里插入图片描述

5.修改外部访问

在redis5中需要修改配置文件redis.conf允许外部访问。需要修改两处。
注释掉下面
bind 127.0.0.1
在这里插入图片描述

protected-mode yes 改成 no
在这里插入图片描述

6.启动并测试

启动redis

# cd /usr/local/redis/
# bin/redis-server redis.conf

重启redis

# bin/redis-cli shutdown
# bin/redis-server redis.conf

启动客户端工具

#bin/redis-cli 

在redis5中客户端工具对命令会有提供功能。

三、 Redis常用命令

Redis中数据是key-value形式,key为字符串类型,value可取类型如下:

? String 字符串
? Hash 哈希表
? List 列表
? Set 集合
? Sorted Set 有序集合

Redis命令相关手册有很多,下面为其中比较好用的两个

https://www.redis.net.cn/order/
http://doc.redisfans.com/

1 Key操作

1.1 exists

判断key是否存在。
语法:exists key名称
返回值:存在返回数字,不存在返回0

1.2 expire

设置key的过期时间,单位秒
语法:expire key 秒数
返回值:成功返回1,失败返回0

1.3 ttl

查看key的剩余过期时间
语法:ttl key
返回值:返回剩余时间,如果不过期返回-1,如key不存在返回-2

1.4 del

根据key删除键值对。
语法:del key [key…]
返回值:被删除key的数量

1.5 keys

查看当前redis中的key数据
语法: keys 表达式 如: keys *
返回值:符合表达式的key列表

2 字符串值(String)

2.1 set

设置指定key的值
语法:set key value
返回值:成功OK

2.2 get

获取指定key的值
语法:get key
返回值:key的值。不存在返回nil

2.3 setnx

当且仅当key不存在时才新增。
语法:setnx key value
返回值:不存在时返回1,存在返回0

2.4 setex

设置key的存活时间,无论是否存在指定key都能新增,如果存在key覆盖旧值。同时必须指定过期时间。
语法:
语法:setex key seconds value
返回值:OK

3 哈希表(Hash)

Hash类型的值中包含多组field value。

3.1 hset

给key中field设置值。
语法:hset key field value
返回值:成功1,失败0

3.2 hget

获取key中某个field的值
语法:hget key field
返回值:返回field的内容

3.3 hmset

给key中多个filed设置值
语法:hmset key field value field value
返回值:成功OK

3.4 hmget

一次获取key中多个field的值
语法:hmget key field field
返回值:value列表

3.5 hkeys

获取key中所有的field的值
语法: hkeys key
返回值: field 列表

3.6 hvals

获取key中所有value的值
语法:hvals key
返回值:value列表

3.7 hgetall

获取所有field和value
语法:hgetall key
返回值:field和value交替显示列表

3.8 hdel

删除key中任意个field
语法:hdel key field field
返回值:成功删除field的数量,当删除key中所有的field,key自动删除。

4 列表(List)

4.1 rpush

向列表末尾中插入一个或多个值
语法;rpush key value value
返回值:列表长度

4.2 lrange

返回列表中指定区间内的值。可以使用-1代表列表末尾
语法:lrange list 0 -1
返回值:查询到的值

4.3 lpush

将一个或多个值插入到列表前面
语法:lpush key value value
返回值:列表长度

4.4 llen

获取列表长度
语法:llen key
返回值:列表长度

4.5 lrem

删除列表中元素。count为正数表示从左往右删除的数量。负数从右往左删除的数量。
语法:lrem key count value
返回值:删除数量。

5 集合(Set)

set和java中集合一样。
5.1 sadd

向集合中添加内容。不允许重复。
语法:sadd key value value value
返回值:本次命令新增数据个数

5.2 scard

返回集合元素数量
语法:scard key
返回值:集合长度

5.3 smembers

查看集合中元素内容
语法:smembers key
返回值:集合中元素

5.4 srem

删除集合中的元素
语法: srem key member [member…]
返回值:删除元素个数

6 有序集合(Sorted Set)

有序集合中每个value都有一个分数(score),根据分数进行排序。
6.1 zadd

向有序集合中添加数据
语法:zadd key score value score value
返回值:新增的元素个数

6.2 zrange

返回区间内容,withscores表示带有分数
语法:zrange key 区间 [withscores]
返回值:值列表

6.3 zrem

删除集合内容
语法: zrem key member [member …]
返回值: 删除元素个数

四、 Redis持久化策略

Redis不仅仅是一个内存型数据库,还具备持久化能力。

1 RDB

rdb模式是默认模式,可以在指定的时间间隔内生成数据快照(snapshot),默认保存到dump.rdb文件中。当redis重启后会自动加载dump.rdb文件中内容到内存中。
用户可以使用SAVE(同步)或BGSAVE(异步)手动保存数据。
可以设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令,可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令。
  例如:
  save 900 1
  save 300 10
  save 60 10000
  那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行
  服务器在900秒之内,对数据库进行了至少1次修改
  服务器在300秒之内,对数据库进行了至少10次修改
  服务器在60秒之内,对数据库进行了至少10000次修改

1.1 优点

rdb文件是一个紧凑文件,直接使用rdb文件就可以还原数据。
数据保存会由一个子进程进行保存,不影响父进程。
恢复数据的效率要高于aof

1.2 缺点

每次保存点之间,因redis不可意料的关闭,可能会导致丢失数据。
由于每次保存数据都需要fork()子进程,在数据量比较大时可能会比较耗费性能。

2 AOF

AOF默认是关闭的,需要在配置文件中开启AOF。Redis支持AOF和RDB同时生效,如果同时存在,AOF优先级高于RDB(Redis重新启动时会使用AOF进行数据恢复)
监听执行的命令,如果发现执行了修改数据的操作,同时直接同步到数据库文件中。
2.1 优点

相对RDB数据更加安全。

2.2 缺点

相同数据集AOF要大于RDB。
相对RDB可能会慢一些。

2.3 开启办法

修改redis.conf中

# 默认no
appendonly yes
# aof文件名
appendfilename "appendonly.aof"

五、 Redis主从复制

Redis支持集群功能。为了保证单一节点可用性,redis支持主从复制功能。每个节点有N个复制品(replica),其中一个复制品是主(master),另外N-1个复制品是从(Slave),也就是说Redis支持一主多从。
一个主可有多个从,而一个从又可以看成主,它还可以有多个从。

1 主从优点

增加单一节点的健壮性,从而提升整个集群的稳定性。(Redis中当超过1/2节点不可用时,整个集群不可用)
从节点可以对主节点数据备份,提升容灾能力。
读写分离。在redis主从中,主节点一般用作写(具备读的能力),从节点只能读,利用这个特性实现读写分离,写用主,读用从。

2 一主多从搭建

在已经搭建的单机版redis基础上进行操作。
并且关闭redis单机版

六、 哨兵(Sentinel)

在redis主从默认是只有主具备写的能力,而从只能读。如果主宕机,整个节点不具备写能力。但是如果这是让一个从变成主,整个节点就可以继续工作。即使之前的主恢复过来也当做这个节点的从即可。
Redis的哨兵就是帮助监控整个节点的,当节点主宕机等情况下,帮助重新选取主。
Redis中哨兵支持单哨兵和多哨兵。单哨兵是只要这个哨兵发现master宕机了,就直接选取另一个master。而多哨兵是根据我们设定,达到一定数量哨兵认为master宕机后才会进行重新选取主。我们以多哨兵演示。

1 没有哨兵下主从效果

只要杀掉主,整个节点无法在写数据,从身份不会变化,主的信息还是以前的信息。

2 搭建多哨兵

前提:安装了单机的redis

七、 集群(Cluster)

前提:已经安装好redis单机版。
当集群中超过或等于1/2节点不可用时,整个集群不可用。为了搭建稳定集群,都采用奇数节点。

1 复制redis配置文件

从/usr/local/redis/bin下把redis.conf复制到当前目录中,命名为redis-7001.conf

# cp /usr/local/redis/bin/redis.conf /usr/local/redis/bin/redis-7001.conf

2 修改redis-7001.conf

# cd /usr/local/redis/bin
# vim redis-7001.conf

需要修改如下
port 7001
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 15000

# appendonly yes 如果开启aof默认,需要修改为yes。如果使用rdb,此处不需要修改
daemonize yes
protected-mode no
pidfile /var/run/redis_7001.pid

3 复制配置文件,并修改内容

把redis-7001.conf 复制5份,分别叫做redis-7002.conf、redis-7003.conf、redis-7004.conf、redis-7005.conf、redis-7006.conf

# cp redis-7001.conf redis-7002.conf
# cp redis-7001.conf redis-7003.conf
# cp redis-7001.conf redis-7004.conf
# cp redis-7001.conf redis-7005.conf
# cp redis-7001.conf redis-7006.conf

新复制的5个配置文件都需要需改三处。

例如nodes-7002.conf中需要把所有7001都换成7002。
可以使用 :%s/7001/7002/g 进行全局修改。
port 7002
cluster-config-file nodes-7002.conf
pidfile /var/run/redis_7002.pid

4 启动6个redis

执行之前一定要先删除dump.rdb

# 可以使用redis-server结合6个配置文件进行启动6个实例。
# rm -f dump.rdb
# vim startup.sh
	./redis-server redis-7001.conf
	./redis-server redis-7002.conf
	./redis-server redis-7003.conf
	./redis-server redis-7004.conf
	./redis-server redis-7005.conf
	./redis-server redis-7006.conf
# chmod a+x startup.sh

启动

# ./startup.sh

5 查看启动状态
在这里插入图片描述

6 建立集群

在redis3的时候需要借助ruby脚本实现集群。在redis5中可以使用自带的redis-cli实现集群功能,比redis3的时候更加方便了。
建议配置静态ip,ip改变集群失效

# ./redis-cli --cluster create 192.168.14.129:7001 192.168.14.129:7002 192.168.14.129:7003 192.168.14.129:7004 192.168.14.129:7005 192.168.14.129:7006 --cluster-replicas 1

7 测试
集群测试时,千万不要忘记最后一个-c参数。

# ./redis-cli -p 7001 -c
# set age 18

8 编写关闭脚本

# vim stop.sh
# chmod a+x stop.sh
	./redis-cli -p 7001 shutdown
	./redis-cli -p 7002 shutdown
	./redis-cli -p 7003 shutdown
	./redis-cli -p 7004 shutdown
	./redis-cli -p 7005 shutdown
	./redis-cli -p 7006 shutdown

八、 Jedis

Redis给Java语言提供了客户端API,称之为Jedis。
(Jedis API和Redis 命令几乎是一样的。Jedis API特别简单,基本上都是创建对象调用方法即可。)

1 单机版

public void testStandalone(){
    Jedis jedis = new Jedis("192.168.14.129",6379);
    jedis.set("name","bjsxt-standalone");
    String value = jedis.get("name");
    System.out.println(value);
}

2 带有连接池

public void testPool(){
    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    jedisPoolConfig.setMaxTotal(20);
    jedisPoolConfig.setMaxIdle(5);
    jedisPoolConfig.setMinIdle(3);
    JedisPool jedisPool = new JedisPool(jedisPoolConfig,"192.168.14.129",6379);
    Jedis jedis = jedisPool.getResource();
    jedis.set("name","bjsxt-pool");
    String value = jedis.get("name");
    System.out.println(value);
}

3 集群

public void testCluster(){
    Set<HostAndPort> set = new HashSet<>();
    set.add(new HostAndPort("192.168.14.129",7001));
    set.add(new HostAndPort("192.168.14.129",7002));
    set.add(new HostAndPort("192.168.14.129",7003));
    set.add(new HostAndPort("192.168.14.129",7004));
    set.add(new HostAndPort("192.168.14.129",7005));
    set.add(new HostAndPort("192.168.14.129",7006));
    JedisCluster jedisCluster = new JedisCluster(set);
    jedisCluster.set("name","bjsxt");
    String value = jedisCluster.get("name");
    System.out.println(value);
}

九、 使用SpringBoot整合SpringDataRedis操作redis

Spring Data是Spring公司的顶级项目,里面包含了N多个二级子项目,这些子项目都是相对独立的项目。每个子项目是对不同API的封装。
所有Spring Boot整合Spring Data xxxx的启动器都叫做spring-boot-starter-data-xxxx
Spring Data 好处很方便操作对象类型。
把Redis不同值得类型放到一个opsForXXX方法中。
opsForValue : String值
opsForList : 列表List
opsForHash: 哈希表Hash
opsForZSet: 有序集合Sorted Set
opsForSet : 集合

1 添加依赖

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

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

2 配置配置文件
spring.redis.host=localhost 默认值
spring.redis.port=6379 端口号默认值

spring:
  redis:
    host: 192.168.14.129

3 编写配置类

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        //RedisConnectionFactory是配置文件对应的Factory
        
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        
        //配置key和value的序列化器。不适用默认的jdk序列化,使用json序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
	
		//如果使用hash数据类型。可以提供格外的序列化器
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        
        return redisTemplate;
    }
}

4.1 编写对象新增

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Test
public void testString() {
    People peo = new People(1, "张三");
    redisTemplate.opsForValue().set("peo1", peo);
}

4.2 编写对象获取
此处必须编写值序列化器。不指定时返回类型为LinkedHashMap

@Test
public void testGetString() {
	
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<People>(People.class));
    People peo = redisTemplate.opsForValue().get("peo1");
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
    
    System.out.println(peo);
}

5.1 编写存储List

@Test
public void testList() {
    List<People> list = new ArrayList<>();
    list.add(new People(1, "张三"));
    list.add(new People(2, "李四"));
    redisTemplate.opsForValue().set("list2", list);
}

5.2 编写List取值

@Test
public void testGetList(){
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<List>(List.class));
    List<People> list2 = redisTemplate.opsForValue().get("list2");
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
    System.out.println(list2);
}

十、使用GenericJackson2JsonRedisSerializer序列化器和Jackson2JsonRedisSerializer序列化器的区别(建议使用Jackson2JsonRedisSerializer序列化器)

1 改配置类

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        
        //配置key和value的序列化器。不适用默认的jdk序列化,使用json序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
	
		//如果使用hash数据类型。可以提供格外的序列化器
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        return redisTemplate;
    }
}

2.1 编写对象新增

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Test
public void testString() {
    People peo = new People(1, "张三");
    redisTemplate.opsForValue().set("peo1", peo);
}

2.2 编写对象获取
此处不需要编写值序列化器。GenericJackson2JsonRedisSerializer序列化时会把自定义类型保存在数据中

@Test
public void testGetString() {
	
	//redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<People>(People.class));
	//不需要写上面这行,GenericJackson2JsonRedisSerializer序列化时会把自定义类型保存在数据中,所以占用内存相对大了,---不建议用,容易出现notfound错误,因为分布式应用中获取值时可能没有对应的(序列化时的自定义类型)
    People peo = redisTemplate.opsForValue().get("peo1");
    
    System.out.println(peo);
}
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-10-25 12:36:07  更:2021-10-25 12:38:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:00:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码