Redis理论

15 篇文章 0 订阅
4 篇文章 0 订阅

Redis

远程字典服务

内存存储,持久化,rdb,aof

高速缓存

发布订阅信息

地图信息分析

计时器,计数器

集群,事务,持久化,多种多样的数据类型

Nosql

Nosql:Not Only SQL(不仅仅是sql)

数据之间没有关系,键值对存储,列存储

大数据高性能

数据类型多样性,不需要设计数据库

大数据的3V:

海量Volume

多样Variety

实时Velocity

大数据的3高:

高并发

高可拓

高性能

阿里巴巴数据架构演进:

在这里插入图片描述

在这里插入图片描述

安装:

使用docker安装

默认安装最新版

docker pull redis

挂载配置文件:

建立以下目录 /home/redis/myredis/data

复制以下文件到 /home/redis/myredis/redis.conf

在这里插入图片描述

docker run --restart=always --log-opt max-size=100m --log-opt max-file=2 -p 6379:6379 --name myredis -v /home/redis/myredis/myredis.conf:/etc/redis/redis.conf -v /home/redis/myredis/data:/data -d redis redis-server /etc/redis/redis.conf  --appendonly yes  --requirepass 000000

-v 数据挂载地址(就是上面的文件地址)

redis-server /etc/redis/redis.conf 以配置文件启动redis,加载容器内的conf文件,最终找到的是挂载的目录 /etc/redis/redis.conf

-requirepass 000000 设置密码 (不然会被当成矿机)

进入容器命令:

docker exec -it myredis redis-cli

输入密码:

auth 000000

000415

使用测试例:

get s1

本教程基于http://t.csdn.cn/OpzpC创建,修改为快速上线版

进入容器内部

docker exec -it myredis bash

退出容器

exit

使用通过docker进行测压(本人测试出现了问题)

docker exec -it myredis redis-benchmark -h localhost -p 6379 -c 100 -n 100000

在这里插入图片描述

redis基本知识

redis有16个数据库

默认使用的第0个

大小写无所谓

select 5 表示切换到第5个数据库

DBSIZE   可以查看这个数据库的大小,如果没有存key值(数据),则所占大小默认为0,

keys *   查看当前数据库所有的key

flushdb  清除当前数据库数据

FLUSHALL 清除所有数据库的数据

不同数据库数据不互通

查看所有的key

redis是单线程的,CUP不是redis的性能瓶颈,内存,和带宽才是,所以可以用单线程就够了,还能防止并发问题还有产生切换开销,(但是redis4用了多线程处理异步任务,reids6正式使用IO多线程)

因为redis是内存怪物,只用单线程就不用切换上下文,效率最高

五大数据类型

String

List

Hash

Set

Zset(有序集合)

Redis-Key命令

可以使用Tab进行命令提示(例如输入getr 按下Tab会变成GETRANGE)

常用基础命令

//检查key_name是否存在
exists key_name

//将key_name移动到第num个数据库
move key_name num

//设置num秒之后过期
expire key_name num

//查询key_name的过期剩余时间
ttl key_name

//查看数据类型
type name
String
//在key_name后面追加一个字符串"value"//不存在就是新建
append key_name "value"


//查看长度
strlen

//让String类型的数字自增//++操作
incr key_name

//人String类型的数字增加了num//+=num操作
incrby views 10

//自减操作//--操作
decr key_num

//-=num操作
decrby key_num 10

//截取0到5范围内的String
getrange key_name 0 5

//截取全部String(相当于get key_name)
getrange key_name 0 -1

//替换,把位置1后面的String替换成newstr
setrange key_name 1 newstr

//setex(set with expire)  设置过期时间
setex key_name 10 "hello"

//setnx(Set if not exist) 不存在再进行设置(分布式锁常用)
setnx key_name "hello"

//批量赋值操作  
mset k1 v1 k2 v2 k3 v3 

//批量获取
mget k1 k2 k3

//原子操作赋值
msetnx k1 v1 k2 v2

//设置对象(json)
set user:1 {name:zhangsan,age:3}

//进行拆分//查询就是更细分
mset user:1:name zhangsan user:1:age 3
List

所有的list是用L开头

//left push //从左边推入
Lpush list_name value

//列出全部
Lrange list_name 0 -1

//列出0到2的值
Lrange list_name 0 2

//从左边移出
Lpop list_name

//从右边移出
Rpop list_name

//查询列表长度
Llen list_name

//移出指定个数的值(取关)
Lrem list_name num value

//截断,剩下1到3的段
Ltrim list_name 1 3

//套娃操作//list1的末尾移到list2的头部
RpopLpush list1_name list2_name

//元素替换//要确保存在(不然会被判越界)
Lset list_name 1 value

//搜索性插入//在value1之后插入value2
Linsert list_name after value1 value2 

//搜索性插入//在value1之前插入value2
Linsert list_name before value1 value2 
Set

set是集合,里面的值不能重复,唯一性

//添加值
sadd set_name value

//检查是否有这个值
Sismember set_name value

//列出所有元素
Smembers set_name

//移除元素
srem set_name value

//获取set集合里的个数
scard set_name

//随机选出一个元素
Srandmember set_name 

//随机选出num个元素
Srandmember set_name num

//移出元素
Spop set_name

//从set1_name移动value元素到set2_name集合
Smove set1_name set2_name value

//以前一个set的不同部分作为返回
Sdiff set1_name set2_name

//相同部分作为返回
Sinter set1_name set2_name

