狂神说Redis学习总结

狂神说Redis学习总结

①redis的入门理论

一.Redis的描述

1.Redis是什么?

Remote Dictionary Server远程服务字典,是一个开源的使用ANSI C语言编写、支持网络,可以基于内存也可以持久化的日志型,key-value数据库。

2.Redis能干什么?

  • 内存存储、持久化、内存断电即失
  • 效率高,可以用于高速缓存
  • 发布订阅系统
  • 地图信息分析
  • 计时器、计数器

3.Redis的特点是什么?

  • 多样的数据结构
  • 持久化
  • 集群
  • 事务

二.NoSQL的定义

1.nosql的意思是not only sql,它存储的数据类型更多通常是使用Map这样的键值对进行存储。由于现在的mysql数据库已经无法承载那么多类型的数据,所以很多数据都是由nosql来进行存储,它不需要一个固定的格式
2.nosql的特点
①方便拓展
②大数据高性能(一秒写8w次,读取11w次)
③数据类型多样
3.传统RDBMS和NoSQL
RDBMS:

  • 结构化组织
  • SQL语句
  • 数据和关系都存在单独的表中
  • 操作数据定义语言
  • 严格的一致性
  • 基础的事务

NoSQL

  • 不仅仅是数据
  • 没有固定的查询语言
  • 键值对存储,列存储,文档存储,图形数据库
  • 最终一致性
  • CAP定理和BASE(异地多活,其实就是一处崩了其它地方还是可以执行)
  • 高性能,高可用,高可扩

三.web1.0与web2.0的区别

1.web1.0更注重用户自己去搜索信息,以内容、信息为中心
2.web2.0用户可读可写,用户既是浏览者也是网站的建设者之一

四.数据存储的四大分类

1.kv键值对
新浪:redis
美团:redis+tair
阿里、百度:redis+memacache

2.文档型数据库
MongoDB:基于分布式文件存储的数据库,处理大量文档,它是介于关系型和非关系型之间,非关系型功能最多,最像关系型数据库
ConthDB
3.列存储数据库
HBase
分布式文件系统
4.图关系型数据库:拓扑图

五.缓存的发展

1.缓存的发展:
90年代的网站访问量并不会很大,所以这个时候一个mysql就足够了,但是到了后面①数据量太大②数据索引,一个机器的内存也放不下③访问量(读写混合),一个服务器承受不了。
2.后来使用了Memcache+mysql+垂直拆分。使用多个数据库,并使用缓存减少读所使用的时间
优化数据库索引结构->文件缓存(IO)->Memcache
3.分库分表+水平拆分+MySQL集群
目的就是加快写的过程,早些年的MyISAM是表锁每次修改都需要锁住一个表,那么效率低下,而且无法适应高并发下面的开发。然后出现了Innodb使用的是行锁。用分库分表来减轻写的压力
4.最近的年代关系型数据库已经不够用了,MySql已经没办法满足现在的数据量了,需要其他类型的数据库来分担压力。这样mysql的压力就会变小了,只存储一些自己专门处理的数据

②安装

一.window的安装

1.window的安装只需要去到github里面下载安装包然后安装就可以了
2.使用ping来测试是否连接成功。

二.Linux的安装

1.下载安装包,然后转移到opt下面去
2.执行

yum -y install gcc
yum -y install gcc-c++

配置好环境
3.可能会出现这个问题,就需要强制关闭这个进程。Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
Existing lock /var/run/yum.pid: another copy is running as pid 3685.

rm -f /var/run/yum.pid #关闭进程

4.tar -zxvf redis-6.0.10.tar.gz使用这个命令解压文件
5.执行 gcc -v看看成功了没有,然后make配置环境
6.如果make失败很有可能就是你的gcc的版本太低了,要升级

yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils 
scl enable devtoolset-9 bash

7.然后执行make install
8.然后查看一下 usr/local/bin下面有没有redis相关的文件
9.在usr/local/bin创建一个目录并且拷贝redis.conf在这里保证文件的安全
10.在usr/local/bin开启服务器(刚刚配置好的文件)
redis-server redisConfig/redis.conf

