redis初级笔记
根据狂神说Java的视频以及redis中文官网文档所做的笔记 --yuhang.tang
默认16个数据库(0-15)
redis-cli #进入redis
127.0.0.1:6379> select 3 #选择3号数据库
OK
127.0.0.1:6379[3]> dbsize #数据库当前大小
(integer) 0
127.0.0.1:6379[3]> keys * #查看所有key
(empty array)
flushdb #清空当前库
flushall #清空全部数据库的内容
redis是单线程的,很快的,redis基于内存操作,CPU不是redis性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了
为什么单线程还这么快?
redis是将所有的数据全部放在内存中,所以使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的工作!!!)对于内存系统来说,没有上下文切换效率就是最高的!
127.0.0.1:6379[3]> set name yuhang
OK
127.0.0.1:6379[3]> get name
"yuhang"
127.0.0.1:6379[3]> exists name #判断是否存在:存在
(integer) 1
127.0.0.1:6379[3]> exists name1 #不存在
(integer) 0
127.0.0.1:6379[3]> type name #查看key的格式
string
127.0.0.1:6379[3]> get name
"yuhang"
127.0.0.1:6379[3]> expire name 5 #expire key 秒数n 让该key n秒后过期
(integer) 1
127.0.0.1:6379[3]> get name
(nil)
String
127.0.0.1:6379[3]> get key1
"va"
127.0.0.1:6379[3]> append key1 vi #append key string 在key中的value追加字符串,如果key不存在,则相当于set
(integer) 4
127.0.0.1:6379[3]> get key1
"vavi"
127.0.0.1:6379[3]> strlen key1 #strlen key 查看value长度
(integer) 4
127.0.0.1:6379[3]> set view 0
OK
127.0.0.1:6379[3]> incr view #incr key 自动递增
(integer) 1
127.0.0.1:6379[3]> incr view
(integer) 2
127.0.0.1:6379[3]> get view
"2"
127.0.0.1:6379[3]> decr view #decr key 递减
(integer) 1
127.0.0.1:6379[3]> incrby view 10 #incrby key n 增加n
(integer) 11
127.0.0.1:6379[3]> decrby view 5 #decrby key n 减少n
(integer) 6
127.0.0.1:6379[3]> set key1 "hello,world"
OK
127.0.0.1:6379[3]> getrange key1 0 3 #getrange key 起始 终止 截取key1中0-3
"hell"
127.0.0.1:6379[3]> getrange key1 0 -1 #截取所有
"hello,world"
#setex(set with expire ) #设置过期时间
127.0.0.1:6379[3]> mset k1 v1 k2 v2 k3 v3 k4 v4 #mset 批量添加key-value
OK
127.0.0.1:6379[3]> keys *
1) "k2"
2) "k3"
3) "k1"
4) "k4"
127.0.0.1:6379[3]> mget k1 k2 k3 k4 #mget 批量得到value
1) "v1"
2) "v2"
3) "v3"
4) "v4"
setnx k1 v1 #只有在k1不存在时,添加v1
List
在redis中,我们可以把list当成栈和队列
127.0.0.1:6379[3]> lpush list one #lpush key 将一个值或者多个值插入list头部
(integer) 1
127.0.0.1:6379[3]> lpush list two'
Invalid argument(s)
127.0.0.1:6379[3]> lpush list two
(integer) 2
127.0.0.1:6379[3]> lpush list three
(integer) 3
127.0.0.1:6379[3]> lrange list 0 -1 #lrange key n1 n2
1) "three"
2) "two"
3) "one"
lpop list #移除左边的
rpop list #移除右边的
lindex list n #通过下标获得list中的值
llen list #查看长度
lrem list 1 one # 移除list集合中之指定个数的value,
ltrim list 1 3 #截取下标范围的值,只剩下
exists list #查看列表是否存在
List的常用案例
正如你可以从上面的例子中猜到的,list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是,你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作,将会非常快,也会很容易扩展到百万级别元素的规模。
例如在评级系统中,比如社会化新闻网站 reddit.com,你可以把每个新提交的链接添加到一个list,用LRANGE可简单的对结果分页。
在博客引擎实现中,你可为每篇日志设置一个list,在该list中推入博客评论,等等
List上的阻塞操作
可以使用Redis来实现生产者和消费者模型,如使用LPUSH和RPOP来实现该功能。但会遇到这种情景:list是空,这时候消费者就需要轮询来获取数据,这样就会增加redis的访问压力、增加消费端的cpu时间,而很多访问都是无用的。为此redis提供了阻塞式访问 BRPOP 和 BLPOP 命令。 消费者可以在获取数据时指定如果数据不存在阻塞的时间,如果在时限内获得数据则立即返回,如果超时还没有数据则返回null, 0表示一直阻塞。
同时redis还会为所有阻塞的消费者以先后顺序排队。
Set()
- 无序不重复集合
127.0.0.1:6379[3]> sadd myset "hello" #sadd set 添加set值
(integer) 1
127.0.0.1:6379[3]> sadd myset "kaungshen"
(integer) 1
127.0.0.1:6379[3]> sadd myset "yuhang"
(integer) 1
127.0.0.1:6379[3]> smembers myset #查看set集合中的所有值
1) "kaungshen"
2) "yuhang"
3) "hello"
127.0.0.1:6379[3]> sismember myset yu #sismember set #判断是否该值存在于set中
(integer) 0
127.0.0.1:6379[3]> sismember myset yuhang
(integer) 1
127.0.0.1:6379[3]> scard myset #scard set 获取set集合中内容元素个数
127.0.0.1:6379[3]> srem myset hello #srem myset 移除set中的某个元素
(integer) 1
127.0.0.1:6379[3]> srandmember myset #srandmember 随机抽取一个元素
"kaungshen"
###########################################################################################
微博,b站:共同关注
- 差集 sdiff key1 key2
- 交集 sinter key1 key2
- 并集 sunion key1 key2
Hash()
map集合,key-map 这时候这个值是一个map集合,即key -,本质和string类型没有太大区别
Zset(有序集合)
- 在set的基础上,增加了一个值,set k1 v1 zset k1 score1 v1
127.0.0.1:6379[3]> zadd myset 1 one 2 two 3 three #添加多对 set
(integer) 3
127.0.0.1:6379[3]> zrange myset 0 -1 #查看所有set
1) "one"
2) "two"
3) "three"
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@排序如何实现@@@@@@@@@@@@@@@@@@@@@@@
127.0.0.1:6379[3]> zadd salary 500 xiaohong 1500 xiaoming 2500 xiaohua
(integer) 3
127.0.0.1:6379[3]> zrange salary 0 -1
1) "xiaohong"
2) "xiaoming"
3) "xiaohua"
127.0.0.1:6379[3]> zrangebyscore salary -inf +inf #zrangebyscore 通过分数排序 -inf +inf 负无穷到正无穷
1) "xiaohong"
2) "xiaoming"
3) "xiaohua"
geospatial地理位置
-
朋友的位置,城市经纬度,打车距离
#getadd 添加地理位置 #规则: 两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入! #参数 key 值(经度,经度,名称) 127.0.0.1:6379[5]> geoadd china:city 116.40 39.90 beijing (integer) 1 127.0.0.1:6379[5]> geoadd china:city 117.40 49.90 shanghai (integer) 1 127.0.0.1:6379[5]> geoadd china:city 108.40 34.66 xian (integer) 1
geodist 返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在, 那么命令返回空值。
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
计算出的距离会以双精度浮点数的形式被返回。 如果给定的位置元素不存在, 那么命令返回空值。
Hyperloglog基数统计
什么是基数?
A{1,3,5,7,8,7}
B{1,3,5,7,8}
基数等于不重复的元素=5,可以接受误差!
网页的UV(一个人访问一个网站多次,但还是算作一个人!)
127.0.0.1:6379[5]> pfadd mykey 1 2 3 5 6 78 9 4 1 2 3 4 5 #添加元素
(integer) 1
127.0.0.1:6379[5]> pfcount mykey #统计基数
127.0.0.1:6379[5]> pfadd mykey1 7 8 9 10
(integer) 1
127.0.0.1:6379[5]> pfmerge mykey2 mykey mykey1 #将mykey和mykey1合并为mykey2
OK
127.0.0.1:6379[5]> pfcount mykey2
(integer) 11
Bitmaps
位存储
例:疫情感染人数:0 1 0 1 1 1
统计用户信息:登录与未登录,打卡与未打卡
事务
原子性:要么同时成功,要么同时失败
事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
用法
MULTI 命令用于开启一个事务,它总是返回 OK
。 MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。
redis的事务:
- 开启事务(multi)
- 命令入队( …)
- 执行事务(exec) 或者 放弃事务(discard)
127.0.0.1:6379[5]> multi #开启事务
127.0.0.1:6379[5](TX)> set key1 yuhang #命令入队
QUEUED
127.0.0.1:6379[5](TX)> lpush key2 455
QUEUED
127.0.0.1:6379[5](TX)> set key3 kaungshen
QUEUED
127.0.0.1:6379[5](TX)> exec #执行事务
1) OK
2) (integer) 1
3) OK
- 编译时异常:其中一条命令错了 整个队列中的命令都不会执行
- 运行时异常:其中一条命令错了 整个队列中的命令会执行
悲观锁:
- 很悲观,认为什么时候都会出问题,无论做什么都会加锁!
乐观锁:
- 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据时去判断一下,在此期间是否有人修改过这个数据
- 获取version
- 更新的时候比较version
测试多线程修改值,使用watch可以当做redis的乐观锁操作!
-
watch key 监视
-
unwatch 放弃监视
将redis当做使用LRU算法的缓存来使用
当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据是件很方便的事情。这个行为在开发者社区非常有名,因为它是流行的memcached系统的默认行为。
LRU是Redis唯一支持的回收方法。本页面包括一些常规话题,Redis的maxmemory
指令用于将可用内存限制成一个固定大小,还包括了Redis使用的LRU算法,这个实际上只是近似的LRU。
回收策略
当maxmemory限制达到的时候Redis会使用的行为由 Redis的maxmemory-policy配置指令来进行配置。
以下的策略是可用的:
-
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
-
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
-
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
-
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
-
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
-
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
一般的经验规则:
-
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
-
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
-
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
-
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
-
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
-
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
近似LRU算法
Redis的LRU算法并非完整的实现。这意味着Redis并没办法选择最佳候选来进行回收,也就是最久未被访问的键。相反它会尝试运行一个近似LRU的算法,通过对少量keys进行取样,然后回收其中一个最好的key(被访问时间较早的)。
不过从Redis 3.0算法已经改进为回收键的候选池子。这改善了算法的性能,使得更加近似真是的LRU算法的行为。
Redis LRU有个很重要的点,你通过调整每次回收时检查的采样数量,以实现调整算法的精度
Redis为什么不使用真实的LRU实现是因为这需要太多的内存
Redis_持久化
Redis 提供了不同级别的持久化方式:
- RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
- AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
- 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
- 你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
- 最重要的事情是了解RDB和AOF持久化方式的不同,让我们以RDB持久化方式开始:
RDB持久化
RDB的优点
-
RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
-
RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
-
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
-
与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
-
RDB的缺点
-
如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
-
RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.
AOF持久化
append-only file 只追加操作的文件
将我们的命令全部记录下来,再重新执行一遍
默认不开启
AOF 优点
-
使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
-
AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
-
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
-
AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
AOF 缺点
-
对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
-
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
AOF有多耐用?
**你可以配置 Redis 多久才将数据 fsync 到磁盘一次。有三种方式:**fsync(同步)
- 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
- 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
- 从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
- 推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
日志重写
因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令; Redis 2.4 则可以自动触发 AOF 重写, 具体信息请查看 2.4 的示例配置文件。
快照snapshotting
在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。你也可以通过调用 SAVE或者 BGSAVE , 手动让 Redis 进行数据集保存操作。
save 60 1000 #Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集
工作方式
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
- Redis 调用forks. 同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。
触发机制
1 save的规则满足的情况下,会自动触发rdb规则
2.执行flushall命令,也会触发我们的rdb规则
3.退出redis,也会产生rdb文件
备份就自动生成一个dump。rdb
如何恢复rdb文件?
1.只需要将rdb文件放在我们redis启动目录就可以,redis启动的时候会自动检查dump.rdb恢复其中的数据!
redis发布/订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
使用场景:
1.实时消息系统!
2.实时聊天
3 订阅,关注系统都是可以的
Redis主从复制
- 主 redis 中的数据有两个副本(replication)即从 redis1 和从 redis2,即使一台 redis 服务器宕机其它两台 redis 服务也可以继续提供服务。
- 主 redis 中的数据和从 redis 上的数据保持实时同步,当主 redis 写入数据时通过主从复制机制会复制到两个从 redis 服务上。
- 只有一个主 redis,可以有多个从 redis。
- 主从复制不会阻塞 master,在同步数据时,master 可以继续处理 client 请求。
- 一个 redis 可以即是主又是从
配置
修改从 redis 服务器上的 redis.conf 文件,添加 slaveof 主 redisip 主 redis 端口。
上边的配置说明当前该从 redis 服务器所对应的主 redis 是192.168.101.3,端口是6379
主机负责写 从机负责读
哨兵模式
自动选举模式
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式
概述
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
这里的哨兵有两个作用
- 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eAM4TRf-1622106198383)(Redis初级.assets/image-20210527135830167.png)]
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel 。
主从服务配置文件
docker拉取的redis跟我们平时自己下载的不一样,没有redis.conf文件,如果需要可以通过官方提供的地址下载默认配置文件
建议把redis.conf文件放置到/etc/redis/
目录下,方便记忆,后续启动容器的时候,该配置文件会与容器内的配置文件进行关联
$ mkdir /etc/redis
$ cd /etc/redis
$ wget http://download.redis.io/redis-stable/redis.conf
主机
# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1
# 关闭保护模式
protected-mode no
# 让redis服务后台运行
daemonize yes
# 设定密码(可选,如果这里开启了密码要求,从机的配置里就要加这个密码. 都是内网的话,不考虑安全性,就不使用密码认证了)
# requirepass password
# 配置日志路径,为了便于排查问题,指定redis的日志文件目录,该目录为容器内的目录
logfile "/var/log/redis.log"
缓存穿透和雪崩
缓存处理流程
前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。
缓存穿透
描述:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
- 布隆过滤器:一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先校验,不符合则丢弃,从而避免了对底层存储系统的查询压力
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),一个key非常热点,在不停的扛大并发,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案
- 设置热点数据永远不过期。
- 加分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
- 设置热点数据永远不过期。
双11防止雪崩方案
1.搭建集群
2.限流降级
,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
- 布隆过滤器:一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先校验,不符合则丢弃,从而避免了对底层存储系统的查询压力
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),一个key非常热点,在不停的扛大并发,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案
- 设置热点数据永远不过期。
- 加分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
- 设置热点数据永远不过期。
双11防止雪崩方案
1.搭建集群
2.限流降级
3.数据预热