IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis学习记录 -> 正文阅读

[大数据]Redis学习记录

NoSQL的四大分类:

KV键值对
文档型数据库:
MongoDB(要掌握)是一个介于关系型数据库和非关系型数据库中间的产品,是非关系型数据库中功能最丰富,最像关系型数据库的
ConthDB
列存储数据库:
图关系数据库:

Redis:

Remote Dictionary Server 远程字典服务
Redis是单线程的 6.0之后有多线程,将所有的数据全部放在内存中,所以使用单线程去操作效率最高
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-value数据库,并提供多种语言的API
是热门的NoSQL技术之一,也被称为结构化数据库,可以用作数据库、缓存和消息中间件MQ
一共有17个数据库默认使用第0个

Redis作用:

1.内存存储、持久化 什么是持久化(rdb、aof)
2.效率高,可以用于高速缓存
3.发布订阅系统
4.地图信息分析
5.计时器、计数器

Redis和Mysql的区别:

mysql是关系型数据库,redis是缓存数据库
mysql用于持久化的存储数据到硬盘,功能强大,速度较慢,基于磁盘,读写速度没有Redis快,但是不受空间容量限制,性价比高
redis用于存储使用较为频繁的数据到缓存中,读取速度快,基于内存,读写速度快,也可做持久化,但是内存空间有限,当数据量超过内存空间时,需扩充内存,但内存价格贵

windows用命令启动:redis-server redis.windows.conf

打开cli.exe
    127.0.0.1:6379> ping ---->测试链接
    PONG
    127.0.0.1:6379> set name lv ---->设置set key value
    OK
    127.0.0.1:6379> get name ---->根据key获取值
    "lv"
    127.0.0.1:6379> keys * ---->查看当前数据库所有的key
    1) "name"
    127.0.0.1:6379> FLUSHDB ---->清空当前数据库
    OK
    127.0.0.1:6379> FLUSHALL ---->清空全部数据库
    OK
    127.0.0.1:6379> select 3 ---->切换3号数据库
    OK
    127.0.0.1:6379[3]> DBSIZE ---->查看DB大小
    (integer) 0
    127.0.0.1:6379> EXISTS name ---->查看name这个key是否存在
    (integer) 1
    127.0.0.1:6379> move name 1 ---->移除name这个key到1号数据库
    (integer) 1
    127.0.0.1:6379> EXPIRE name 10 ---->设置name这个key10秒后过期
    (integer) 1
    127.0.0.1:6379> ttl name ---->查看过期剩余时间
    (integer) -2
    127.0.0.1:6379> get name
    (nil)
    127.0.0.1:6379> type age ---->查看age这个key的类型
    string

String(字符串):
String类似的使用场景:value除了是字符串还可以是数字

 	127.0.0.1:6379> APPEND KEY1 HELLO ---->往这个key后面加上HELLO,如果这个key不存在,就相当于新建一个key
    (integer) 7
    127.0.0.1:6379> GET KEY1
    "V1HELLO"
    127.0.0.1:6379> STRLEN KEY1 ---->获取这个key的长度
    (integer) 7
    127.0.0.1:6379> incr views ---->自增1
    (integer) 1
    127.0.0.1:6379> decr views ---->自减1
    (integer) 0
    127.0.0.1:6379> INCRBY views 10 ---->可以设置步长,指定增量为10
    (integer) 10
    127.0.0.1:6379> DECRBY views 5 ---->可以设置步长,指定减量为5
    (integer) 5
    127.0.0.1:6379> get name
    "zhangsan"
    127.0.0.1:6379> GETRANGE name 0 3 ---->截取第0个到第三个的字符串
    "zhan"
    127.0.0.1:6379> GETRANGE name 0 -1 ---->截取全部字符串
    "zhangsan"
    127.0.0.1:6379> SETRANGE name 1 xx ---->替换指定位置开始的字符串
    (integer) 8
    127.0.0.1:6379> get name
    "zxxngsan"
    127.0.0.1:6379> setex age 10 22 ---->增加一个age值为22并在10秒后过期
    OK
    127.0.0.1:6379> ttl age
    (integer) -2
    127.0.0.1:6379> get age
    (nil)
    127.0.0.1:6379> setnx mykey redis ---->如果不存在mykey才能增加成功 1代表成功0代表失败
    (integer) 1
    127.0.0.1:6379> setnx mykey mongoDB
    (integer) 0
    127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 ---->批量增加key
    OK
    127.0.0.1:6379> keys *
    1) "views"
    2) "k2"
    3) "name"
    4) "k1"
    5) "mykey"
    6) "k3"
    127.0.0.1:6379> mget k1 k2 k3 ---->批量获取key
    1) "v1"
    2) "v2"
    3) "v3"
    127.0.0.1:6379> msetnx k1 v1 k4 v4 ---->批量创建不存在的key 因为k1已经存在所以后面的k4并不会被创建 (原子性操作,要么一起成功,要么一起失败)
    (integer) 0
    127.0.0.1:6379> mset user:1:name zhangsan user:1:age 22 ---->增加一个user:1对象name的值为zhangsan age的值为22
    OK
    127.0.0.1:6379> mget user:1:name user:1:age
    1) "zhangsan"
    2) "22"
    127.0.0.1:6379> getset db redis ---->先get在set 如果没有db这个key会返回nil然后创建这个key
    (nil)
    127.0.0.1:6379> get db
    "redis"
    127.0.0.1:6379> getset db mongodb ---->先get在set 如果有db这个key会返回这个值然后更新这个值
    "redis"
    127.0.0.1:6379> get db
    "mongodb"