11.开启客户端redis-cli -p 6379,连接服务器端口
12.在客户端上面shutdown关闭所有的连接
13.ps -ef|grep redis:查看还有什么连接

③基本功能

一.基本操作和Redis的读写速度为什么这么快

redis有16个数据库
select 数字 #切换数据库
set name  值 #设置一些键值对
flushdb  #清空当前数据库
FLUSHALL #清空所有的数据库
keys *  #查看所有的键值对
exists xxx #是否存在这个键,存在返回1
expire xxx  时间(数字) #多少秒之后关闭,可用于单点登录
ttl xx  #存活时间 -1就是永久 -2就是不存在
type xx #查看变量的类型

2、Redis是单线程的。它是基于内存的操作,CPU不是redis的操作瓶颈,操作瓶颈应该是网络带宽和机器的内存。
3.Redis是单线程,为什么也可以这么快?
原因是多线程不一定就快,因为只有单个cpu的时候是需要不断的上下文切换就会消耗资源浪费时间,那么这个时候单线程就更快了。高性能服务器也不一样是多线程的。
核心:redis把所有的数据都是放到内存(电脑的cpu内存,也就是说只有一个cput)上面的,所以单线程的效率更高。对于内存系统来说没有上下文切换效率更高

二.基本数据类型

1.String

1.string的一些应用比如设置一个对象,可以学习json的数据结构
mset user:1:name xx user:1:age xx这样子的格式来进行
2.获取全部的值通常使用 0 -1这样就不需要知道这个数组到底有多大
append name “xxx” #给name添加字符串,如果不存在name就会自己创建一个

strlen xx #计算字符串长度
incr xx #自增1 
decr xx #自减1
incrby xx  (数字) #加上某一个数值
decrby xx  (数字) #减去某一个数值
setrange name start “xx” #替换某个字符串
getrange name  start end #截取某个字符串
setex (set with exipire)name “xxx” 数字 #设置字符串并且决定它存活的时间
setnx(set not null)name “xxx” #如果name不是空的才能设置
mset k1 v1 k2 v2 ....#批量设置
mget k1 k2....#批量获取
msetnx #批量设置,而且还是一个原子事务,要么都可以,要么都不可以

2.Set

1.集合可以做共同关注和共同好友的功能

sadd set xx #添加集合元素
spop set xx #随机移除
smembers set #集合全部元素遍历
sismember set “xx” #是不是包含这个元素
smove  set1 set2 “xx”  #把set1里面的xx元素移动到set2里面去
setrandmember set #随机抽取一个元素
scard set #集合有多少个元素
sdiff set1 set2 #set1里面和set2不同的元素,差集
sinter set1 set2 #交集
sunion set1 set2 #并集

3.List

1.如果是没有左右边的l就是list的意思
2.它实际上就像是一个链表

  • 如果没有key就创建
  • key存在就创建新的内容
  • 移除所有值,空链表,也代表不存在
  • 两边插入修改效率高
  • 消息队列(lpush rpop) 栈(lpush lpop)
lpush list xx  #在左边插入值
rpush list xx  #在右边插入值
lindex list 数字 #在左边的第x个值
lrange list x1 x2 #从x1 到x2范围下的值
lpop list #从左边弹出第一个元素
rpop list #从右边弹出第一个元素 
Llen list #list的长度
Lrem list 个数  值 #你要移除多少个这样的值
ltrim list x1 x2 #截断,保留x1-x2范围的值
rpoplpush list1 list2 #在list1中pop出最右边的, 然后加入到list2的最左边
linsert list before|afer "xx" "aa" #在xx之前(之后)插入aa
lset list (index) xx #在list的index的位置替换为xx

4.Hash

1.Hash其实就是 key -多个(key -value)这样子的形式存储,类似于string,也可以理解为key -map
2.hash通常以用于存储变更对象
比如user:1 name xx user :1 age xx

