Redis学习总结

一,什么是Redis

Redis是一个使用C语言开发的一个开源的高性能数据库,以键值对的形式存储,Redis将数据放到内存中, 读取速度快,所以被广泛应用。

二,Redis的下载和安装

下载地址: https://redis.io/download/

2.1在虚拟机中安装C语言环境

由于Redis是C语言开发的,安装Redis需要C语言环境。

yum install gcc-c++

2.2 安装

将安装包拷到/usr/upload目录下解压
tar -zxvf redis-3.0.0.tar.gz

进入到解压后的目录进行编译
cd /usr/upload/redis-3.0.0
make

安装到指定目录
make install PREFIX=/usr/local/redis

2.3 启动

  1. 前端启动
直接运行bin/redis-server将以前端模式启动。
cd /usr/local/redis/bin
./redis-server

缺点: 命令窗口关闭会导致redis-server进程结束(前端启动的关闭方法:1,ctrl + c 2, 关闭命令窗口)
2. 后端启动

1,拷贝配置文件
cp /usr/upload/redis-3.0.0/redis.conf  /usr/local/redis/bin
2,修改配置文件
vim /usr/local/redis/bin/redis.conf
      daemonize yes
3,启动
       ./redis-server redis.conf
4,关闭
       ./redis-cli shutdown
5,链接 
       ./redis-cli     

三,Redis的基本命令

    keys *:查看所有key
    expire和ttl:设置和查看key的失效时间(秒)
    incr和decr:自增和自减
    exists:判断key值是否存在
    
    select (0~15): 切换数据库,一个redis实例最多可提供16个数据库,下标从**0****15**,
                   客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库,redis不支持修改数据库的名称,
                   只能通过select 0、select 1...选择数据库。
    FLUSHALL --清空所有数据库的所有数据
    FLUSHDB --清空当前所在数据库的数据               

四,Redis的五种数据类型

string ----> key value
赋值:set key value

取值:get key

删除:del key

自增自减:incr key  decr key
hash ----> key (key value) (key value)…
赋值:HSET key key value 

取值:HGET key field

删除:HDEL key field
list ----> key value value…

元素有顺序,可重复

赋值:lpush/rpush key value  value...
lpush 在数据的左边添加新数据
rpush 在数据的右边添加新数据

取值:lrange k 0 -1 

删除:lrem key  num value   num指删除几个    
set ----> key value value …

元素无顺序,不能重复

赋值:sadd key value value...

取值: smembers key

删除: srem key value
zset ----> zadd key score1 value1 (score2 value2)…

元素有顺序,不能重复

赋值:  zadd key score1 value1 (score2 value2)...
取值:  zrange key  0 -1 withscores
删除:  zrem key  num  value
127.0.0.1:6379> zadd set1 1 2 3 4 5 6 
(integer) 3
127.0.0.1:6379> zrange zset1 0 -1
(empty list or set)
127.0.0.1:6379> zrange zset1 0 -1 withscores
(empty list or set)
127.0.0.1:6379> zadd zset2 2 a 3 b 4 c 
(integer) 3
127.0.0.1:6379> zrange zset2 0 -1 
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> zrange zset2 0 -1 withscores
1) "a"
2) "2"
3) "b"
4) "3"
5) "c"
6) "4"

五,Redis的持久化

Redis的高性能是由于其将所有数据都存储在了内存中,而内存在断电后会丢失所有数据,为了使Redis在重启后仍能够保证数据不丢失,需要将数据从内存同步到硬盘中,就是持久化。

RDB持久化

RDB方式是通过快照完成的,当符合一定条件时Redis会自动将内存中的数据发起快照并保存到硬盘中。
RDB是Redis默认使用的持久化方式,在redis.conf配置文件中有以下配置

save 900 1  #900秒内容如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000 #表示60秒内如果超过10000个key被修改,则发起快照保存

  优点:不影响性能
  缺点:不能保证数据的完整性
AOF持久化

AOF持久化,是将Redis执行的命令记录到日志文件中,当启动Redis时会从持久化的日志文件中恢复数据。

redis.conf开启AOF
appendonly yes

AOF持久化策略
# appendfsync always
appendfsync everysec
# appendfsync no

优点: 可以保证数据的完整性
缺点: 会影响性能,AOF文件会比较大,

两种持久化方案的对比
AOF文件更新频率要比RDB高,且AOF要比RDB恢复数据慢
AOF会比RDB更安全,但是文件会更大
RDB的性能要比AOF好
如果RDB和AOF都开启了,则优先加载AOF.

六,主从复制

持久化保证了即使redis服务重启也会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障。

主从配置
主redis无需配置