List(列表):
实际上是一个链表,可以作用栈、队列、阻塞队列,在两边插入或改动值,效率最高

 	127.0.0.1:6379> LPUSH list one ---->将一个值或多个值插入到列表头部(左边)
    (integer) 1
    127.0.0.1:6379> LPUSH list two
    (integer) 2
    127.0.0.1:6379> LPUSH list three
    (integer) 3
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> RPUSH list right ---->将一个值或多个值插入到列表尾部(右边)
    (integer) 4
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "right"
    127.0.0.1:6379> Lpop list ---->移除list第一个元素
    "three"
    127.0.0.1:6379> Rpop list ---->移除list最后一个元素
    "right"
    127.0.0.1:6379> LRANGE list 0 -1
    1) "two"
    2) "one"
    127.0.0.1:6379> Lindex list 1 ---->通过下标获取list元素
    "one"
    127.0.0.1:6379> Llen list ---->获取list的长度
    (integer) 2
    127.0.0.1:6379> LREM list 1 one ---->移除list准确个数的value
    (integer) 1
    127.0.0.1:6379> LRANGE list 0 -1
    1) "two"
    127.0.0.1:6379> lrange list 0 -1
    1) "four"
    2) "three"
    3) "one"
    4) "two"
    127.0.0.1:6379> ltrim list 1 2 ---->通过下标截取list指定的长度
    OK
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "one"
    127.0.0.1:6379> lrange list 0 -1
    1) "two"
    2) "four"
    3) "three"
    4) "one"
    127.0.0.1:6379> rpoplpush list list2 ---->移除列表最后一个元素并移动到list2里
    "one"
    127.0.0.1:6379> lrange list 0 -1
    1) "two"
    2) "four"
    3) "three"
    127.0.0.1:6379> lrange list2 0 -1
    1) "one"
    127.0.0.1:6379> exists list ---->判断这个list是否存在
    (integer) 1
    127.0.0.1:6379> lrange list 0 0
    1) "two"
    127.0.0.1:6379> lset list 0 five ---->将列表指定下标的值替换为另外一个值(如果不存在会报错)
    OK
    127.0.0.1:6379> lrange list 0 0
    1) "five"
    127.0.0.1:6379> lrange list 0 -1
    1) "two"
    127.0.0.1:6379> linsert list before two three ---->将某个具体的value插入到列表某个value的前面
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    127.0.0.1:6379> linsert list after two one ---->将某个具体的value插入到列表某个value的后面
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"