hset hash xx aa #设置键值对
hmset hash ... #设置多个键值对
hmget hash x1 x2 ....#获取多个键值对
hdel hash xx #删除键值对
hgetall hash #获取所有的键值对
hlen hash #键值对的个数
hexists hash xx #判断hash中是否有这个xx字段
hincr hincrby #自增,方式和string的一样
hvals hash #展示所有的值
hkeys hash #展示所有的键
hsetnx #和string的一样

5.Zset

1.类似set但是它是有序的,而且可以用于排行榜和各种带权比较

zadd zset score  xx #score相当于是一个序号或者说是标记,其它和set相同,多了一个score
zrangebyscore zset min max withscores #排序,min到max的范围下的值可以排序

zrem zset xx  #删除某个指定元素
zrange zset 0 -1 withscores #遍历所有元素
zrevrange #反向遍历所有元素
zcard zset #统计所有元素个数
zcount zset min max #判断这个范围有多少个数据

6.geospatial地理位置

1.geospatial的本质其实就是一个Zset,我们可以用来搜索附近的人,也可以搜索距离

geoadd key 经度 纬度 地方名 #添加地理位置
geodist key 地方1 地方2 #两个地方的距离
geopos key 地方....  #地方的位置(纬度经度)
georadius key 指定经度 指定纬度 搜索半径大小 km  #搜索指定半径大小的指定位置的范围内的城市
georadius key xx xx xx km withcoord withdist #加上了直线距离和搜索到的城市的位置
georadiusbymember key xx xx xx km #搜索指定城市指定半径大小内的城市 
geohash key city1 city2 #给出两个哈希字符串,字符串越接近那么他们也越近

7.Hyperloglog

1.主要是用在网站的UV上面,比如一个人访问多次网站,那么实际上还是一个人在访问网站,那么传统方法就是使用set来保存id,但是占用内存大。所以这个时候就需要用hyperloglog来保存,它能保存2^64个这样的id,而且占用的内存只是12kb。但是也有一些错误率0.81%,比较小可以忽略

pfadd key x1 x2.... #添加数据
pfmerge key key1 key2 #合并key1和key2他们是基数合并,所以不会有重复的
pfcount key #计算有多少个元素

8.BitMap

1.bitmap的作用就是统计打卡,和一些01事件

setbit key 序号(标记) 0|1 #这里就是记录了这个标记是0还是1,比如病人1号 生病了就是1,没生病就是0
getbit key  序号(标记) # 获取指定的标记的值
bitcount key #统计有多少个1

④持久化

一.AOF(Append Only File)

1.AOF持久化的方式也是一样的,通过主进程分支的子进程来存储,但是它存储的是语句(也就是每次初始化都需要重新去创建数据)而不是数据,每次初始化的时候都需要读取文件,然后重新初始化数据,所以效率低下,但是文件完整性比较好。
2.
优点:
①每一次修改都同步,文件完整性比较好
②每秒同步一次,可能丢失一秒数据
③从不同步效率最高
缺点:
①数据文件太大比起rdb
②而且运行效率也比较低下
3.如果append的文件出现问题可以使用redis-check-aof来修复
redis-check-aof --fix 文件名

4.rewrite操作其实就是如果持久化文件过大,就需要不断新建文件来继续存储

二.RDB(Redis DataBase)

1.RDB(Redis DataBase)是持久化的一种处理方式,它每次会根据我们设置好的配置文件的参数,然后然后这个参数save的规则进行持久化,然后他是分离出一个子进程来完成这个持久化的过程,他不会干扰父进程的处理,而且他们可以共享内存,最后子进程根据save规则来存储rdb文件。
这里的持久化指的是下次访问redis还能访问到这一数据。
2.
优点:可以处理恢复大型的数据文件,对数据完整性不高
缺点:需要一定的时间间隔来存储,如果redis宕机了数据就没了, fork的时候需要占用内存
3.如何恢复rdb文件?
只需要放到与redis的文件附近就可以了,通过config get dir找到这个位置。
4.触发机制:
①通过对save的设置
②flushall
③退出redis

⑤springboot整合

一.入门