//合并,取并集
Sunion set1_name set2_name

Hash

Map集合

更时候对象的存储

set多个key-value

与String类似

//存入
Hset hash_name key value

//获取
Hget hash_name key

//批量存入
Hmset hash_name key1 value1 key2 value2

//批量获取
Hmget hash_name key1 key2

//所有获取 返回的是一个key跟一个value
Hgetall hash_name

//删除key(value也没了)
Hdel hash_name key

//获取长度
Hlen hash_name

//判断key是否存在
Hexists hash_name key

//获取所有的key
Hkeys hash_name 

//获取所有的value
Hvals hash_name

//让对应的hash的对应的key自增
incr hash_name key

//让对应的hash的对应的key自减
decr hash_name key

//让对应的hash的对应的key加num
Hincrby hash_name key num

//让对应的hash的对应的key减num
Hdecrby hash_name key num

//存在不设置,不存在才设置
Hsetnx hash_name key value
Zset

有序集合

存入

//按照num排序存入
 Zadd set_name score value
 
//普通打印所有集合
Zrange set_name 0 -1

//普通打印num1到num2的所有集合
Zrange set_name num1 num2

 
 //获取-inf(负无穷)到+inf(正无穷)排序
 Zrangebyscore set_name -inf +inf
 
 //获取排序(在后面加scores)
Zrangebyscore set_name -inf +inf withscores

 //获取负无穷到200的排序(在后面带score)
Zrangebyscore set_name -inf 200 withscores

//降序排列(在后面带score)
Zrevrangebyscore set_name -inf 200 withscores

//移出元素
Zrem set_name value

//获取个数
Zcard set_name

Zcount set_name num1 num2

事务

redis单条命令保证原子性,事务不保证原子性

开启事务(multi)

命令入队(许多的Redis命令)

执行事务(exec) / 放弃事务(discard)

编译型异常(类似代码有误)

比如说同一个事务赋值再读取,会出现错误

运行时异常(类似1/0)

比如说插入一个命令失败了,但是其他命令还能正常运行

乐观锁

很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断下,在此期间是否有人修改过这个数据,
获取version
更新的时候比较version

//监控
watch


//取消监控
unwatch

秒杀系统用的

Jedis

java与redis的中间件

新建项目

项目里建立maven包

依赖

    <dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.2.3</version>
        </dependency>

链接模板

package com.lkw;

import redis.clients.jedis.Jedis;

public class TestPing {
    public static void main(String[] args) {
        Jedis jedis=new Jedis("192.168.199.131",6379);
        jedis.auth("000415");
        System.out.println(jedis.get("key" ));
    }
}

事务模拟:

package com.lkw;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestTX {
    public static void main(String[] args) {
        Jedis jedis=new Jedis("192.168.199.131",6379);
        jedis.auth("000415");

        //创建json
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","lkw");
        String josn2str=jsonObject.toJSONString();

        //创建事务
        Transaction multi = jedis.multi();

        try{
            multi.set("user1",josn2str);
            multi.set("user2",josn2str);

            //模拟异常事务
            int i=1/0;
        }catch (Exception e){
            //放弃事务
            multi.discard();
            e.printStackTrace();
        }finally {

            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();
        }
    }
}

Springboot整合

在spring-data

spring-data也是类似于springboot一样的整合怪

在Springboot2.x之后jedis换成了lettuce

jedis采用的直连,多线程是不安全的,如果要避免就要选择jedis pool

lettuce:采用netty,可以在多个线程共享

Redis.conf

Redis持久化

数据保存在硬盘(快照)

RDB:

在这里插入图片描述

AOF操作

类似命令日志记录

在这里插入图片描述

默认不开启

大数据形式效率低

这个命令用于修复

redis-check-aof --fix appendonly.aof

修复后数据丢失

Redis发布订阅

可以用消息队列代替

消息发送者:

频道:

消息接收者:

Redis主从复制

主从复制读写分离,主redis处理写请求,从redis处理读请求

作用:

数据冗余

故障恢复

负载均衡

高可用(集群)基石

默认自己是主库,所以只用配置从库就行,

查看当前库的信息
info replication

伪集群:复制配置文件,然后改端口,改pidfile,改日志服务名

对于docker可以重新创建容器,改端口,改映射文件,之类的

slaveof host_name port_name
//要认谁当老大
//slave奴隶

或者在配置文件配置

在这里插入图片描述

然后配置文件配置老大机 密码

全量复制:全部复制

增量复制:只复制后继内容

slaveof no one
//设置成没有老大,然后自己变成老大

这个是手动

哨兵可以自动转移

哨兵模式

自动选举老大的模式

多哨兵模式,(哨兵的集群)

哨兵的配置文件:sentinel.conf

基本内容:

sentinel monitor myredis 127.0.0.1 6379 1

1代表主挂掉了会进行投票

主机掉线再回来,就只能当奴隶了

如果有哨兵集群,就要记得改变哨兵的端口

配置主机从机密码

故障转移时间也能设置

通知脚本:可以启动sh脚本,传输什么什么信息

缓存穿透缓存击穿和雪崩

面试高频

缓存穿透

布隆过滤器:一种数据结构,对有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力

在这里插入图片描述

导致的问题:

1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键

2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一-段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

缓存穿透与缓存击穿的区别

缓存穿透:查询不存在的数据,缓存和存储都没有命中,

缓存击穿:不小心某个热点key过期,导致大量请求传到存储层(mysql)

雪崩

缓存集中过期

redis宕机

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值