Set(集合):
set中的值是不能重复的,并且是无序的

	127.0.0.1:6379> sadd myset hello ---->往myset集合里赋值
    (integer) 1
    127.0.0.1:6379> sadd myset lv
    (integer) 1
    127.0.0.1:6379> sadd myset redis
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset ---->查看myset集合里的值
    1) "hello"
    2) "redis"
    3) "lv"
    127.0.0.1:6379> SISMEMBER myset hello ---->判断myset集合里是否有hello这个值
    (integer) 1
    127.0.0.1:6379> SISMEMBER myset world ---->判断myset集合里是否有world这个值
    (integer) 0
    127.0.0.1:6379> scard myset ---->获取set集合中的元素个数
    (integer) 3
    127.0.0.1:6379> srem myset hello ---->移除set集合中的指定元素
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset
    1) "redis"
    2) "lv"
    127.0.0.1:6379> SRANDMEMBER myset ---->随机抽取set集合一个元素,后面可以加个数
    "lv"
    127.0.0.1:6379> SRANDMEMBER myset ---->随机抽取set集合一个元素,后面可以加个数
    "redis"
    127.0.0.1:6379> spop myset ---->随机移除set集合的元素
    "mongodb"
    127.0.0.1:6379> sadd myset2 set2
    (integer) 1
    127.0.0.1:6379> smove myset myset2 lv ---->将lv元素从myset移动到myset2集合
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset
    1) "world"
    2) "hello"
    127.0.0.1:6379> SMEMBERS myset2
    1) "set2"
    2) "lv"
    数字集合类:差集、交集、并集:共同关注可以这样实现
    127.0.0.1:6379> SDIFF myset myset2 ---->差集
    1) "hello"
    2) "world"
    127.0.0.1:6379> SINTER myset myset2 ---->交集,拥有的同样的元素
    1) "lv"
    127.0.0.1:6379> SUNION myset myset2 ---->并集
    1) "set2"
    2) "hello"
    3) "world"
    4) "lv"

Hash(哈希):
可以看做Map集合 key-value,当key-map的时候,这个值是个map集合,本质和String类型没有太大区别,还是一个简单的key-value
使用场景:hash可以存变更的数据,比如用户信息,经常变动的信息,比较适合对象的存储

 	127.0.0.1:6379> hset myhash field1 lv ---->set一个key-value
    (integer) 1
    127.0.0.1:6379> hget myhash field1
    "lv"
    127.0.0.1:6379> hmset myhash field1 hello field2 world ---->set多个key-value
    OK
    127.0.0.1:6379> hmget myhash field1 field2 ---->获取多个key的value
    1) "hello"
    2) "world"
    127.0.0.1:6379> hgetall myhash ---->获取全部的数据
    1) "field1"
    2) "hello"
    3) "field2"
    4) "world"
    127.0.0.1:6379> hdel myhash field1 ---->删除指定的key-value
    (integer) 1
    127.0.0.1:6379> hgetall myhash
    1) "field2"
    2) "world"
    127.0.0.1:6379> hlen myhash ---->获取myhash的数量
    (integer) 1
    127.0.0.1:6379> hexists myhash field1 ---->判断指定的key是否存在
    (integer) 0
    127.0.0.1:6379> hkeys myhash ---->只获取所有的key
    1) "field2"
    127.0.0.1:6379> hvals myhash ---->只获取所有value
    1) "world"
    127.0.0.1:6379> hset myhash field1 5
    (integer) 1
    127.0.0.1:6379> hincrby myhash field1 1 ---->指定增量
    (integer) 6
    127.0.0.1:6379> hincrby myhash field1 -1 ---->指定减量
    (integer) 5
    127.0.0.1:6379> hsetnx myhash field4 hello ---->如果不存在则创建 存在则不能设置
    (integer) 1
    127.0.0.1:6379> hsetnx myhash field4 hello ---->如果不存在则创建 存在则不能设置
    (integer) 0