1.使用Springdata的导入jar,其实springboot会自动导入
2.然后配置一下端口号,和哪个机连接的数据库
3.看一下源码会发现,RedisAutoConfiguration自动配置类里面有两个模板对象,他们是非常重要的,我们也可以知道我们可以自己来配置模板对象
4.我们每次需要调用某个存储结构都需要使用opsForxxx这个,然后才能使用它的api,其实这里的api都是为数据库的存储服务的,所以不需要纠结
5.然后就是序列化的问题

@Test
void contextLoads() {
    redisTemplate.opsForValue().set("好人","sss");
    redisTemplate.opsForGeo().add("china:city" ,new Point(120,30),"上海");
    System.out.println(redisTemplate.opsForValue().get("好人"));
    System.out.println(redisTemplate.opsForGeo().position("china:city","上海"));
    RedisConnectionFactory connectionFactory = redisTemplate.getConnectionFactory();
    RedisConnection connection = connectionFactory.getConnection();
    connection.flushDb();
}

二.序列化

1.序列化的作用。就是为了不要在传输数据的过程中,让数据变成了乱码。我们可以通过序列化和反序列化防止数据乱码和丢失。
2.springboot里面的序列化需要我们自己设置一个配置类进行序列化,然后设置序列化的类型。关键在于设置ObjectMapper和Serilizer
3.意思其实很简单,其实就是key就是以String形式进行的序列化,如果是对象类型就进行jackon的序列化,我们会发现在最后展现出来的数据就是我们序列化之后的数据。如果不序列化就没办法识别普通的对象(因为一个对象有很多种普通数据)
代码

下面的代码就是RedisConfig里面重新定制的RedisTemplate

@Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String,
                Object>();
        template.setConnectionFactory(factory);
// Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new
                Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
// String 的序列化
        StringRedisSerializer stringRedisSerializer = new
                StringRedisSerializer();
// key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

⑥配置文件详解

在这里插入图片描述
在这里插入图片描述

⑦ 事务

一.Redis的事务

1.Redis的事务没有隔离性,只保证单条语句原子性,但是并不保证事务的原子性。
2.Redis的事务分两种错误:
编译前的错误(命令写错了):那么整个事务无效
运行时错误(比如1/0这样的语法性错误):那么除了出问题这个语句不会执行,其它语句还是会执行的

multi  #开启事务 
exec  #执行事务
discard #结束事务,并且不执行那些语句

二.乐观锁

1.面试常考点Redis有没有乐观锁?
当然是有的,我们在mybatisplus里面使用的是version进行的对比,那么现在在redis上面使用的就是watch来进行监视和对比,如果在执行事务之前,watch的值发生改变,那么就会执行失败。这个场景就类似与获取version,对比version,失败时候就没办法执行是一样的。

下面是狂神老师的图

在这里插入图片描述

⑧Jedis

简单来说Jedis就是类似于JDBC都是数据库里面的JAVA代码实现,可以调用api来完成对redis的数据库操作

配置环境

1.创建空项目,改变project和moudle的jdk版本,然后修改javacompiler的版本
2.修改maven的位置
3.导入依赖
4.测试Jedis,和redis的命令操作一模一样
5.对于事务的操作需要获取multi对象进行操作事务执行完之后再使用会jedis

依赖

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.75</version>
    </dependency>

</dependencies>

Jedis事务的操作

public static void main(String[] args) {
    Jedis jedis = new Jedis("127.0.0.1",6379);
    JSONObject jsonObject=new JSONObject();
    jedis.flushDB();
    jsonObject.put("user", "haoren");
    jsonObject.put("age","3");
    Transaction multi = jedis.multi();
    try{
        multi.set("user1",jsonObject.toJSONString());
        multi.set("user2",jsonObject.toJSONString());
        int i=1/0;
        multi.exec();


    }catch (Exception e){
        multi.discard();
        System.out.println(e.getMessage());
    }finally {
        System.out.println(jedis.get("user1"));
        System.out.println(jedis.get("user2"));
        jedis.close();
    }

}

⑨Redis的发布订阅

