Redis
学习形式:
- 上手就用
- 根本的实践先学习,而后将常识融汇贯通
nosql解说
为什么要用Nosql
当初都是大数据时代
大数据个别的数据库无奈进行剖析解决了
至多要会Springboot+SpringCloud
压力肯定会越来越大,适者生存
1.单机MySQL的年代
90年代,一个根本的网站访问量个别不会太大,单个数据库齐全足够,那个时候,更多的去应用动态网页,HTML,服务器基本没有太大的压力思考一下,这种状况下:整个网站的瓶颈是什么?
1.数据量如果太大,一个机器放不下了
2.数据的索引 300万就肯定要建设索引(B+Tree),一个机器内存也放不下
3.访问量(读写混合),一个服务器接受不了
只有你呈现以上的三种状况之一,那么你就必须要升级
2.Memcached(缓存)+MYSQL+垂直拆分
网站80%的状况都是在读,每次都要去查詢数据库的话就非常的麻烦!所以说咱们心愿加重数据的压力,咱们能够应用缓存来保障效率!倒退过程:优化数据结构和索引->文件缓存(IO)->Memcachaed(过后最热门的技术!)
3.分库分表+程度分表+MYSQL集群
技术和业务在倒退的同时,对人的要求也越来越高!==实质:数据库(读,写)==
早些年MYISAM:表锁,非常影响效率!高并发下就会呈现重大的锁问题
转战INNODB:行锁
缓缓的就开始应用分库分表来解决写的压力!Mysql在那个年代推出了表分区!这个并没有多少公司应用!
Mysql的集群,很好的解决了那个年代的所有需要
4.现在最近的年代
技术爆炸
2010(按键手机 android1.0HTC)--2020
十年之间,世界曾经产生了天翻地覆的变动(定位,也是一种数据,音乐,热榜!)
MySQL等关系型数据库就不够用了,数据量很多,变动很快!
图形数据库 JSON数据库
MYSQL有的时候应用它来存储一些比拟大的文件,博客,图片!数据库表很大,效率就低了!如果有一种数据库来专门解决这种数据,mysql的压力就会变得非常小(钻研如何解决这些问题!)大数据的io压力下,表简直没法更大
目前一个根本的互联网我的项目
为什么要用NoSQL
用户的个人信息,社交网络,==地理位置==。用户本人产生的数据,用户日志等等爆发式增长!
这时候咱们就须要应用NoSQL数据库的,NoSQL能够很好的解决以上的状况!
NoSQL=Not Only SQL(不仅仅是SQL)
泛指非关系型数据库,随着web2.0互联网的诞生!传统的关系型数据库很难凑合web2.0时代!尤其是超大规模的高并发的社区!站长!裸露进去很多难以克服的问题,NOSQL在当今大数据环境下倒退的十分迅速,Redis是倒退最快的,而且是咱们当下必须把握的技术!
很多的数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不须要一个固定的格局(行和列),不须要有多余的操作就能够横向扩大了!Map<String,Object>应用键值对来管制
NoSql特点
1.不便扩大(数据之间没有关系,很好扩大!)
2.大数据量高性能(Redis一秒能够写8万次,读取11万次,nosql的缓存记录级,是一种细粒度的缓存,性能比拟高)
3.数据类型是多样型的!(不须要当时设计数据库!随取随用!如果是数据量非常大的表,很多人就无奈设计了!)
4.传统RDBMS和NOSQL
传统的RDBMS
- 结构化组织
- SQL
- 数据和关系都存在独自的表中
- 操作操作,数据定义语言
- 严格的一致性
- 根底的事务
- ……
NOSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- CAP定理 和 BASE实践(异地多活!)高级架构师
- 高性能,高可用,高可扩
- ……
理解:3V+3高
大数据时代的3v:次要是形容问题的
1.海量Volume
2.多样Variety
3.实时Velocity
大数据时代的3高:次要是对程序的要求
1.高并发
2.高可拓(随时程度拆分,机器不够了,能够扩大机器)
3.高性能(保障用户体验和性能!)
真正在公司中的实际:NOsql+RDBMS一起应用才是最强的,阿里巴巴的架构演进!
技术没有高下之分,看你如何应用!(晋升内功,思维的进步!)
技术急不得,越是缓缓学,能力越扎实
麻利开发,极限编程
任何一家互联网的公司,都不可能只是简简单单让用户能用就好了
大量公司做的都是雷同的业务(竞品协定)
随着这样的竞争,业务是越来越欠缺,而后对于开发者的要求也是越来越高!
如果你将来想当一个架构师:没有什么是加一层解决不了的
1.商品的根本信息
名称,价格,商家信息
关系型数据库就能够解决了(王坚:阿里云的这群疯子)
淘宝外部的mysql 不是大家用的mysql
2.商品的形容,评论(文字比拟多)
文档型数据库中,mongodb
3.图片
分布式文件系统 FastDFS
- 淘宝本人的TFS
- Google的 GFS
- Hadoop HDFS
- 阿里云的 oss
4.商品的关键字(搜寻)
- 搜索引擎 solr elasticsearch
- Isearch: 多隆
所有牛逼的人都有一段苦逼的岁月,然而你只有像sb一样的去保持,终将牛逼!
5.商品热门的波段信息
- 内存数据库
- redis tair memache
6.商品的交易,内部的领取接口
- 三方利用
要晓得,一个简略的网页背地的技术不肯定是大家所想的那么简略!
大型互联网利用问题
- 数据类型太多了
- 数据源太多了
- 常常重构
- 数据要革新,大面积革新麻烦
解决问题:
![\[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-544IbeI2-1605684515441)(C:\Users\12168\AppData\Roaming\Typora\typora-user-images\image-20200811155340164.png)\]](https://img-blog.csdnimg.cn/2...
关系型数据库:表格,行,列(POI)
NoSql的四大分类
kv键值对:
- 新浪:redis
- 美团:redis+tair
- 阿里,百度:Redis+memcache
文档型数据库(bson格局和json一样)
mongodb(个别必须要把握)
- mongodb是一个基于分布式文件存储的数据库,C++编写,次要用来解决大量的文档
- mongodb是一个介于关系型数据库和非关系型数据库之间的产品,Mongodb是非关系型数据库中性能最丰盛,最像关系型数据库的
- conthDB
列存储数据库
- HBase
- 分布式文件系统
图关系型数据库
- 它不是存图形,放的是关系,比方:朋友圈社交网络,广告举荐
- Neo4j,InfoGrid
Redis入门
redis是什么
Redis(Remote Dictionary Server ),即近程字典服务
是一个开源的应用ANSI C语言编写、反对网络、可基于内存亦可长久化的日志型、Key-Value数据库,并提供多种语言的API。
区别的是redis会周期性的把更新的数据写入磁盘或者把批改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
收费和开源,是当下最热门的nosql技术之一,也被人们称之为结构化数据库
Redis能干嘛
1.内存存储,长久化,内存中是断电即失,所以说长久化很重要(rdb,aof)2.效率高,能够用于高速缓存
3.公布订阅零碎
4.地图信息剖析
5.计时器,计数器(浏览量)
6.……
个性
1.多样的数据类型
2.长久化
3.集群
4.事务
……
留神
==Window在Github上下载(停更很久了)==
Redis举荐都是在Linux服务器上搭建的,咱们是基于Linux学习
默认端口是6379
window下应用的确简略,然而redis举荐咱们应用linux去开发应用
测试性能
“redis-benchmark” 是一个压力测试工具!
官网自带的性能测试工具
redis-benchmark
测试:100个并发连贯 100000申请
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
根底的常识
redis默认有16个数据库
默认应用的是第0个数据库
能够应用select进行切换数据库
select 3 //切换到第三个数据库
dbsize //查看以后的大小
set k v //插入数据
get k //查问数据
keys * //查问所有的k
flushdb //清空以后库
flushall //清空全副的数据库
exists name //判断name是否存在
move name 1 //移除在第一个数据库中的name
expire name 10 //该参数10秒后过期
ttl name //查问残余的过期工夫 -2示意没了
type name //查问以后的key的类型
append key1 “hello” //在key前面追加字符串,如果以后key不存在,就相当于setkey
strlen key1 //获取字符串长度
incr views //数据加1
decr views //数据减1
incrby views 10 //数据加10
decrby views 10 //数据减10
getrange key 0 3 //取0-3两头的字符串
getrange key 0 -1 //取全副符串和get key是一样的
setrange key 1 xx //替换指定地位的字符串
setex (set with expire) //设置过期工夫
setnx (set if not expire) //不存在设置 (在分布式锁中会经常应用)如果存在就创立胜利,如果不存在就创立失败
mset //批量插入
mget //批量获取
msetnx //批量不存在设置(原子性:一个谬误全副谬误)
对象
set user:1 {name:zhangsan,age:3} //设置一个user:1 对象 值为json字符串来保留一个对象
mset user:1:name zhangsan user:2:name lisi
这里的key是一个奇妙的设计: user:{id}:{filed} ,如此设计在redis中是齐全ok了
getset //先get而后再set 如果不存在值,则返回nil 如果存在值,获取原来的值,并设置新的值
数据结构是雷同的,jedis
string类型的应用场景:value除了是咱们的字符串还能够是咱们的数字
- 计数器
- 统计多单位数量
- 粉丝数
- 对象缓存存储
思考:为什么redis是6379
粉丝效应
Redis是单线程的
明确Redis是很快的,官网示意,Redis是基于内存操作,CPU不是redis性能瓶颈,redis的瓶颈是依据机器的内存和网络带宽,既然能够应用单线程来实现,就应用单线程了
Reids是c语言写的,官网提供的数据为10W+的QPS,齐全不比同样是应用k-v的Memcache差
Redis为什么单线程还这么快?
1.误区1:高性能的服务器肯定是多线程的
2.误区2:多线程(cpu上下文会切换!)肯定比单线程效率高!
cpu>内存>硬盘的速度要有所理解!
外围:redis是所有的数据全副放在内存中的,所以说应用单线程去操作效率就是最高的,多线程(cpu上下文会切换:耗时的操作),对于内存零碎来说,如果没有上下文切换效率就是最高的,屡次读写都是在一个cpu上的,在内存状况下,这个就是最佳的计划!
redis
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它能够用作==数据库==、==缓存==和==消息中间件==。 它反对多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 汇合(sets), 有序汇合(sorted sets) 与范畴查问, bitmaps, hyperloglogs 和 天文空间(geospatial) 索引半径查问。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘长久化(persistence), 并通过 Redis哨兵(Sentinel)和主动 分区(Cluster)提供高可用性(high availability)
Redis-key
大根本数据类型
- String(字符串)
90%的java程序员应用redis只会应用一个String类型
List
根本的数据类型,列表
在redis外面,咱们能够把list玩成,栈,队列,阻塞队列
所有的list命令都是l结尾的
#############################################> lpush list one #将一个值或者多个值,插入到列表头部(左)1> lpush list two2> lpush list three3> lrange list 0 -1threetwoone> lrange list 0 1threetwo> rpush list right #将一个值或者多个值,插入到列表头部(右)4> lrange list 0 -1threetwooneright#############################################lpoprpop> lrange list 0 -1 threetwooneright> lpop list #移除列表的第一个元素three> rpop list #移除列表的最初一个元素right> lrange list 0 -1twoone#############################################lindex > lindex list 1 #通过下标取得list中的某一个值one> lindex list 0two#############################################llen> lpush list one1> lpush list two2> lpush list three3> (error) ERR unknown command> llen list #返回列表长度3#############################################移除指定的值!> lrange list 0 -1threethreetwo> lrem list 1 three #移除list汇合中指定个数的value,准确匹配1> lrange list 0 -1threetwo> lpush list three3> lrem list 2 three2> lrange list 0 -1two#############################################trim 修剪> rpush mylist "hello"1> rpush mylist "hello1"2> rpush mylist "hello2"3> rpush mylist "hello3"4> ltrim mylist 1 2 #通过下标截取指定的长度,这个list曾经被扭转了,只剩下截取的元素OK> lrange mylist 0 -1hello1hello2#############################################rpoplpush #移除列表最初一个元素并且挪动到新的列表中> rpush mylist "hello"1> rpush mylist "hello1"2> rpush mylist "hello2"3> rpoplpush mylist myotherlist #移除列表最初一个元素并且挪动到新的列表中hello2> lrange mylist 0 -1 #查看原来的列表hellohello1> lrange myotherlist 0 -1 #查看指标列表中,的确存在该值hello2#############################################lset 将列表中指定下标的值替换为另外一个值,更新操作> exists list #判断这个列表是否存在0> lset list 0 item #如果不存在列表咱们去更新就会报错ERR no such key> lpush list value11> lrange list 0 0value1> lset list 0 item #如果存在,更新以后下标的值OK> lrange list 0 0item> lset list 1 other #如果不存在,则会报错ERR index out of range#############################################linsert #将某个具体的value插入到列表中某个元素的后面或者前面> rpush mylist hello3> rpush mylist hello14> linsert mylist before hello1 other5> lrange mylist 0 -1hellootherhello1hellohello1> linsert mylist after other enw6> lrange mylist 0 -1hellootherenwhello1hellohello1
小结
- 它实际上是一个链表,before node after ,left ,right 都能够插入值
- 如果key不存在,创立新的链表
- 如果key存在,新增内容
- 如果移除了所有的值,空链表,也代表不存在
- 在两边插入或者改变值效率最高!两头元素,相对来说效率会低一点
音讯队列(Lpush Rpop) 栈 (Lpush Lpop)
Set(汇合)
set中的值是不能反复的
#############################################> sadd myset hello #set汇合中增加元素1> sadd myset kuangshen1> sadd myset lovekuangshen1> smembersERR wrong number of arguments for 'smembers' command> smembers myset #查看指定set的所有值lovekuangshenkuangshenhello> sismember myset hello #判断某一个值是不是在set汇合中1> sismember myset world0#############################################> scard myset #获取set汇合中的内容元素个数3> sadd myset lovekuangshen #曾经存在的增加失败0#############################################> srem myset hello #移除set汇合中的指定元素1> scard myset2> smembers mysetlovekuangshenkuangshen#############################################set是无序不反复汇合,抽随机> srandmember myset #随机抽选出一个元素kuangshen> srandmember mysetlovekuangshen> srandmember myset 2 #随机抽取指定个数的元素kuangshenlovekuangshen#############################################删除指定的key,随机删除key> smembers mysetlovekuangshenkuangshen> spop myset #随机删除一些set汇合中的元素lovekuangshen> spop mysetkuangshen#############################################将一个指定的值,挪动到另外一个set汇合中> sadd myset hello1> sadd myset hello0> sadd myset world1> sadd myset kuangshen1> sadd myset2 set21> smove myset myset2 kuangshen #将一个指定的值,挪动到另外一个set汇合1> smembers mysetworldhello> smembers myset2set2kuangshen#############################################> sadd key1 a1> sadd key1 b1> sadd key1 c1> sadd key2 c1> sadd key2 d1> sadd key2 e1> sadd key2 e0> sadd key2 key1> sdiff key1 key2 #差集ab> sinter key1 key2 #交加(独特好友就能够这样实现)c> sunion key1 key2 #并集cekeydba
微博,a用户将所有关注的人放在一个set汇合中,将它的粉丝也放在一个汇合中
独特关注,共同爱好,二度好友,举荐好友!(六度宰割实践)
Hash(哈希)
Map汇合,key-Map汇合,实质和String类型没有太大区别,还是一个简略的kv
set myhash field kuangshen
> hset myhash field1 kuangshen #set一个具体key-value1> hget myhash field1 #获取一个字段值kuangshen> hmset myhash field1 hello field2 world #set多个key-valueOK> hmget myhash field1 field2 #获取多个字段值helloworld> hgetall myhash #获取全副的数据field1hellofield2world#############################################> hdel myhash field1 #删除hash指定key字段,对应的value值也就隐没了1> hgetall myhashfield2world#############################################hlen> hmset myhash field1 hello field2 worldOK> hgetall myhashfield2worldfield1hello> hlen myhash #获取hash表的字段数量2#############################################> hexists myhash field #判断hash中指定字段是否存在0> hexists myhash field11##############################################只取得所有field#只取得所有value> hkeys myhash#只取得所有fieldfield2field1> hvals myhash#只取得所有valueworldhello#############################################incr decr> hset myhash field3 5 #指定增量1> hincrby myhash field3 16> hincrby myhash field3 -15> hsetnx myhash field4 hello #如果不存在则能够设置1> hsetnx myhash field4 world #如果存在则不能设置0#############################################> hset user:1 name qinjiang1> hget user:1 nameqinjiang
hash变更的数据user name age 尤其是用户信息之类的,常常变动的信息!hash更适宜于对象的存储,String更加适宜字符串存储
Zset(有序汇合)
在set的根底上,减少了一个值,set k1 v1 zset k1 score1 v1
> zadd myset 1 one #增加一个值1> zadd myset 2 two 3 three #增加多个值1> zrange myset 0 -1onetwothree#############################################排序如何实现> zadd salary 2500 xiaohogn #增加三个用户1> zadd salary 5000 zhangsan1> zadd salary 500 kuangshen1> zrangebyscore salary -inf +inf #显示全副的用户,从小到大排序kuangshenxiaohognzhangsan> zrange salary 0 -1kuangshenxiaohognzhangsan> zrangebyscore salary 0 -1 #显示全副的用户并附带问题kuangshen500xiaohogn2500zhangsan5000> zrangebyscore salary -inf 2500 withscores #显示工资小于2500员工的降序排列kuangshen500xiaohogn2500> zrevrange salary 0 -1 #从大到小排序zhangsankuangshen#############################################移除rem中的元素> zrange salary 0 -1kuangshenxiaohognzhangsan> zrem salary xiaohogn #移除有序汇合中的指定元素1> zrange salary 0 -1kuangshenzhangsan> zcard salary # 获取有序汇合中的个数2#############################################> zadd myset 1 hello1> zadd myset 2 world 3 kuangshen2> zcount myset 1 3 #获取指定区间的成员数量3> zcount myset 1 22
案例思路:set排序 存储班级成绩表,工资排序
一般音讯1 重要音讯2 带权重进行判断
排行榜利用实现
三种非凡数据类型
- geospatial 地理位置
敌人的定位,左近的人,打车间隔计算
redis的geo在redis3.2版本就推出了!这个性能能够推算地理位置的信息,两地之间的间隔,方圆几里的人
getadd http://www.jsons.cn/lngcode/
#geoadd 地理位置#规定:两极无奈间接增加,咱们个别会间接下载城市数据,间接通过java程序一次性导入#参数key 值(纬度经度名称)> geoadd china:city 116.40 39.90 beijing1> geoadd china:city 121.47 31.23 shanghai1> geoadd china:city 106.50 29.53 chongqin1> geoadd china:city 114.08 22.54 shenzhen1> geoadd china:city 120.16 30.24 hangzhou1> geoadd china:city 108.96 34.26 xian1#无效的经度-180度到180度#无效的纬度-85.05112878度到85.05112878度#当坐标地位超出上述指定范畴时,该命令将会返回一个谬误
geopos
> geopos china:city beijing #获取指定的城市的经度和纬度116.3999989628791839.900000091670925> geopos china:city beijing shanghai116.3999989628791839.900000091670925121.4700016379356431.229999039757836
geodist
两人之间的间隔
单位如下
m示意单位为米
km示意单位为千米
mi示意单位为英里
ft示意单位为英尺
> geodist china:city beijing shanghai #查看上海到北京的直线间隔1067378.7564> geodist china:city beijing shanghai km1067.3788> geodist china:city beijing chongqin km1464.0708
georedius 以给定的经纬度为核心
我左近的人?(取得所有左近的人的地址,定位)通过半径来查问
取得指定数量的人,200
所有的数据都应该录入:china:city才会让后果更清晰
> georadius china:city 110 30 1000 km #以110 30这个经纬度为核心,寻找方圆1000km内的城市chongqinxianshenzhenhangzhou> georadius china:city 110 30 500 kmchongqinxian> georadius china:city 110 30 500 km withdist #显示到两头间隔的地位chongqin341.9374xian483.8340> georadius china:city 110 30 500 km withcoord #显示别人的定位信息chongqin106.4999976754188529.529999579006592xian108.9600017666816734.2599996441893> georadius china:city 110 30 500 km withdist withcoord count 1 #筛选出指定的用户chongqin341.9374106.4999976754188529.529999579006592> georadius china:city 110 30 500 km withdist withcoord count 2chongqin341.9374106.4999976754188529.529999579006592xian483.8340108.9600017666816734.2599996441893
georadiusbymember
#找出位于指定元素四周的其余元素> georadiusbymember china:city beijing 1000 kmbeijingxian> georadiusbymember china:city shanghai 400 kmhangzhoushanghai
gethash 命令-返回一个或多个地位元素的geohash示意
该命令将返回11个字符的geohash字符串
#将二维的经纬度转换为一维的字符串,如果两个字符串越靠近,那么则间隔越近> geohash china:city beijing chongqinwx4fbxxfke0wm5xzrybty0
geo 底层的实现原理其实就是Zset!咱们能够应用Zset命令来操作geo
> zrange china:city 0 -1 #查看地图中全副的元素chongqinxianshenzhenhangzhoushanghaibeijing> zrem china:city beijing #移除指定元素1
hyperloglog
什么是基数
A{1.3.5.7.8.9.7}
B{1,3,5,7,8}
基数(不反复的元素) =5 ,能够承受误差!
简介
reids2.8.9版本就更新了Hyperloglog 数据结构
reids hyperloglog 基数统计的算法
网页的uv(一个人拜访一个网站屡次,然而还是算作一个人)
传统的形式,set保留用户的id,而后就能够统计set中的元素数量作为规范判断
这个形式如果保留大量的用户id,就会比拟麻烦!咱们的目标是为了计数,而不是保留用户id
长处:占用的内存是固定的,2^64不同的元素的技术,只须要废12kb内存,如果要从内存角度来比拟的话,hyperloglog是首选
0.81%错误率,统计uv工作,能够忽略不计的
> pfadd mykey a b c d e f g h i j #创立第一组元素1> pfcount mykey #统计mykey元素的基数数量10> pfadd mykey2 i j z x c v b n m #创立第二组元素 1> pfcount mykey29> pfmerge mykey3 mykey mykey2 #合并两组 mykey mykey2 => mykey3 (并集)OK> pfcount mykey3 #查看并集的数量15
如果容许容错,那么肯定能够应用hyperloglog
如果不容许容错,就应用set或者本人的数据类型即可
bitmap
位存储
统计疫情感化人数:010101
统计用户信息,沉闷,不沉闷!登录,未登录!打卡,365打卡!两个状态的,都能够应用bitmaps
Bitmaps 位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态!
365天=365bit 1字节 = 8bit 46个字节左右
测试
应用bitmap来记录 周一到周日的打卡
setbit sign 0 1
0
setbit sign 1 0
0
setbit sign 3 0
0
setbit sign 4 0
0
setbit sign 5 1
0
setbit sign 6 1
0查看某一天是否有打卡
#############################################> getbit sign 40> getbit sign 61
统计打卡天数
> bitcount sign #统计这周的打卡记录,就能够看到是否有全勤3
Redis配置详解
Redis长久化
- RDB
- AOF
Redis事务操作 ACID
redis单条命令是保障原子性的,然而事务不保障原子性的,要么同时胜利,要么同时失败,原子性!
redis事务的实质:一组命令的汇合!一个事务中的所有命令都会被序列化,在事务执行的过程中,会依照程序执行
一次性,程序性,排他性!执行一些列的命令
-----队列 set set set 执行 ----
redis事务没有隔离级别的概念!
所有的命令在事务中,并没有间接被执行!只有发动执行命令的时候才会执行!exec
redis的事务
- 开启事务 (multi)
- 命令入队
- 执行事务 (exec)
锁:redis能够实现乐观锁
失常执行事务!
> multi #开启事务OK #命令入队> set k1 v1QUEUED> set k2 v2QUEUED> get k2QUEUED> set k3 v3QUEUED> exec #执行事务OKOKv2OK
放弃事务
multi #开启事务OK> set k1 v1QUEUED> set k2 v3QUEUED> set k4 b5QUEUED> discard #勾销事务QUEUED> get k4 #事务队列中命令都不会被执行QUEUED> (error) ERR unknown command> DISCARD QUEUED
编译型异样(代码有问题!命令有错!),事务中所有的命令都不会被执行
> multiOK> set k1 v1QUEUED> set k2 v2QUEUED> set k3 v3QUEUED> getset k3 #谬误命令QUEUED> set k4 v4QUEUED> set k5 v5QUEUED> exec #执行事务报错EXECABORT Transaction discarded because of previous errors.> get k5 #所有的命令都不会被执行null
运行时异样(1/0),如果队列中存在一些语法型谬误,那么执行命令的时候,其余命令式能够失常执行的,谬误命令会抛出异样
> set k1 v1OK> multiOK> incr k1 #会执行的时候失败QUEUED> set k2 v2QUEUED> set k3 v3QUEUED> get k3QUEUED> execOKOKv3> get k2v2> get k3v3> get k1v1> incr k1ERR value is not an integer or out of range #尽管第一条命令报错了,然而仍旧失常执行胜利了
监控!watch(面试常问)
乐观锁
- 很乐观,什么时候都会出问题,无论做什么都会加锁!
乐观锁
- 很乐观,认为什么时候都不会呈现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人批改过这个数据,version
- 获取version
- 更新的时候比拟version
redis测监督测试
失常执行胜利> set money 100OK> set out 0OK> watch money #监督money对象OK> multi #事务失常完结,数据期间没有产生变动,这个时候就失常执行胜利OK> decrby money 20QUEUED> incrby out 20QUEUED> exec8020
测试多线程批改值,应用watch能够当做redis的乐观锁操作!
> set money 100OK> set out 0OK> watch money #监督moneyOK> multiOK> decrby money 20QUEUED> incrby out 20QUEUED> exec #执行之前,另外一个线程,批改了咱们的值,这个时候,就会导致事务执行失败null
如果批改失败,获取最新的值就好
Jedis
咱们要应用java来操作redis
什么是jedis是redis官网举荐的java连贯开发工具!应用java操作redis,如果你要应用java操作redis,那么肯定要对jedis非常的相熟测试
1.导入对应的依赖
<!--导入jedis的包--> <dependencies> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency> </dependencies>
2.编码测试:
- 连贯数据库
package com.kuang; import redis.clients.jedis.Jedis; public class testPing { public static void main(String[] args) { //1.new jedis对象即可 Jedis jedis = new Jedis("127.0.0.1",6379); //jedis所有的命令就是咱们之前学习的所有指令~!所以之前的指令学习很重要 System.out.println(jedis.ping()); } }
输入
#### 罕用的api
String
List
Set
Hash
Zset
所有的api命令,就是咱们对应的下面的指令!所以之前的指令学习很重要
- 操作命令
- 断开连接!
SpringBoot整合
SpringBoot操作数据:spring-data jpa jdbc mongodb redis
SpringData也是和Springboot齐名的我的项目
阐明:在springboot2.x后,原来应用的jedis被替换成为了lettuce
jedis:采纳的是直连,多个线程操作的话是不平安的,如果想要防止不平安的,应用jedis pool连接池!BIO阻塞
lettuce:采纳netty,实例能够在多个线程中进行共享,不存在线程不平安的状况!能够缩小线程数量,更像Nio模式
Springboot 所有的配置类,都有一个主动配置类
主动配置类都会绑定一个properties 配置文件
源码剖析
整合测试一下
1.导入依赖
2.配置连贯
3.测试
Redis实现订阅公布(音讯队列)
Redis主从复制
概念
主从复制,是指将一台redis服务器的数据,复制到其余redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制都是单向的,只能由主节点到从节点。master以写为主,slave以读为主。
==默认状况下,每台redis服务器都是主节点==;且一个主节点能够有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制的作用次要包含:
1.数据冗余:主从复制实现了数据的热备份,是长久化之外的一种数据冗余形式
2.故障复原:当主节点呈现问题时,能够由从节点提供服务,实现疾速的故障复原,实际上是一种服务的冗余
3.负载平衡:在主从复制的根底上,配合读写拆散,能够由主节点提供写服务,由从节点提供读服务(即写redis服务时利用读取主节点,读redis服务时利用连贯从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,能够大大提高redis服务器的并发量
4.高可用基石(集群):除了上述作用以外,主从复制还是哨兵和集群可能施行的根底,因而说主从复制是redis高可用的根底
一般来说,==要将redis利用于我的项目工程中,只应用的一台redis服务器是万万不能的==,起因如下:
1.从构造上,单个redis服务器会产生单点故障,并且一台服务器须要解决所有的申请负载,压力较大;
2.从容量上,单个redis服务器内存容量无限,就算一台redis服务器容量为256g,也不能将所有内存用作于redis存储内存,一般来说,==单台redis最大应用内存不应该超过20g==
电商网站上的商品,个别都是一次上传,无数次浏览的,说业余点也就是“多读少写”
主从复制,读写拆散!80%的状况下都是在进行读操作!减缓服务器的压力!架构中常常应用!一主二从!
只有在公司中,主从复制就是必须要应用的
,因为在实在的我的项目中不可能单机应用redis
环境配置
只配置从库,不配置主库
> info replication #查看以后库的信息# Replicationrole:master #角色 masterconnected_slaves:0 #没有从机master_repl_offset:0repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0
复制3个配置文件,而后批改对应的信息
1.端口
2.pid名字
3.log文件名字
4.dump.rdb名字
一主二从
咱们个别状况下只用配置从机就好了
一个主机两个从机
slaveof 127.0.0.1 6379
实在得从主配置应该在配置文件中配置,这样的话是永恒的,咱们这里应用的是命令,临时的!
细节
主机能够写,从机不能写只能读!主机中所有的信息和数据,都会主动被从机保留
主机写:
从机只能读取内容:
测试:主机断开连接,从机仍旧连贯到主机的,然而没有写操作,这个时候,主机如果回来了,从机仍旧能够间接获取到主机写的信息!
如果是应用命令行来配置的主从,这个时候如果重启了,就会主动变回主机!只有变为从机,立马就会从主机中获取值!
复制原理
slave启动胜利连贯到master后会发送一个sync同步命令
Master接到命令,启动后盾的存盘过程,同时收集所有接管到的用于批改数据集命令,在后盾过程执行结束之后,==master将传送整个数据文件到slave,并实现一次齐全同步==
==全量复制==:而salve服务在接管到数据库文件数据后,将其存盘并加载到内存中
==增量复制==:master持续将新的所有收集到的批改命令顺次传给slave,实现同步
然而只有是从新连贯master,一次齐全同步(全量复制)将被主动执行
咱们的数据肯定能够在从机中看到!
层层链路
上一个M连贯下一个S!
这个时候也能够实现咱们的主从复制!
如果没有老大了,这个时候能不能抉择一个老大进去呢?手动!
谋权篡位
如果主机断开了连贯,咱们能够应用SLAVEOF no one
让本人变成主机!其余的节点就能够手动连贯到最新的这个主节点(手动)!如果这个时候老大修复了,那就从新连贯
Redis哨兵模式(当初公司中所有的集群都用哨兵模式)
主动选举老大的模式
概述:
主从切换技术的办法是:当主服务器宕机后,须要手动把一台服务器切换为主服务器,这就须要人工干预,费时费力,还会造成一段时间内服务不可用。这不是一种举荐的形式,更多时候,咱们优先思考哨兵模式。redis从2.8开始正式提供了Sentinel(哨兵模式)架构来解决这个问题
谋权篡位的主动版,可能后盾监控主机是否故障,如果故障了依据投票数主动将从库转换为主库
哨兵模式是一种非凡的模式,首先redis提供了哨兵的命令,哨兵是一个独立的过程,作为过程,它会独立运行,其原理是哨兵通过发送命令,期待redis服务器响应,从而监控运行的多个redis实例
这里哨兵有两个作用
- 通过发送命令,让redis服务器返回监控其运行状态,包含主服务器和从服务器
- 当哨兵检测到master宕机,会主动将slave切换为master,而后通过公布订阅模式告诉其余的从服务器,批改配置文件,让它们切换主机
然而一个哨兵过程对redis服务器进行监控,可能会呈现问题,为此,咱们能够应用多个哨兵进行监控,各个哨兵之间还会进行监控,这样酒就造成了多哨兵模式
假如主服务器宕机,哨兵1先检测到这个后果,零碎并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个景象成为主观下线。当前面的哨兵也检测到主服务器不可用,并且数量达到肯定值时,那么哨兵之间就会进行一次投票,投票后果由一个哨兵发动,进行failover[故障转移]操作。切换胜利后,就会通过公布订阅模式,让各个哨兵把本人监控的从服务器实现切换主机,这个过程称为主观下线
测试
咱们目前的状态是一主二从
1.配置哨兵配置文件
# sentinel monitor 被监控的名称 host port 1sentinel monitor myredis 127.0.0.1 6379 1
前面的数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机!
2.启动哨兵
如果Master节点断开了,这个时候就会从从机中随机抉择一个服务器(这外面有一个投票算法)
哨兵日志
如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规定!
哨兵模式
长处:
1.哨兵集群,基于主从复制模式,所有的主从配置的长处它全有
2.主从能够切换,故障能够转移,零碎的可用性就会更好
3.哨兵模式就是主从模式的降级,手动到主动,更加强壮!
毛病:
1.redis不好啊在线扩容的,集群容量一旦达到下限,在线扩容就非常麻烦
2.实现哨兵模式的配置其实是很麻烦的,外面有很多抉择
哨兵模式的全副配置
# Example sentinel.conf# port <sentinel-port>port 8001# 守护过程模式daemonize yes# 指明日志文件名logfile "./sentinel1.log"# 工作门路,sentinel个别指定/tmp比较简单dir ./# 哨兵监控这个master,在至多quorum个哨兵实例都认为master down后把master标记为odown# (objective down主观down;绝对应的存在sdown,subjective down,主观down)状态。# slaves是主动发现,所以你没必要明确指定slaves。sentinel monitor MyMaster 127.0.0.1 7001 1# master或slave多长时间(默认30秒)不能应用后标记为s_down状态。sentinel down-after-milliseconds MyMaster 1500# 若sentinel在该配置值内未能实现failover操作(即故障时master/slave主动切换),则认为本次failover失败。sentinel failover-timeout TestMaster 10000# 设置master和slaves验证明码sentinel auth-pass TestMaster testmaster123sentinel config-epoch TestMaster 15#除了以后哨兵, 还有哪些在监控这个master的哨兵sentinel known-sentinel TestMaster 127.0.0.1 8002 0aca3a57038e2907c8a07be2b3c0d15171e44da5sentinel known-sentinel TestMaster 127.0.0.1 8003 ac1ef015411583d4b9f3d81cee830060b2f29862
Redis缓存穿透和雪崩(面试高频,工作罕用)
Redis缓存的应用,极大的晋升了应用程序的性能和效率,特地是数据查问方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那么就不能应用缓存。
另外的一些典型问题就是,缓存穿透,缓存雪崩和缓存击穿。目前,业界也都有比拟风行的解决方案
缓存穿透(查不到)
概览
缓存穿透的概念很简略,用户想要查问一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向长久层数据库查问。发现也没有,于是本次查问失败。当用户很多的时候,缓存都没有命中,于是都去申请了长久层数据库。这会给长久层数据库造成很大的压力,这个时候就相当于呈现了缓存穿透。
解决方案
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查问的参数以hash模式存储,在管制层先进行校验,不合乎则抛弃,从而防止了对底层存储系统的查问压力
缓存空对象
当存储层不命中后,即便返回的空对象也将其缓存起来,同时会设置一个过期工夫,之后再拜访这个数据将会间接从缓存中获取,爱护了后端数据源;
然而这种办法会存在两个问题:
1.如果空值可能被缓存起来,这就意味着缓存须要更多的空间存储更多的键,因为这当中可能会有很多的空值的键
2.即便对空值设置了过期工夫,还是会存在缓存层的数据会有一段时间窗口的不统一,这对于须要放弃一致性的业务会有影响。
缓存击穿(量太大,缓存过期!)
概述
微博服务器宕机
这里须要留神和缓存击穿的区别,缓存击穿,是指一个key十分热点,在不停的扛着大并发,大并发集中对这一个点进行拜访,当这个key在生效的霎时,继续的大并发就穿破缓存,间接申请数据库,就像在一个屏障上凿开了一个洞。
当某个key在过期的霎时,有大量的申请并发拜访,这类数据个别是热点数据,因为缓存过期,会同时拜访数据库来查问最新数据,并且回写缓存,会导致数据库霎时压力过大 。
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期工夫,所以不会呈现热点key过期后产生的问题
加互斥锁
分布式锁:应用分布式锁,保障对于每个key同时只有一个线程去查问后端服务,其余线程没有取得分布式锁的权限,因而只须要期待即可。这种形式将高并发的压力转移到了分布式锁,因而对分布式锁的考验很大
缓存雪崩
服务器的高可用问题
概念
缓存雪崩,是指在某一个时间段,缓存集中过期生效,redis宕机!
产生雪崩的起因之一,比方在写文本的时候,马上就要双十二零点,很快就会迎来一波抢购,这波商品工夫比拟集中的放入了缓存,假如缓存一个小时,那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品拜访查问,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的申请都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的状况
其实集中过期,倒不是十分致命,比拟致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为天然造成的缓存雪崩,肯定是在某个时间段集中创立缓存,这个时候,数据库也是考研顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能霎时就把数据库压垮。
双十一:停掉一些服务,(保障次要的服务可用!)==服务降级==
解决方案
redis高可用
这个思维的含意是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其余的还能够持续工作,其实就是搭建的集群(异地多活)
限流降级(在springCloud解说过!)
这个解决方案的思维是,在缓存生效后,通过加锁或者队列来管制读数据库写缓存的线程数量。比方对某个key只容许一个线程查问数据和写缓存,其余线程期待。
数据预热
数据加热的含意就是在正式部署之前,我线把可能的数据先事后拜访一遍,这样局部可能大量拜访的数据就会加载到缓存中。在行将产生大并发拜访前手动触发加载缓存不同的key,设置不同的过期工夫,让缓存生效的工夫点尽量平均