Zset(有序集合):
在set的基础上,增加一个值。 普通消息,重要消息,带权重进行判断,应用场景:排行榜排序

	127.0.0.1:6379> zadd myset 1 one ---->添加一个值
    (integer) 1
    127.0.0.1:6379> zadd myset 2 two
    (integer) 1
    127.0.0.1:6379> zadd myset 3 three
    (integer) 1
    127.0.0.1:6379> zrange myset 0 -1 ---->遍历集合
    1) "one"
    2) "two"
    127.0.0.1:6379> zadd gz 2500 xiaohong
    (integer) 1
    127.0.0.1:6379> zadd gz 5000 zhangsan
    (integer) 1
    127.0.0.1:6379> zadd gz 8000 lv
    (integer) 1
    127.0.0.1:6379> ZRANGEBYSCORE gz -inf +inf ---->显示全部用户 从小到大
    1) "xiaohong"
    2) "zhangsan"
    3) "lv"
    127.0.0.1:6379> ZREVRANGE gz 0 -1 ---->显示全部用户 从大到小
    1) "lv"
    2) "zhangsan"
    127.0.0.1:6379> ZRANGEBYSCORE gz -1 0
    (empty list or set)
    127.0.0.1:6379> ZRANGEBYSCORE gz -inf +inf  withscores ---->显示全部用户 从小到大并且附带值
    1) "xiaohong"
    2) "2500"
    3) "zhangsan"
    4) "5000"
    5) "lv"
    6) "8000"
    127.0.0.1:6379> ZRANGEBYSCORE gz -inf 2500 withscores ---->显示工资小于2500的升序排序
    1) "xiaohong"
    2) "2500"
    127.0.0.1:6379> zrem gz xiaohong ---->移除元素
    (integer) 1
    127.0.0.1:6379> zrange gz 0 -1
    1) "zhangsan"
    2) "lv"
    127.0.0.1:6379> zcard gz ---->获取有序集合中的个数
    (integer) 2
    127.0.0.1:6379> zcount gz 2500 5000 ---->获取指定区间的数量
    (integer) 2
    127.0.0.1:6379> zcount gz 2500 8000
    (integer) 3

geospatial地理位置:
场景:定位,附近的人,打车距离计算,底层命令就是Zset 可以用Zset命令来操作Geo

 	127.0.0.1:6379> GEOADD china:city 118.11022 24.490474 xiamen ---->添加地理位置 key 经度 纬度 名称
    (integer) 1
    127.0.0.1:6379> GEOADD china:city 121.472644 31.231706 shanghai
    (integer) 1
    127.0.0.1:6379> geoadd china:city 116.405285 39.904989 beijing
    (integer) 1
    127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen
    (integer) 2
    127.0.0.1:6379> GEOPOS china:city beijing chongqing ---->获取指定的城市的经纬度
    1) 1) "116.40528291463852"
       2) "39.904988422912503"
    2) 1) "106.49999767541885"
       2) "29.529999579006592"
    127.0.0.1:6379> GEODIST china:city beijing shanghai ---->查看两地的直线距离
    "1067597.9668"
    127.0.0.1:6379> GEODIST china:city beijing shanghai km ---->查看两地的直线距离 km为单位
    "1067.5980"
    127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km ---->在china:city以100,30经纬度查找半径1000km的城市
    1) "chongqing"
    2) "shenzhen"
    127.0.0.1:6379> GEORADIUS china:city 110 30 500 km ---->在china:city以100,30经纬度查找半径500km的城市
    1) "chongqing"
    127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist ---->在china:city以100,30经纬度查找半径500km的城市并显示直线距离
    1) 1) "chongqing"
       2) "341.9374"
    127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord ---->在china:city以100,30经纬度查找半径500km的城市并显示经纬度
    1) 1) "chongqing"
       2) 1) "106.49999767541885"
          2) "29.529999579006592"
    127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 1 ---->在china:city以100,30经纬度查找半径500km的城市并显示经纬度 并且只显示一个结果
    1) 1) "chongqing"
       2) "341.9374"
       3) 1) "106.49999767541885"
          2) "29.529999579006592"
    127.0.0.1:6379> GEORADIUSBYMEMBER china:city xiamen 1000 km ----> 找出位于指定元素周围的其他元素
    1) "shenzhen"
    2) "xiamen"
    3) "shanghai"
    127.0.0.1:6379> geohash china:city beijing xiamen ---->将经纬度转为字符串
    1) "wx4g0b7xrt0"
    2) "ws7grdm5re0"