修改从redis的redis.conf配置文件,添加主的IP和端口
slaveof <masterip> <masterport>
主从复制过程
复制过程说明:

1、  slave 服务启动,slave 会建立和master 的连接,发送sync 命令。

2、master启动一个后台进程将数据库快照保存到RDB文件中

3、master 就发送RDB文件给slave

4、slave 将文件保存到磁盘上,然后加载到内存恢复

5、master把缓存的命令转发给slave

注意:主死了,从只能读 

七,Redis集群

1,Redis集群的架构

在这里插入图片描述

(1)所有的redis节点彼此互联(PING-PONG机制),节点的fail是
通过集群中超过半数的节点检测失效时才生效.
也就是说集群至少需要三台。

在这里插入图片描述

(2)存取数据时连接任一节点都可以,但集群中有一个节点fail整个集群都会fail

原因是:
   Reids集群中内置了16384个哈希槽,当需要在集群中防止一个值时,
   会先对key使用crc16算法计算,然后对16384进行求余,获得[0~16383]。
   这样,每个key都会对应一个哈希槽,redis会根据集群的数量将哈希槽进行大致均等的
   分配到各个节点。因此当集群中的任意一个节点挂掉都会导致部分哈希槽丢失,
   导致整个集群失效。
2,Redis集群的搭建

由于上述原因,所以Redis集群中至少应该有三个节点,为了保证集群的高可用,每个节点需要有一台备用机,也就是说一个高可用的Redis集群至少需要6台服务器。
在此,通过使用一台虚拟机运行6个Redi实例来模拟分布式环境
2.1 集群搭建环境
使用ruby脚本搭建集群,需要安装ruby。

yum install ruby
yum install rubygems
gem install redis-3.0.0.gem

2.2创建Redis实例
搭建伪分布式,需要6个redis实例放到/usr/local/redis-cluster目录下,并且运行在不同的端口7001-7006。
注意:必须删除dump.rdb和appendonly.aof文件
修改redis.conf配置文件

cluster-enabled yes

2.3启动每个实例
2.4使用ruby脚本搭建集群

./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005  192.168.25.153:7006
# 1 表示每个节点有一台备份
[root@localhost src]# ./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005  192.168.25.153:7006
>>> Creating cluster
Connecting to node 192.168.25.153:7001: OK
Connecting to node 192.168.25.153:7002: OK
Connecting to node 192.168.25.153:7003: OK
Connecting to node 192.168.25.153:7004: OK
Connecting to node 192.168.25.153:7005: OK
Connecting to node 192.168.25.153:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.25.153:7001
192.168.25.153:7002
192.168.25.153:7003
Adding replica 192.168.25.153:7004 to 192.168.25.153:7001
Adding replica 192.168.25.153:7005 to 192.168.25.153:7002
Adding replica 192.168.25.153:7006 to 192.168.25.153:7003
M: 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3 192.168.25.153:7001
   slots:0-5460 (5461 slots) master
M: 8cd93a9a943b4ef851af6a03edd699a6061ace01 192.168.25.153:7002
   slots:5461-10922 (5462 slots) master
M: 2935007902d83f20b1253d7f43dae32aab9744e6 192.168.25.153:7003
   slots:10923-16383 (5461 slots) master
S: 74f9d9706f848471583929fc8bbde3c8e99e211b 192.168.25.153:7004
   replicates 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3
S: 42cc9e25ebb19dda92591364c1df4b3a518b795b 192.168.25.153:7005
   replicates 8cd93a9a943b4ef851af6a03edd699a6061ace01
S: 8b1b11d509d29659c2831e7a9f6469c060dfcd39 192.168.25.153:7006
   replicates 2935007902d83f20b1253d7f43dae32aab9744e6
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.....
>>> Performing Cluster Check (using node 192.168.25.153:7001)
M: 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3 192.168.25.153:7001
   slots:0-5460 (5461 slots) master
M: 8cd93a9a943b4ef851af6a03edd699a6061ace01 192.168.25.153:7002
   slots:5461-10922 (5462 slots) master
M: 2935007902d83f20b1253d7f43dae32aab9744e6 192.168.25.153:7003
   slots:10923-16383 (5461 slots) master
M: 74f9d9706f848471583929fc8bbde3c8e99e211b 192.168.25.153:7004
   slots: (0 slots) master
   replicates 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3
M: 42cc9e25ebb19dda92591364c1df4b3a518b795b 192.168.25.153:7005
   slots: (0 slots) master
   replicates 8cd93a9a943b4ef851af6a03edd699a6061ace01
