Redis学习

一、介绍

  1. 由与用户量增大,请求数量也随之增大,数据压力过大
  2. 多台服务器之间数据不同步
  3. 多台服务器之间的锁已经不存在互斥性了
    Redis是基于内存存储数据和读取数据的
    可以将之前存在Session中的共享数据统一放在Redis中
    Redis基于它接受用户请求时单线程的,实现类似锁的功能

NoSQL

代表非关系型数据库not only sql

  1. Key-Value:Redis
  2. 文档型:ElasticSerch,Solr,Mongodb
  3. 面向列:hbase,cassandra
  4. 图形化:Neo4j

二、安装

version: '3.1'
services:
  redis:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis
    environment:
      - TZ=Asia/Shanghai
    ports:
      -6379:6379
    

和之前操作一样
创一个文件夹新建一个文件yml的,然后docker-compose up -d运行以下就行
在这里插入图片描述
在这里插入图片描述
下载redis官网的图形化操作软件之后的操作
在这里插入图片描述
在这里插入图片描述
其他不用动先

三、Redis常用命令

3.1Redis存储数据的结构

常用的物种数据结构
key-string:一个key对应一个值
key-hash: 一个key对应一个map(存储对象数据)
key-list:一个key对应一个列表 (使用list实现栈和队列结构)
key-set:一个key对应一个集合 (交集差集和并集的操作)
key-zset:一个key对应一个有序的集合 (排行榜)
另外三种
HyperLogLog:计算近似值
GEO:地理位置
BIT:一般存储的也是一个字符串,存储的时byte[]

在这里插入图片描述

3.2 string常用命令

1.添加值
set key value
2.取值
get key
3.批量操作
mset 、mget
4.自增命令(自增1)
incr key
5.自减功能
decr key
6.自增自减指定数量
incrby key increment
decrby key increment
7.设置值的同时,指定生成时间
setex key second value
8.设置值,如果当前key不存在,如果存在,什么事不发生
setnx key value
9.在key对应的value过后追加内容
append key value
10.查看value长度
strlen key

3.3 hash常用命令

1.存储数据
hset key field value
2.获取数据
hget key field 
3.批量操作
hmset key field value field value
hmget key field field ..
4.自增(指定自增的值)
hincrby key field increment 
5.设置值的方式
hsetnx key field value
6.检查field是否存在
hexists key field
7删除field的记录
hdel key field
8.获取当前哈希结构中的全部field和value
hgetall key
9获取全部field
hkeys key
#获取全部value
hvals key
11.获取field数量
hlen key

3.4list常用命令

1.存储数据
lpush key value ...
rpush key value.. 从右侧插入
2.存储数据 如果key不存在,或者不是list结构什么事都不做
lpushx key valuie 只能增加一个
rpushx key value
3.修改数据(指定索引位置,会覆盖索引位置的数据)
lset key index value
4.获取数据 弹栈方式(左侧或者右侧弹出数据)
lpop key 
rpop key
5.获取范围内的数据(stop-1代表最后一个)
lrang key start stop
6.指定索引位置的内容
lindex key index
7.获取整个列表的长度
llen key
8.删除(删除当前列表中count个value值,若是count>0从左侧向右侧删除小于0则容右侧向左侧删除 count==0删除全部value)
lrem key count value
9保留列表中范围内的数据
ltrim key start stop
10.将列表中最后一个数据,插入到另外一个列表头部位置
rpoplpush list1 list2

3.5set常用命令

#1.存储数据
sadd key member [member..]
2.获取全部数据
smembers key
3.随机获取(同时移除)
spop key
4.交集
sinter set1 set2...
5.并集
sunion set1 set2
6.差集
sdiff set1 set2 ...
7.删除数据(指定value)
srem key member [member..]
8.查看set是否包含这个值
sismember key member

3.6zset命令

