redis基础知识内容

1.redis特性:(一个基于内存的数据库,数据可以直接存入内存中)
非结构化
无关联
非SQL---查询方式
BASE----事务特性
2.SQL数据库使用场景:1)数据结构固定
2)相关业务对数据安全性一致性要求较高
3.NOSQL(redis)使用场景:1)数据结构不固定
2)对一致性,安全性要求不高
3)对性能有要求
redis特点:
1.键值型
2.单线程
3.低延迟,速度快
4.支持数据持久化
5.支持主从集群、分片集群
6.支持多语言客户端
redis是一个key-value的数据库,key一般是string类型。不过value的类型多种多样
基本类型有:String:hello world
Hash:{name:"jack",age:21}
List:[A->B->C->C]
Set{A,B,C}
SortedSet{A:1,B:2,C:3}
redis通用命令:(命令help+命令查看该命令的使用文档。)
1.KEYS:查看符合模板的所有key
KEYS *:查询所有的键
KEYS a*:查询以a开头的以此类推
不建议在生产环境下使用KEYS因为底层的模糊查询机制会很浪费时间。不要在主节点去做会阻塞所有的命令。
2.DEL:删除一个指定的key
删除一个:DEL name
删除多个:DEL name nema ni nk integer 3返回值的意思:删除的是三个数
3.EXISTS:判断key是否存在,存在1不存在2
exits name
exits blog
4.EXPIRE:给一个key设置有效期,有效期到期时为负数时该key会被自动删除。
5.TTL:查看一个KEY的剩余有效期当显示负数则代表永久有效。
redis数据类型命令:
1.String类型:
String类型,也就是字符串类型,是redis中最简单的存储类型。
其Value是字符串,不过根据字符串的格式不同,又可以分为3类:
string:普通字符串
int:整数类型,可以做自增,自减操作
float:浮点类型,可以做自增、自减操作。
常用命令:

2.key结构
避免id冲突,数值不明确
格式如下(不固定的)
项目名:业务名:类型:id
例如:heima:user:1
多个单词之间用冒号隔开
3.Hash类型:保存对象类型时使用
也叫散列,其value是一个无序字典,类似于java中的HashMap结构
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD
String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便。
一个key可以有多个filed(字段名)value(字段值)
Hash类型常用命令:

4.List类型:
如何利用list结构模拟一个阻塞队列?
1)入口和出口在不同边
2)出队时采用BLPOP或BRPOP
常用命令:

5.set类型要求对象不重复。它的常用命令有:
 
 
6.SortedSet类型
类似于Java中的TreeSet类型
但是SoretedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)【跳表就是用来做排序的】加hash表。
因为SortedSet的可排序性,经常被用来实现排行榜这样的功能。
常用命令有:

所有的排名默认都是升序的,如果要降序则在命令的Z后面添加REV即可。
REDIS的客户端
1.jedis以redis命令作为方法名称,学习成本低,简单实用。但是jedis实例时线程不安全的,多线程环境下需要基于连接池来使用。
2.lettuce是基于Netty实现的,支持同步,异步和响应式编程方式,并且是线程安全的。支持redis的哨兵模式,集群模式和管道模式。跟spring结合比较好。
3.Redission是基于redis实现的分布式,可伸缩的java数据结构集合,包含了诸如MAP、Queue,Lock,Semaphore,Atomiclong等强大功能。
jedis的具体使用步骤:
1.引入依赖
2.建立连接
3.使用jedis,方法名与redis命令一致
4.释放资源
jedis连接池:
jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用jedis连接池代替jedis的直连方式。
1.先配置连接池
2.创建jedis对象传入参数
3.提供静态方法。
4.释放资源
SpringDataRedis
1.引入依赖
2.配置文件
3.注入redisTemplate并使用
4.编写测试
spring默认使用lettuce其它要自己去引用。
获取数据就要输出结果。
SpringDataRedis的序列化方式:
缺点:
1。可读性差
2.内存占用较大
mapper是springmvc中默认的json处理工具。
手段处理json
一,redisTemplate的两种序列化实践方案:
方案一:
1.自定义RedisTemplate
2.修改RedisTemplate的序列化器为GenericJackson2Jackson2JsonRedisSerializer
方案二:
1。使用StringRedisTemplate
2.写入Redis时,手动把对象序列化为JSON
3.读取Redis时,手动把读取到的JSON放序列化为对象。(重点:手动)
mysql和redis的区别:
1、MySQL数据库作为存储的关系型数据库,相对薄弱的地方在于每次请求访问数据库时,都存在着I/O操作,如果反复频繁的访问数据库会产生以下问题:
(1)会在反复链接数据库上花费大量的时间,从而导致运行效率过慢
(2)反复的访问数据库也会导致数据库的负载过高,那么此时缓存的概念就衍生出来了
2、Redis是基于单线程的,Redis效率比较高,由于Redis是基于内存操作,所以CPU不是性能瓶颈,机器的内存和宽带才是Redis的瓶颈。
redis事务和锁机制:(!!!!!!!!!!!!!!!!!!!!!!!!!)
redis事务是一个单独的隔离操作:事务中的所有命令都会序列化,按顺序地执行。事务在执行过程中,不会被其他客户端发送来的命令请求所打断。
redis事务的主要作用就是串联多个命令防止别的命令插队。
关于事务的三个命令:
Multi、Exec、discard
从输入Multi命令开启事务开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,redis会将之前的命令队列中的命令依次执行。
组队过程中可以通过discard来放弃组队。
事务的错误处理:
1.组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消
2.如果在执行阶段的某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
事务冲突
用锁的机制去解决
1.悲观锁(每次操作都上锁等我解锁后才可以操作)
在你自己拿数据之前先上锁只有你解锁了才可以使用。传统性数据库里边用到了很多这样的锁机制,比如行锁,表锁等,读锁,写锁等都是在操作之前先上锁
2.乐观锁(就是版本号更新使用问题,不会上锁但是会更新)【抢票的例子】利用乐观锁淘汰用户。

前一个人先更改了数据内容使此版本的数据升级成为了新版本的数据,原来版本使用者者则必须被判断是否是新版本者,如果不是则没有使用权,就是只能在新版本的基础上开始使用。
乐观锁适用于多读的应用类型(多人同时操作,最终只有一个人基本成功),这样可以提高吞吐量。redis就是利用这种check-and-set机制实现事务的。
乐观锁在redis中的命令操作:
WHATCH key [key...]
在执行multi之前,先执行watch key1[key2],可以监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
unwatch:取消watch命令对所有key的监视。
如果在执行watch命令之后,exec命令或discard命令先被执行了的话,那么就不需要再执行unwatch了。
总结:redis事务的三特性:
1,单独的隔离操作
2.没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行。
3.不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
加用incr减用decr redis中。
ab工具模拟并发
连接超时的问题:
超卖和超时问题:
连接超时问题可以用连接池的方式来解决
超卖问题可以通过乐观锁来解决
1.首先监视
2.开启事务
3.组队
4.执行
乐观锁容易造成库存遗留问题:
即当第一个人修改版本号之后其他没有修改版本号的人无法再清库存了,即只卖出去了一个
可以用LUA嵌入式脚本语言解决
LUA脚本在redis中的优势:
将复杂的或者多步的redis操作,写为一个脚本,一次提交给redis执行,减少反复连接redis的次数。提升性能。
 LUA脚本使类似redis事务,有一定的原子性,不会被其他命令插队,可以完成一些redis事务性的操作