hyperloglog
基数统计的算法 场景:网页的uv 传统的方式,set保存用户的id,然后可以统计set中元素数量作为标准判断

	127.0.0.1:6379> PFadd mykey a b c d e f g h i j k l ---->创建第一组元素mykey
    (integer) 1
    127.0.0.1:6379> PFcount mykey ---->统计mykey元素的基数数量
    (integer) 12
    127.0.0.1:6379> PFadd mykey2 j k l m n o p q r s t ---->创建第二组元素mykey2
    (integer) 1
    127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 ---->合并两组mykey 和 mykey2 成mykey3  并集
    OK
    127.0.0.1:6379> pfcount mykey3
    (integer) 19

Bitmaps
位存储,场景:统计用户信息,登陆和未登陆的用户,只有两个状态的都可以使用
数据结构,操作二进制位来进行记录,只有0和1两个状态

 	127.0.0.1:6379> setbit sign 0 1  ---->设置sign的元素
    (integer) 0
    127.0.0.1:6379> setbit sign 1 1
    (integer) 0
    127.0.0.1:6379> setbit sign 2 0
    (integer) 0
    127.0.0.1:6379> getbit sign 1  ---->查看sign的元素
    (integer) 1
    127.0.0.1:6379> bitcount sign ---->统计sign值为1的元素
    (integer) 2

Redis的事务
事务本质:一组命令的集合 一个事务中的所有命令都会被序列化,执行过程中会按顺序执行,一次性、顺序性、排他性
单条命令有原子性,但是事务没有原子性,没有隔离级别的概念
1.开启事务(multi) 2.命令入队(…) 3.执行事务(exec)

 	127.0.0.1:6379> multi ---->开启事务
    OK
    127.0.0.1:6379> set k1 v1 ---->命令入队
    QUEUED
    127.0.0.1:6379> exec ---->执行事务
    1) OK
    127.0.0.1:6379> MULTI ---->开启事务
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> discard ---->取消事务 队列里的不会被执行
    OK
    127.0.0.1:6379> get k1
    "v1"
    127.0.0.1:6379> get k2
    (nil)

编译型异常(代码有问题,执行的命令有错误)事务中所有的命令都不会被执行

 	127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> set k3 v3
    QUEUED
    127.0.0.1:6379> getset k3 ---->错误的命令,后面执行事务的时候全部命令都不会被执行
    (error) ERR wrong number of arguments for 'getset' command
    127.0.0.1:6379> set k4 v4
    QUEUED
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> get k1
    (nil)

运行时异常(1/0)如果事务队列中存在语法性,那么执行命令的时候其他命令是可以正常执行的,错误命令抛出异常

	127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incr k1
    QUEUED
    127.0.0.1:6379> get k1
    QUEUED
    127.0.0.1:6379> exec
    1) (error) ERR value is not an integer or out of range ---->
    2) "v1"

乐观锁
多线程修改值,使用watch可以当做redis的乐观锁操作

	127.0.0.1:6379> set money 100
    OK
    127.0.0.1:6379> set out 0
    OK
    127.0.0.1:6379> watch money ---->监视money对象(乐观锁)
    OK
    127.0.0.1:6379> multi ---->事务正常结束 数据没有发生变动,这时候正常执行成功
    OK
    127.0.0.1:6379> DECRBY money 20
    QUEUED
    127.0.0.1:6379> INCRBY out 20
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 80
    2) (integer) 20

Jedis
是redis官方推荐的java连接开发工具,使用java操作redis中间件
导入对应的依赖

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
    </dependency>

用IDEA模拟开启事务:

  public class Test {
            public static void main(String[] args) {
                //新建一个jedis对象
                Jedis jedis = new Jedis("127.0.0.1",6379);
                jedis.flushDB();
                JSONObject jsonObject = new  JSONObject();
                jsonObject.put("hello","world");
                jsonObject.put("name","zhangsan");
                //开启事务
                Transaction multi = jedis.multi();
                String result = jsonObject.toString();
                //jedis.watch(result);
                try {
                    multi.set("user1",result);
                    multi.set("user2",result);
                    multi.exec();
                }catch (Exception e){
                    multi.discard();
                    e.printStackTrace();
                }finally {
                    System.out.println(jedis.get("user1"));
                    System.out.println(jedis.get("user2"));
                    jedis.close();
                }
            }
        }