1.订阅通常都是执行subscribe订阅了某个频道,然后由后台进行publish进行推送
2.发布和订阅原理,其实就是通过一条链表把他们串起来,后台(发布)->频道->订阅的人。首先就是订阅subscribe就可以加入到这一个频道,然后每一次后台发布东西的时候都会由频道发布这些信息给用户。
3.通常使用消息的中间件完成。
4.应用场景:订阅发布、实时信息系统、实时聊天系统。

subscribe 频道 #订阅
publish 频道 消息 #发布

⑩主从复制

一.主从复制简介

1.什么是主从复制?
主从赋值就是一个Redis服务器复制其它Redis服务器,然后前者是主节点后者是子节点,主节点只可以写,子节点只可以读,分担了服务器的负载。不需要所有人都只访问一台服务器
2.主从复制的作用?
①数据冗余:实现了数据的热备份
②故障恢复:如果主节点出问题了就可以使用子节点来恢复
③负载均衡:少写多读,子节点可以分担很多读的压力,大大提升redis的服务器并发量
④高可用:主从复制是哨兵模式和集群实施的基础,主从复制是高可用的基础

3.为什么只用一台redis服务器是不可行的?
①从结构上如果有单点服务器故障了,一台服务器的请求负载就压力很大
②容量:单台redis服务器的容量不足以完成业务,而且也不应该超过20g
4.增加配置文件修改,开启服务器
①修改pid
②port
③logfile
④dump

info replication #查看服务器信息

5.连接主机,首先是客户端连接上服务器端,然后通过

slaveof host port #连接主机

6.主从机的区别,主机可写可读,但是从机只能够读不能写。而且主机断开连接之后,从机还能够继续运行。但是从机断开连接之后就会和主机断开,没办法得到主机的内容(命令行,可以通过配置文件来配置)。

主从复制的原理:
全量复制:slave服务在接收到数据库文件之后就会加载到内存,第一次连接主机会传文件完成sync
增量复制:master继续新收集修改命令传给slave,完成sync
只要重新连接master都会进行一次全量复制
7.第二种主从赋值就是类似一条链表,如果这个时候老大没了,就可以使用slaverof no one来重新定位老大。如果旧老大上线了就需要重新配置,因为它已经不是老大了

上面是第一种主从复制模式,下面是第二种
在这里插入图片描述

二.哨兵模式

1.哨兵模式是什么?
哨兵模式其实就是自动切换主机的意思,如果主机出现故障,哨兵检测到了就是主观下线,多个哨兵检测到了就是客观下线,这个时候就需要哨兵重新投票哪一个从机来当主机。哨兵之间也会互相监控。哨兵检测的方式就是每次都发个信息过去,如果没有回信息就有可能故障了
2.使用哨兵模式
①配置sentinel.conf在redisConfig里面
sentinel monitor 监视器名称 host port 投票数 #配置哨兵

②redis-sentinel redisConfig/sentinel.conf开启哨兵
3.常用配置比如port和monitor哨兵配置
4.如果哨兵模式的老大走了又回来就只能当小弟了,哨兵会自动配置和convert的。
哨兵模式的优点
①哨兵集群高可用,而且具备主从复制的优点,并且更具有健壮性
②主从可切换,故障可转移
③自动,健壮性强
缺点:
①很难扩容,因为哨兵选择多配置也多

在这里插入图片描述

缓存穿透和雪崩

1.缓存穿透:就是在缓存里面查不到,然后都去mysql服务器里面去查,服务器就会承载非常大的压力,这就是穿透。
2.缓存击穿:都去查一个key了,如果服务器宕机,这个时候查询都会打到key上面去就有可能击穿缓存(缓存服务器宕机,key过期)去到服务器上面去查。简单来说就是缓存的能够接收的请求数量有限,如果太多就会被击穿去到服务器查 (并发太多)
3.解决方案:
①永不过期的热键
②加互斥锁,只允许一个线程去取数据
4.雪崩就是redis缓存服务器突然断电,所有的key都失效。解决方案:
①开多几台redis服务器
②限流降级
③数据预热

总结

这是Redis的简单入门学习,今后学习仍然还是需要继续深入底层,找到更多的应用场景,理解原理使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值