1.添加数据(score必须是数值,member不允许重复)
zadd key score member(。。。)
2.修改member的分数(如果member存在key中,正常添加,如果member不存在,就相当于zadd
zincrby key increment member
3.查询(查看指定member的分数)
zscore key member 
4.查询数量
zcard key
5.查询score范围内的member数量
zount key min max
6.删除
zrem key member..
7.根据分数从小到大排序,获取指定范围内的,如果添加scop会返回member对应的分数
zrange key srart stop [withscore]
8.根据分数从大到小排序,获取指定范围内的,如果添加scop会返回member对应的分数
zrevrange key start stop [withscore]
9.zrangebyscore key min max [withscore]] [limit offset count]
10.
zrevrangebyscore key max min [withscore] [limit offset count]
如果写(那就是小于但不等于的方式找  +inf -inf最大值和最小值

3.7key命令

1.全部key
keys pattern 
2.查看某一个key是否存在
exists key(1存在 0不存在)
3.删除key
del key。。
4.设置key的生存时间
expire key second
pexpire key milloseconds
5.设置时间点
expireat key timestamp
pxeprieat key milloseconds
6.查看剩余时间
ttl key 
pttl key    	-2 当前key不存在 -1 没有设置时间 
7.移除生成时间
persist key   (1移除成功 0 不存在生存时间 或者key不存在
8.操作库
select 0~15
9移动库
move key 0~15

3.8库的常用命令

1.清空当前所在的库
flushdb
2.清空全部
flushall
3.查看当前数据库有多少key
dbsize
4.最后一次操作时间
lastsave 
5.实时监控redis服务接收到的命令
monitor

Java连接redis

  1. jedis连接
  2. lettuce连接redis

4.1

  1. 创建Maven项目
  2. 导入依赖
  3. 测试
	<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>
    </dependencies>
    public static void main(String[] args) {
        /*连接redis*/
        Jedis jedis=new Jedis("192.168.0.106",6379);
        /*操作redis*/
        jedis.set("name","李四");
        /*释放资源*/
        jedis.close();
    }

4.2存储对象

 @Test
    public  void setByteArray(){
        Jedis jedis=new Jedis("192.168.0.106",6379);
        /*准备key-value*/
        String key="user";
        User user=new User(1,"张三");
        /*将key和value转换成byte【】*/
        byte[] value=SerializationUtils.serialize(user);
        byte[] keys = SerializationUtils.serialize(key);
        /*存储到redis*/
        jedis.set(keys,value);
        /*释放资源*/
        jedis.close();
    }
   @Test
    public void getall(){
        Jedis jedis=new Jedis("192.168.0.106",6379);
        /*准备key*/
        String key="user";
        /*将key装换位byte*/
        byte[] keys=SerializationUtils.serialize(key);
        /*jedis去redis、获取value*/
        byte[] value=jedis.get(keys);
        /*将value反序列化*/
        User user=(User)SerializationUtils.deserialize(value);
        /*输出*/
        System.out.println(user);
        /*释放资源*/
        jedis.close();
    }
		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

Jedis连接池

   @Test
    public void pool(){
        /*创建连接池*/
        JedisPool pool=new JedisPool("192.168.0.106",6379);
        /*通过连接词获得对象*/
        Jedis jedis=pool.getResource();
        String value=jedis.get("user");
        System.out.println(value);
        jedis.close();
    }
   @Test
    public void pool2(){
        /*创建连接池的连接信息*/
        GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(100);/*连接池中最大的活跃数*/
        poolConfig.setMaxIdle(10);/*最大空弦数*/
        poolConfig.setMinIdle(5);
        poolConfig.setMaxWaitMillis(3000);/*当连接池空了,多久没获取到连接池,就超时*/
        /*创建连接池*/
        JedisPool pool=new JedisPool(poolConfig,"192.168.0.106",6379);
        Jedis jedis=pool.getResource();
        String value=jedis.get("user");
        System.out.println(value);
        jedis.close();
    }

5.1redis管道操作\

解决如下问题
在这里插入图片描述
解决方案
在这里插入图片描述

@Test
    public void pipeline(){
        long i=System.currentTimeMillis();
        /*创建连接池*/
        JedisPool jedisPool=new JedisPool("192.168.0.106",6379);

   /*     *//*获取一个连接对象*//*
        Jedis jedis=jedisPool.getResource();

        *//*执行ince-100000*//*
        for (int j = 0; j <10000 ; j++) {
            jedis.incr("pp");
        }
        *//*释放资源*//*
        jedis.close();*/
        /*管道的方式*/
        /*获取一个连接对象*/
        Jedis jedis1=jedisPool.getResource();
        /*创建管道*/
        Pipeline pipeline=jedis1.pipelined();
        /*执行ince*/
        for (int j = 0; j <10000 ; j++) {
            pipeline.incr("qq");
        }
        /*执行命令*/
        pipeline.syncAndReturnAll();
        /*释放资源*/
        jedis1.close();
        System.out.println(System.currentTimeMillis()-i);
    }

时间减少了很多倍

5.2修改配置文件

version: '3.1'
services:
  redis:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 6379:6379
    volumes:
      - ./conf/redis.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]

增加密码

在conf目录下的redis.conf里面添加如下代码
requirepass xxxx
这样再次重启redis容器然后进入redis-cli后会要求你输入密码
auth xxx (这是校验的代码)
在java代码中可以通过连接池的构造函数传入密码
在linux中可以通过在redis-cli中输入
config set requirepass xxxx

    @Test
    public void pool2(){
        /*创建连接池的连接信息*/
        GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(100);/*连接池中最大的活跃数*/
        poolConfig.setMaxIdle(10);/*最大空弦数*/
        poolConfig.setMinIdle(5);
        poolConfig.setMaxWaitMillis(3000);/*当连接池空了,多久没获取到连接池,就超时*/
        /*创建连接池*/
        JedisPool pool=new JedisPool(poolConfig,"192.168.0.106",6379,3000,"xxxx");
        Jedis jedis=pool.getResource();
        String value=jedis.get("user");
        System.out.println(value);
        jedis.close();
    }

5.3Redis事务

Redis事务,一次事务操作,该成功的成功,该失败的失败
先开启事务,执行一些命令,但是不会立即执行,会被放在队列中,如果执行事务,那么这个队列中的命令全部执行,如果取消了事务,一个队列中的命令全部作废

  1. 开启事务:multi
  2. 输入要执行的命令->被放到队列中
  3. 执行事务:exec
  4. 取消事务:discard
    watch监听机制
    在开启事务之前,先通过watch命令去监听一个或多个key,在开启事务之后,如果由其他个客户端修改了我监听的key,事务会自动取消

5.4redis持久化机制

rdbcompression yes

dbfilename dump.rdb

rdb是redis默认的持久化机制
1.RDB持久化文件速度比较快,而且存储的是一个二进制文件,传输起来方便
2. 持久化的时间
3. save 900 1  在900秒内,有一个key改变了,就执行rdb持久化
	save 300 10
	save 60 10000
4,无法保证数据的绝对安全
文件存到了之前yml配置下的data路径 可通过cat查看
最后shutdown save即可以持久化了

5.5AOF

#开启AOF持久化
appendonly yes
#aof文件的名称
appendfilename "redis.aof"
#aof持久化执行的时机
# appendfsync always
appendfsync everysec
# appendfsync no
最后shutdown nosave也可以持久化
1.aof持久化相对于rdb较慢的,存储的是一个文本文件,到了后期文件会比较大,传输困难
2.时机
# appendfsync always  没执行一个写操作,立即持久化到aof文件中,性能比较低
appendfsync everysec 每秒执行一次持久化
# appendfsync no 根据你的操作系统不同,环境不同,在一定时间内执行一次持久化
3.AOF相对RDB更安全,推荐同时开启AOF和RDB
4.如果同时开启RDB和AOF持久化,那么在Redis宕机重启之后,需要加载一个持久化文件,优先选择AOF文件。
5.如果先开启RDB,在开启AOF,如果RBD执行了持久化,那么RDB文件中的内容会被AOF覆盖掉

5.5主从架构

分担读写的压力,相对于之前的单机版的redis,主从架构的redis有多个redis,并且各司其职
在这里插入图片描述

version: '3.1'
services:
  redis1:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis1
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7001:6379
    volumes:
      - ./conf/redis1.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis2:
    image:  daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis2
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7002:6379
    volumes:
      - ./conf/redis2.conf:/usr/local/redis/redis.conf
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis3:
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7003:6379
    volumes:
      - ./conf/redis3.conf:/usr/local/redis/redis.conf
    links:
      - redis1:master
    command: ["redis-server","/usr/local/redis/redis.conf"]




#从节点配置
replicaof master 6379

在这里插入图片描述

问题:如果master挂掉了,整个redis架构i就挂掉了

5.6哨兵

在这里插入图片描述

#哨兵需要后台启动
daemonize yes
#指定master节点的ip
sentinel monitor master localhost 6379 2(主的)
sentinel monitor master master 6379 2(sleve)
#哨兵每隔多久执行一次
sentinel down-after-milliseconds mymaster 10000

在这里插入图片描述
在这里插入图片描述
启动哨兵
在这里插入图片描述
每个redis都要启动一次包括redis2和3的

5.7集群搭建

Redis集群在保证主从 加哨兵的基本功能之外,还能提升存储数据的能力

在这里插入图片描述

#dicker-compose.yml
version: '3.1'
services:
  redis1: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis1
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7001:7001
      - 17001:17001
    volumes:
      - ./conf/redis1.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"] 
  redis2: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis2
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7002:7002
      - 17002:17002
    volumes:
      - ./conf/redis2.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis3: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7003:7003
      - 17003:17003
    volumes:
      - ./conf/redis3.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis4: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis4
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7004:7004
      - 17004:17004
    volumes:
      - ./conf/redis4.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis5: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis5
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7005:7005
      - 17005:17005
    volumes:
      - ./conf/redis5.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis6: 
    image: daocloud.io/library/redis:5.0.7
    restart: always
    container_name: redis6
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7006:7006
      - 17006:17006
    volumes:
      - ./conf/redis6.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]