SpringBoot整合:
在SpringBoot2.x之后Jedis被替换成lettuce
Jedis:采用的直连,多个线程操作是不安全的,如果想避免不安全要使用jedis pool连接池 BIO模式
lettuce:采用的netty,实例可以在多个线程中共享,不存在线程不安全,可以减少线程数据 NIO模式

pom.xml加入依赖
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    配置文件
    spring.redis.host=127.0.0.1
    spring.redis.port=6379

Redis持久化

Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失,所以Redis提供了持久化功能

RDB持久化操作:

配置文件中修改save 60
5,只要60秒内修改5次key,执行flushall命令和退出redis的时候就会触发rdb操作,自动生成的文件为dump.rdb
127.0.0.1:6379> config get dir
1) “dir”
2) “D:\Redis\Redis-x64-3.0.504” ---->dump.rdb文件目录
优点:
1.适合大规模的数据恢复
2.对数据的完整性要求不高
缺点:
1.需要一定的时间间隔进程操作,如果redis意外宕机了,最后一次修改的数据就没了
2.fork进程的时候,会占用一定的内容空间

AOF持久化操作:

将我们所有的命令都记录下来,history,恢复的时候就把这个文件全部执行一遍
配置文件中默认不开启appendonly no 改为yes就是开启
如果aof文件有错误,redis是启动不起来的,我们需要用redis-check-aof修复aof文件
优点:
1.每一次修改都同步,文件的完整性会更好
2.每秒同步一次,可能会丢失一秒的数据
3.从不同步,效率最高
缺点:
1.相对于数据文件来说,aof远远大于rdb,修复的速度比rdb慢
2.aof运行效率也比rdb慢,所以我们redis默认就是rdb持久化

总结:

RDB持久化方式就是能在指定的时间间隔内对你的数据进行快照存储
AOF持久化方式就是记录每次对服务器写的操作命令,服务器重启就会重新执行这些命令来恢复数据
只做缓存,如果希望数据在服务器运行的时候存在,可以不使用任何持久化

Redis发布订阅

是一种消息通信模式:发送者发送消息,订阅者接收消息

Redis主从复制

主从复制是指将一台Redis服务器的数据复制到其他的Redis服务器,数据的复制是单向的,只能从主节点到从节点,读写分离。
主机能写入数据,从机只能读取数据
主从复制的作用:
1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
2.故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际是一种服务的冗余
3.负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务
4.高可用(集群)基石:主从复制还是哨兵和集群能够实施基础

 127.0.0.1:6379> info replication ---->查看当前库的信息
    # Replication
    role:master ---->角色 主机
    connected_slaves:0 ---->没有从机
    master_repl_offset:0
    repl_backlog_active:0
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:0
    repl_backlog_histlen:0
    默认情况下每台Redis服务器都是主节点,一般只用配置从机
    SLAVEOF 127.0.0.1 6379 ---->配置主机是谁,命令配置的话只是暂时性的,用配置文件是永久的
    全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
    增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
    只要重新链接master,一次全量复制将被自动执行

Redis哨兵模式

1.配置哨兵配置文件sentinel.conf
sentinel monitor myredis 127.0.0.1 6379 1 ---->后面的数字1代表主机宕机后slave投票票数最多的成为主机
2.启动哨兵
redis-sentinel kconfig/sentinel.conf
如果从机选举完了,主机连接回来了,主机会被哨兵模式切换成从机
优点:
1.哨兵集群,基于主从复制模式,所有的主从配置优点都有
2.主从可以切换,故障可以转移,系统的可用性好
3.哨兵模式就是主从模式的升级,手动到自动
缺点:
1.Redis不好在线扩容,集群容量一旦到达上限,在线扩容就十分麻烦
2.实现哨兵模式的配置是很麻烦的

哨兵模式的全部配置:

  # Example sentinel.conf
    # 哨兵sentinel实例运行的端口 默认26379
    port 26379