注意只有redis2.6以上的版本才可以使用lua脚本。
利用lua脚本淘汰用户,解决超卖问题
redis2.6以后,通过lua脚本解决争抢问题,实际上是redis利用其单线程的特性,用任务队列的方式解决多任务并发问题。
lua脚本的特点:我在执行过程中只有我接受之后别人才能干预,我在执行过程中,别人是不可能对我的操作进行插队和干预S
lua脚本要求:能看懂即可。
redis持久化操作(!!!!!!!!!!!!)’
把redis数据写入硬盘中去
在指定时间间隔内将内存中的数据集快照写入磁盘。(不定时备份)(RDB默认是开启的)
rdb的缺点:最后一次持久化后的数据可能丢失
rdb的过程通过fork建一个临时文件,把临时文件替换出持久化文件过程用的技术是写时复制技术
rdb的优势:1.会周期性的把数据进行持久化操作,适合大规模的数据恢复
2.节省磁盘空间
3.恢复速度快
4.对数据完整性和一致性要求不高更适合使用。
缺点:
1.fork的时候,内存中数据被克隆了一份,大概2倍的膨胀性需要考虑
2.虽然redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能的
3.在备份周期一定间隔时间做一次备份,如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。
rdb的备份
redis持久化的另外一种操作:AOF
AOF:以日志形式记录每个写操作(增量保存),将redis执行过的所有写指令记录下来(读操作不记录),只追加文件但是不可以改写文件。
AOF是默认不开启的
AOF和RDB同时开启,系统默认读取AOF的数据(数据不会存在丢失)记住!!!!!!!!!!!
AOF持久化流程:
1.客户端的请求写命令会被append追加到AOF缓冲区内;
2。AOF缓冲区根据AOF持久化策略,将操作sync同步到磁盘的AOF文件中;
3.AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量。
4.redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的。
AOF的优势:
1.备份机制更稳健,丢失数据概率更低
2可读的日志文本,通过操作AOF文件,可以处理误操作。
劣势:
1.比起RDB占用更多的磁盘空间
2.恢复备份的速度慢
3.每次读写都同步的话,有一定的性能压力。
4.存在个别bug,造成恢复不能。
问题:用哪个好?
官方两个都推荐。
如果对数据不敏感可以用RDB。
不建议单独使用AOF,因为可能会出现BUG
如果是单纯的做内存缓存,可以都不用。
redis主从复制!!!!!!!!!!!!!!!!!!!!!
1.读写分离(主机专门读操作,从机专门写操作),性能扩展
2.容灾快速恢复(当某一台主机挂了之后能快速切换,继续提供服务)
一主多从只能有一个主服务器
主从复制是指主机数据更新之后根据配置和策略,自动同步备份到的master/slaver机制,Master以写为主,Stave以读为主
一主两从:
当从服务器挂掉之后,再次重启,这个从服务器不会再变成主服务器的从服务器,而是会变成一个新的主服务器,这时候就需要通过命令把这个新的主服务器再变成从服务器加入到第一个主服务器中。而在加入的时候它会把主服务器中的数据从头开始复制。
当主服务器挂掉之后,从服务器不做任何事情还认已经挂掉的主服务器,不会篡位,而主服务器重启后,它依然是主服务器。
主从复制的原理:
1.当从服务器连接上主服务器之后,从服务器向主服务器发送进行数据同步消息
2.主服务器接到从服务器发送过来同步消息,把主服务器数据进行持久化rdb文件,把rdb文件发送给从服务器,然后从服务器拿到rdb进行读取。
3.每次主服务器进行写操作之后,和从服务器进行数据同步。
只有第一次是从服务器主动的,其他都是主服务器主动的。
redis的薪火相传和反客为主!!!!!!!!!!!!!!!!!
slaveof no one将从机变成主机。
薪火相传是一个人管理200个人肯定管理不来即一个服务器管理200个服务器肯定管理不来,所以要分小组长去管理
反客为主是主服务器挂掉了从服务器升级成为了主服务器
哨兵模式!!!!!!!!!!!!!!!
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
还需要注意的是至少有多少个哨兵同意迁移的数量。
缺点:复制延迟
选哪个从机作为主机呢?选择规则依次如下:
1.选优先级靠前的
2.选择偏移量最大的
3。选择runid最小的从服务(每个redis实例启动后都会随机生成一个40位的runid)
当老主机恢复后只会变为从机不会恢复成主机
redis集群!!!!!!!!!!!!!!!!!!!!!!!
集群解决的问题:
容量不够,redis要进行扩容的时候
并发写操作,redis要用集群分摊的时候。
无中心化集群方式搭建集群
任何一台服务器都可以作为集群的入口。他们之间可以联通互相切换使用
一个服务占用一台unlix系统
redis集群的特点:redis集群实现了对redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数居的1/N.
集群的高可用性:当集群的一部分失效,集群也可以继续处理请求。
集群操作和故障恢复!!!!!!!!!!!
集群的分配原则:尽量保证每个主数据库运行在不同的ip地址,每个从库和主库不在一个ip地址上。保证集群的高可用性
集群存在插槽分摊服务器压力。
可以查询集群中的值
集群的故障恢复:
当主从都挂掉要看配置是否为yes为就整个集群挂掉。
redis集群的好处:
实现扩容,分摊压力,无中心配置相对简单。
集群的不足:
多键操作不支持
lua脚本不支持,多键的redis事务不被支持。
复杂度较大
redis在实际应用过程中可能会遇见的一些问题,以及这些问题的解决方案
1.缓存穿透问题:(数据库中的数据可以通过redis中进行缓存)(黑客攻击)

 
1)应用服务器压力突然变大
2)redis命中率降低了,缓存中查不到数据了
3)服务器就会一直去查数据库。
正差情况应该是:先查缓存,查到返回,查不到就查数据库再放到缓存中。
缓存穿透现象出现特点:1.redis查询不到数据库
2.出现很多非正常url访问。黑客攻击
解决方法:
1.对空值做缓存:
2.设置可访问的名单
3.采用布隆过滤器
4.进行实时监控


 
 