以下内容放在conf目录下,每一个redis都要有一个

#指定端口号
port 7001
#开启集群
cluster-enable yes
#集群信息的文件
cluster-config-file nodes-7001.conf
#集群对外ip地址
cluster-announce-ip 192.168.0.106
cluster-announce-port 7001
#集群总线端口
cluster-announce-bus-port 17001

在启动的时候,搭建集群代码
redis-cli --cluster create 192.168.0.106:7001 192.168.0.106:7002 192.168.0.106:7003 192.168.0.106:7004 192.168.0.106:7005 192.168.0.106:7006 --cluster-replicas 1(有几个从节点,只管备份的)
启动时redis redis-cli -h 192.168.0.106 -p 7001就会在之后增加数据时自动计算加在哪一个集群中。
用java连接
Set nodes=new HashSet<>();
nodes.add(new HostAndPort(“192.168.0.106”,7001));
nodes.add(new HostAndPort(“192.168.0.106”,7002));
nodes.add(new HostAndPort(“192.168.0.106”,7003));
nodes.add(new HostAndPort(“192.168.0.106”,7004));
nodes.add(new HostAndPort(“192.168.0.106”,7005));
JedisCluster jedisCluster=new JedisCluster(nodes);
jedisCluster.get(“a”);

常见问题