M: 8b1b11d509d29659c2831e7a9f6469c060dfcd39 192.168.25.153:7006
   slots: (0 slots) master
   replicates 2935007902d83f20b1253d7f43dae32aab9744e6
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost redis-cluster]# 

2.5连接
集群搭建完成后,可以通过连接任意一台redis来连接集群(所有的redis节点彼此互联(PING-PONG机制))

cluster info   #打印集群的信息

cluster nodes  #列出集群当前已知的所有节点(node),以及这些节点的相关信息 

八,Spring Data

1.1.Spring Data 介绍

Spring Data是一个用于简化数据库访问的开源框架。其主要目标是使得对数据的访问变得方便快捷,包含多个子项目:

  • Spring Data JDBC- 对JDBC的Spring Data存储库支持。

  • Spring Data JPA - 对JPA的Spring Data存储库支持。

  • Spring Data MongoDB - 对MongoDB的基于Spring对象文档的存储库支持。

  • Spring Data Redis - 从Spring应用程序轻松配置和访问Redis。

    … …

1.2.Spring Data Redis 介绍

Spring Data Redis 是属于 Spring Data 下的一个模块,作用就是简化对于 redis 的操做。

spring-data-redis针对jedis提供了如下功能:

  1. 提供了一个高度封装的“RedisTemplate”类,里面封装了对于Redis的五种数据结构的各种操作,包括:

     - redisTemplate.opsForValue():操作字符串
     - redisTemplate.opsForHash():操作hash
     - redisTemplate.opsForList():操作list
     - redisTemplate.opsForSet():操作set
     - redisTemplate.opsForZSet():操作zset
    
  2. SpringBoot2.x后RedisTemplate采用是lettuce(基于netty采用异步非阻塞式lO)进行通信,大并发下比jedis效率更高。

  3. RedisTemplate模板使用序列化器操作redis数据,预定义的序列化方案有:
    1,StringRedisSerializer :key或value是字符串时使用
    2,JdkSerializationRedisSerializer :pojo <----> 字节码 , 为乱码
    3,GenericJackson2JsonRedisSerializer :pojo <----> json 不乱码

1.3 RedisTemplate使用

引入依赖

 <!-- Spring Data Redis的启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

修改配置文件

spring:
  redis:
    cluster:
      nodes:
        - 192.168.204.131:7001
        - 192.168.204.131:7002
        - 192.168.204.131:7003
        - 192.168.204.131:7004
        - 192.168.204.131:7005
        - 192.168.204.131:7006
    jedis:
      pool:
        max-active: 20 #连接池最大连接数
        max-idle: 10 #连接池中的最大空闲连接
        min-idle: 5 # 连接池中的最小空闲连接

添加配置

/**
 * 完成对Redis的整合的一些配置
 */
@Configuration
public class RedisConfig {

    /**
     * 创建RedisTemplate:用于执行Redis操作的方法
     */
    @Bean
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory)    {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        return template;
    }
}

测试

import com.bjpowernode.RedisApp;
import com.bjpowernode.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {RedisApp.class})
public class RedisTest {

    //默认key-value的序列化器是JdkSerializationRedisSerializer
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 1、StringRedisSerializer:key或value是字符串时使用
     */
    @Test
    public void testSetStr(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.opsForValue().set("str", "张三丰");
    }

    @Test
    public void testGetStr(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String str = (String) redisTemplate.opsForValue().get("str");
        System.out.println(str);
    }

    /**
     * 2、JdkSerializationRedisSerializer:pojo<----->字节序列,大小243,乱码
     */
    @Test
    public void testSetPojo(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.opsForValue().set("user", user);
    }

    @Test
    public void testGetPojo(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        User user = (User) redisTemplate.opsForValue().get("user");
        System.out.println(user);
    }

    /**
     * GenericJackson2JsonRedisSerializer:pojo<------>json,大小74,不乱码
     */
    @Test
    public void testSetPojo2(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.opsForValue().set("user2", user);
    }

    @Test
    public void testGetPojo2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        User user2 = (User) redisTemplate.opsForValue().get("user2");
        System.out.println(user2);
    }

    /**
     * GenericJackson2JsonRedisSerializer处理String
     */
    @Test
    public void testSetStr2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.opsForValue().set("str2", "张三丰");
    }

    @Test
    public void testGetStr2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        String str2 = (String) redisTemplate.opsForValue().get("str2");
        System.out.println(str2);
    }

    /**
     * 使用通用的序列化器
     */
    @Test
    public void testSetPojo3(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.opsForValue().set("user3", user);
    }

    @Test
    public void testGetPojo3(){
        User user3 = (User) redisTemplate.opsForValue().get("user3");
        System.out.println(user3);
    }
}

设置通用序列化器

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);

        //设置通用序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值