# 哨兵sentinel的工作目录
    dir /tmp

    # 哨兵sentinel监控的redis主节点的 ip port
    # master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
    # quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
    # sentinel monitor <master-name> <ip> <redis-port> <quorum>
    sentinel monitor mymaster 127.0.0.1 6379 2

    # 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
    # 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
    # sentinel auth-pass <master-name> <password>
    sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

    # 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
    # sentinel down-after-milliseconds <master-name> <milliseconds>
    sentinel down-after-milliseconds mymaster 30000

    # 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
    # sentinel parallel-syncs <master-name> <numslaves>
    sentinel parallel-syncs mymaster 1

    # 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
    #1. 同一个sentinel对同一个master两次failover之间的间隔时间。
    #2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
    #3.当想要取消一个正在进行的failover所需要的时间。
    #4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
    # 默认三分钟
    # sentinel failover-timeout <master-name> <milliseconds>
    sentinel failover-timeout mymaster 180000

    # SCRIPTS EXECUTION
    #配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
    #对于脚本的运行结果有以下规则:
    #若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
    #若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
    #如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
    #一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
    #通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。

    #通知脚本
    # shell编程
    # sentinel notification-script <master-name> <script-path>
    sentinel notification-script mymaster /var/redis/notify.sh

    # 客户端重新配置主节点参数脚本
    # 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
    # 以下参数将会在调用脚本时传给脚本:
    # <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
    # 目前<state>总是“failover”,
    # <role>是“leader”或者“observer”中的一个。
    # 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
    # 这个脚本应该是通用的,能被多次调用,不是针对性的。
    # sentinel client-reconfig-script <master-name> <script-path>
    sentinel client-reconfig-script mymaster /var/redis/reconfig.sh # 一般都是由运维来配置!

Redis缓存穿透和雪崩(重点)

缓存穿透概念:用户想查一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有
于是本次查询失败,当用户很多的时候,缓存都没有命中,就都会去请求持久层数据库,这就给持久层数据库造成很大压力(一直查不到某个数据)
解决方案:
1.布隆过滤器:布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力

缓存击穿概念:是指一个key非常热点,在不停的抗着大并发,大并发集中对这一点进行访问,当这个key在失效的瞬间,大并发就
穿破缓存,直接请求数据库,导致数据库瞬间压力过大(比如微博热搜某条热搜一直被搜索)
解决方案:
1.设置热点数据永不过期
2.分布式锁

缓存雪崩概念:是指在某一个时间段,缓存集体过期失效
解决方案:
1.redis高可用
2.限流降级
3.数据预热

内存淘汰和过期key删除策略

Redis 4.0前具体回收策略有以下6种: ● volatile-lru: 在所有带有过期时间的 key 中使用 LRU 算法淘汰数据;
● alkeys-lru: 在所有的 key 中使用最近最少被使用 LRU 算法淘汰数据,保证新加入的数据正常; ●
volatile-random: 在所有带有过期时间的 key 中随机淘汰数据; ● allkeys-random: 在所有的 key
中随机淘汰数据; ● volatile-ttl: 在所有带有过期时间的 key 中,淘汰最早会过期的数据; ● noeviction:
不回收,当达到最大内存的时候,在增加新数据的时候会返回 error,不会清除旧数据,这是 Redis 的默认策略;

Ps: volatile-lru, volatile-random, volatile-ttl 这几种情况在 Redis 中没有带有过期
Key 的时候跟 noeviction 策略是一样的。淘汰策略是可以动态调整的,调整的时候是不需要重启的

Redis 4.0后增加以下两种: ●
volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰(LFU(Least
Frequently Used)算法,也就是最频繁被访问的数据将来最有可能被访问到) ●
allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key。

常见的过期删除策略是惰性删除、定期删除、定时删除。Redis中同时使用了惰性删除和定期删除两种。

(1)惰性删除:只有访问这个键时才会检查它是否过期,如果过期则清除。 ● 优点:最大化地节约CPU资源。 ●
缺点:如果大量过期键没有被访问,会一直占用大量内存。

(2)定时删除:为每个设置过期时间的key都创造一个定时器,到了过期时间就清除。 ● 优点:该策略可以立即清除过期的键。 ●
缺点:会占用大量的CPU资源去处理过期的数据。

(3)定期删除:每隔一段时间就对一些键进行检查,删除其中过期的键。该策略是惰性删除和定时删除的一个折中,既避免了占用大量CPU资源又避免了出现大量过期键不被清除占用内存的情况。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:40:05  更:2022-06-14 22:41:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:30:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码