6.1如果key的生存时间到了,会立即删除嘛?

  1. 定期删除
    Redis每个一段时间就回去查看Redis设置了过期时间的key,会在100ms的见各种默认查看3个key
  2. 惰性删除
    如果去查询已经过了生存时间的key,Redis会先查看当前key的生存时间,是否已经到了,直接删除key,返回用户一个控制。

6.2Reids的淘汰机制

在Redis中内存已经满的时候添加了新的策略,会进行淘汰机制。
#volatile-lru:在内存不足时,Redis会在是指过了生存时间的key中干掉一个最近最少使用的key
#allkeys-lru:在全部key中干掉一个最近最少使用的
#volatile-lfu:Redis会在设置了生存时间的key中干掉一个最近最少频次使用的key
#allkey-lfu;Redis会在全部的key中干掉一个最近最少频次使用的key
#volatile-random:Redis会在设置了生存时间的key中随机干掉一个
#allkey-random:Redis会在全部的key中随机干掉一个
#volatile-ttl:会在设置过生存时间的key中剩余时间最少的key
#noeviction:直接报错
maxmemory-policy 规则
maxmemory 字节大小

6.3缓存问题

缓存穿透
在这里插入图片描述

缓存击穿
在这里插入图片描述
缓存雪崩
在这里插入图片描述
缓存倾斜
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值