缓存击穿

 
现象:1。数据库访问压力瞬间增加2.redis里面没有出现大量key过期。3.redis正常运行
造成原因:1.redis某个热门key过期了,大量访问使用这个key(词汇搜索过高但是这个词汇过期了。)
解决方案:1.预先设置热门数据
2.实时调整
3.使用锁(按照顺序进行)
只要用到锁必定效率很低。

缓存击穿锁解决的步骤图:

缓存雪崩:

现象:1.数据库压力变大,服务器崩溃
造成原因:1.再极少时间段,查询大量key的集中过期问题
解决方案:1.构建多级缓存架构(缺点:过于复杂)2.使用锁或队列不适用于高并发过程。3.设置过期标志更新缓存(提前预知是否过期)4.将缓存失效时间分散开


分布式锁(共享锁)!!!!!!!!!!!!!!!!!!!!!(锁的多个服务器应用有效化)(即成为共享锁。)(当一台服务器上锁后对整个集群都有效)
1.使用redis实现分布式锁:(类似上厕所)
命令setnx key设置加锁
解锁:del 该key
给该锁设置一个过期时间能解决一直霸占不解锁的问题自动释放。
命令:expire key
还有一种突发情况:在上锁之后突然出现了异常,无法设置过期时间了。解决方法:在上锁的同时设置过期时间
命令:set key value nx ex 过期具体时间
2.被误删或锁释放错解决方法:

解决方案:

第一步:uuid标识该锁
第二步:判断uuid值是否一样。
3.LUA原子性:就是顺序执行互相不会被干扰
LUA脚本:在进行的时候不会被打断或干预
使用LUA脚本释放锁保证原子性不会被误删

分布式锁总结:
为了至少确保锁可用必须满足以下四个条件:
1.互斥性:在任意时刻,只有一个客户能持有锁
2.不会发生死锁:即使只有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
3.加锁和解锁的必须是同一个客户端,客户端自己不能把别人加的锁给解了
4.加锁和解锁必须具有原子性。
redis学习的大纲:



 


 
redis命令练习题:
1.set 命令:

 
2.SortedSet命令:

redis学习正式完结!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!感谢阅读!
 

posted on 2023-05-23 20:57  麦苗33  阅读(6)  评论(0)    收藏  举报