万字长文 —— 一文解答你对 Redis 的所有疑惑
序言
Redis 作为目前市面上应用最广泛的 key-value 数据库之一,有着它独一无二的魅力。它可用于缓存,事件发布或订阅,高速队列等场景。该数据库使用 ANSI C 语言编写,支持网络,提供字符串,哈希,列表,队列,集合结构直接存取,基于内存,可持久化。同时丰富的 API 支持广泛的客户端语言。希望兄弟们看完这篇文章可以对 Redis 有一个更深的认识。
PS:标题纯粹在吹牛逼,勿怪勿怪🌚🌚🌚
前置知识
- 在操作系统中,系统从磁盘中读取一次数据是按照 4k 大小进行读取的。
- 在各类数据库软件中也是按照 4k 大小进行数据分片的。
- 使用 Redis 的原因是为了解决在高并发下磁盘 I/O 速度不够的问题。
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 基本类型及使用
- String
- 字符类型
- 数值类型
- bitmaps
- Hashes
- Lists
- Sets
- Sorted Sets
String 类型
type key: 获取 key 指定的 value 值类型
object encoding k1: 获取 key 指定的 value 的编码类型
二进制安全是指 redis 中存的 value 是字节数组,不用担心客户端的编码问题。
为了解决每次命令出现的判断 value 数据类型的操作,redis 在key上标注了 encoding 属性来解决
-
字符类型
- 设置值
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
- nx:只 key 不存在时设置;xx:只 key 存在时设置
- 同时设置多个值
MSET key value [key value ...]
- 获取值
GET key
- 同时获取多个值
MGET key [key ...]
- 字符串追加
APPEND key value
- 获取字符串某一部分
GETRANGE key start end
(索引从0开始,前后包含)- 正反向索引
- 覆盖字符串的某一部分
SETRANGE key offset value
- 获取字符串长度
STRLEN key
- 设置值
-
数值类型
- 指定 key 加一
INCR key
- 指定 key 加某一个数
INCRBY key increment
- 指定 key 减一
DECR key
- 指定 key 减某一个数
DECRBY key decrement
- 指定 key 加一个小数
INCRBYFLOAT key incrementc
- 指定 key 加一
-
bitmap
-
设置指定 key 值的指定偏移量的二进制值
SETBIT key offset value
-
查找指定 key 值的指定字节区间内第一次出现的指定二进制值
BITPOS key bit [start] [end]
-
统计指定 key 值得指定字节区间二进制 1 的个数
BITCOUNT key [start end]
-
为指定 key 做指定的二进制操作,同时把值赋给 destkey
BITOP operation destkey key [key ...]
bitmap 应用:
-
有一个用户系统,统计用户登录天数,且天数随机
- 设置 366 个二进制位
- setbit 用户名 1 1(代表用户名代表的用户第二天登录)
- bitcount 用户名 0 -1(随机天数,一个字节代表8天)
-
商城 6.18 做活动:凡用户登录就送一份礼物。需要知道备货多少礼物(商城有 2亿 用户)
用户有僵尸用户、冷热用户、忠诚用户
所以具体做的是活跃用户统计:随机天数内的活跃用户
如统计 1-3号的活跃用户,分别算出1-3号每天的用户数,连续登陆需去重
- 对每天设置 key 值 bitset 20200908 1[用户id对应1] 1
- 将对应的二进制位对应到用户id bitset 20200910 9[用户id对应9] 1
- 将指定区间内的所有 key 值做或运算 bitop resultKey 20200908 20200910
- bitcount resultKey 0 -1 获取结果 key 中所有二进制 1 的个数
-
-
List 类型
使用同向命令 list可以看作为栈的使用,使用反向命令 list可以看作为队列的使用
有序(指元素的输入顺序)
- 从左到右向指定 key 中加入元素
LPUSH key value [value …]
- 最终结果为加入顺序的倒序
- 从右到左向指定 key 中加入元素
RPUSH key value [value ...]
- 最终结果和加入顺序相同
- 移除并且返回 key 对应的 list 的第一个元素
LPOP key
- 移除并返回存于 key 的 list 的最后一个元素
RPOP key
- 返回存储在 key 的列表里指定范围内的元素
LRANGE key start stop
(包含 stop 对应的那个元素) - 返回存储在 key 列表里的元素的索引 index 对应的值
LINDEX key index
- 设置对应 key index 位置的 list 元素的值为 value
LSET key index value
- 从存于 key 的列表里移除前 count 次出现的值为 value 的元素
LREM key count value
- count > 0: 从头往尾移除值为 value 的元素。
- count < 0: 从尾往头移除值为 value 的元素。
- count = 0: 移除所有值为 value 的元素。
- 把 value 插入存于 key 的列表中在基准值 pivot 的前面或后面
LINSERT key BEFORE|AFTER pivot value
- 其中 pivot 为列表中的元素,如果 有两个基准值则从左到右第一个基准值上操作
- 修剪(trim)一个已存在的 list,这样 list 就会只包含指定范围的指定元素
LTRIM key start stop
- 例如:
LTRIM foobar 0 2
将会对存储在 foobar 的列表进行修剪,只保留列表里的前3个元素。
- 例如:
- BLPOP 是阻塞式列表的弹出原语,即为 LPOP 的阻塞版
BLPOP key [key ...] timeout
- timeout 参数表示的是一个指定阻塞的最大秒数的整型值。当 timeout 为 0 是表示阻塞时间无限制
- BRPOP 是一个阻塞的列表弹出原语,即为 RPOP 的阻塞版 BLPOP 和 BRPOP 会返回 key 和 弹出的元素值
Hashes 类型
- 设置 key 指定的哈希集中指定字段的值
HSET key field value
- 设置 key 指定的哈希集中指定字段的值
HMSET key field value [field value ...]
- 该命令将重写所有在哈希集中存在的字段
- 返回 key 指定的哈希集中该字段所关联的值
HGET key field
- 返回 key 指定的哈希集中指定字段的值
HMGET key field [field ...]
- 返回 key 指定的哈希集中所有字段的名字
HKEYS key
- 返回 key 指定的哈希集中所有字段的值
HVALS key
- 返回 key 指定的哈希集中所有的字段和值
HGETALL key
- 为指定 key 的 hash 的 field 字段值执行 float 类型的加 increment
HINCRBYFLOAT key field increment
Sets 类型
无序但去重
-
添加一个或多个指定的 member 元素到集合的 key中
SADD key member [member ...]
-
返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member
- 如果 member 元素是集合key的成员,则返回1
- 如果 member 元素不是key的成员,或者集合key不存在,则返回0
-
在key集合中移除指定的元素
SREM key member [member ...]
-
返回集合存储的 key 的基数 (集合元素的数量)
SCARD key
-
返回 key 集合所有的元素
SMEMBERS key
-
返回指定所有的集合的成员的交集
SINTER key [key ...]
-
例如:
key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SINTER key1 key2 key3 = {c} 复制代码
-
-
这个命令与 SINTER 命令类似, 但是它并不是直接返回结果集,而是将结果保存在 destination集合中
SINTERSTORE destination key [key ...]
- 如果 destination 集合存在, 则会被重写
-
返回给定的多个集合的并集中的所有成员
SUNION key [key ...]
-
该命令作用类似 SUNION 命令,不同的是它并不返回结果集,而是将结果存储在destination集合中
SUNIONSTORE destination key [key ...]
- 如果 destination 已经存在,则将其覆盖
-
返回一个集合与给定集合的差集的元素
SDIFF key [key ...]
-
举例:
key1 = {a,b,c,d} key2 = {c} key3 = {a,c,e} SDIFF key1 key2 key3 = {b,d} 复制代码
-
-
该命令类似 SDIFF , 不同之处在于该命令不返回结果集,而是将结果存放在 destination 集合中
SDIFFSTORE destination key [key ...]
- 如果 destination 已经存在, 则将其覆盖重写
-
仅提供 key 参数,那么随机返回 key 集合中的一个元素
SRANDMEMBER key [count]
- 如果 count 是正整数,则取出一个去重的结果集(不会超过已有集合的总数)
- 如果 count 是负整数,则取出一个带重复的结果集,(一定满足 count 的绝对值个数)
- 如果 count 是 0,不返回
-
从存储在 key 的集合中移除并返回一个或多个随机元素
SPOP key [count]
- 如果 count 大于集合内部的元素数量,此命令将会返回整个集合,不会有额外的元素
Sorted Sets类型
排序是如何实现的?
SkipList
- 原理及实现
其实跳表就是在普通单向链表的基础上增加了一些索引,而且这些索引是分层的,从而可以快速地查的到数据。如下是一个典型的跳表:
- 查找
查找示意图如下:
比如我们要查找 key 为19的结点,那么我们不需要逐个遍历,而是按照如下步骤:
- 从 header 出发,从高到低的 level 进行查找,先索引到9这个结点,发现9 < 19,继续查找(然后在 level == 2 这层),查找到21这个节点,由于21 > 19, 所以结点不往前走,而是level由2降低到1
- 然后索引到17这个节点,由于17 < 19, 所以继续往后,索引到21这个结点,发现21>19, 所以level由1降低到0
- 在结点17上,level==0 索引到19,查找完毕。
- 如果在 level==0 这层没有查找到,那么说明不存在 key 为19的节点,查找失败
-
将所有指定成员添加到键为 key 有序集合(sorted set)里面。 添加时可以指定多个分数/成员(score/member)对
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
- 如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置
- XX: 仅仅更新存在的成员,不添加新成员。
- NX: 不更新存在的成员。只添加新成员。
- CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内。注:在通常情况下,
ZADD
返回值只计算新添加成员的数量。 - INCR: 当
ZADD
指定这个选项时,成员的操作就等同 ZINCRBY 命令,对成员的分数进行递增操作。
-
返回存储在有序集合 key 中的指定范围的元素。 返回的元素可以认为是按得分从最低到最高排列。 如果得分相同,将按字典排序
ZRANGE key start stop [WITHSCORES]
- WITHSCORES 将元素的分数与元素一起返回
-
返回 key 的有序集合中的分数在 min 和 max 之间的所有元素(包括分数等于max或者min的元素)。元素被认为是从低分到高分排序的
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
-
LIMIT 指定返回结果的数量及区间
-
min 和 max 可以是 -inf 和 +inf,这样一来,可以在不知道有序集的最低和最高 score 值的情况下,使用 ZRANGEBYSCORE 这类命令
-
默认情况下,区间的取值使用闭区间(小于等于或大于等于),可以通过给参数前增加(符号来使用可选的开区间(小于或大于)
-
举个例子:
返回所有符合条件1 < score <= 5的成员;
ZRANGEBYSCORE zset (1 5 复制代码
返回所有符合条件5 < score < 10 的成员
ZRANGEBYSCORE zset (5 (10 复制代码
-
-
-
返回有序集 key 中,指定区间内的成员。其中成员的位置按score值递减(从大到小)来排列
ZREVRANGE key start stop [WITHSCORES]
- 具有相同 score 值的成员按字典序的反序排列
-
返回有序集合中指定分数区间内的成员,分数由高到低排序
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
-
返回有序集 key 中,成员 member 的 score 值
ZSCORE key member
- 如果 member 元素不是有序集 key 的成员,或 key 不存在,返回nil
-
返回有序集 key 中成员 member 的排名
ZRANK key member
- 其中有序集成员按 score 值递增(从小到大)
-
返回有序集 key 中成员 member 的排名
ZREVRANK key member
- 其中有序集成员按 score 值从大到小排列
-
为有序集 key 的成员 member 的 score 值加上增量 increment
ZINCRBY key increment member
- 如果 key 中不存在 member,就在 key 中添加一个 member,score 是 increment。如果 key 不存在,就创建一个只含有指定 member 成员的有序集合
-
计算给定的 numkeys 个有序集合的并集,并且把结果放到 destination 中
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [SUM|MIN|MAX]
- WEIGHTS 选项:为每个给定的有序集指定一个乘法因子,意思就是,每个给定有序集的所有成员的 score 值在传递给聚合函数之前都要先乘以该因子。如果 WEIGHTS 没有给定,默认就是1
- AGGREGATE 选项:指定并集的结果集的聚合方式,默认使用的参数 SUM,可以将所有集合中某个成员的 score 值之和作为结果集中该成员的 score 值。如果使用参数 MIN 或者 MAX,结果集就是所有集合中元素最小或最大的元素。
Redis 进阶使用
管道(Pipelining)
-
简介:
Redis 管道(Pipelining)
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
-
使用:
echo -e "set k2 99\nincr k2\nget k2" |nc localhost 6379
# nc 命令可以开启一个 socket 链接,后面接 ip 地址及端口号
# echo 命令将输入字符串以管道的方式传递给 redis# 在 redis 2.6 以后,redis-cli 开始支持一种新的被称之为 pipe mode 的新模式用于大量数据插入工作。
cat data.txt | redis-cli --pipe# 这将产生类似如下的输出:
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000
复制代码
-
pipe mode的工作原理是什么?
难点是保证redis-cli在pipe mode模式下执行和netcat一样快的同时,如何能理解服务器发送的最后一个回复。
这是通过以下方式获得:
redis-cli –pipe
试着尽可能快的发送数据到服务器。- 读取数据的同时,解析它。
- 一旦没有更多的数据输入,它就会发送一个特殊的
ECHO
命令,后面跟着 20 个随机的字符。我们相信可以通过匹配回复相同的 20 个字符是同一个命令的行为。- 一旦这个特殊命令发出,收到的答复就开始匹配这 20 个字符,当匹配时,就可以成功退出了。
同时,在分析回复的时候,我们会采用计数器的方法计数,以便在最后能够告诉我们大量插入数据的数据量。
重要说明:使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理,例如 10k 的命令,读回复,然后再发送另一个 10k 的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容。
Redis 的发布/订阅 (Pub/Sub)
-
文档:redis.cn/topics/pubs…
-
简介:
订阅,取消订阅和发布实现了发布/订阅消息范式(引自wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者)。而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑。
-
相关命令:
- 将信息 message 发送到指定的频道 channel
PUBLISH channel message
- 订阅给指定频道的信息
SUBSCRIBE channel [channel ...]
- 一旦客户端进入订阅状态,客户端就只可接受订阅相关的命令
SUBSCRIBE
、PSUBSCRIBE
、UNSUBSCRIBE
和PUNSUBSCRIBE
除了这些命令,其他命令一律失效
- 一旦客户端进入订阅状态,客户端就只可接受订阅相关的命令
- 将信息 message 发送到指定的频道 channel
注意事项
- Redis 中发布者发送的消息会通知所有订阅了这个频道订阅者
- 没有订阅者的情况,发布者发布的消息会丢失
Redis 事务
-
相关命令:
- 标记一个事务块的开始。 随后的指令将在执行 EXEC 时作为一个原子执行
MULTI
- 执行事务中所有在排队等待的指令并将链接状态恢复到正常 当使用 WATCH 时,只有当被监视的键没有被修改,且允许检查设定机制时,EXEC会被执行
EXEC
- 标记所有指定的key 被监视起来,在事务中有条件的执行(乐观锁)
WATCH key [key ...]
- 刷新一个事务中已被监视的所有 key
UNWATCH
- 如果执行 EXEC 或者 DISCARD, 则不需要手动执行 UNWATCH
- 刷新一个事务中所有在排队等待的指令,并且将连接状态恢复到正常
DISCARD
- 如果已使用 WATCH,DISCARD 将释放所有被 WATCH 的 key
- 标记一个事务块的开始。 随后的指令将在执行 EXEC 时作为一个原子执行
Redis Modules(Redis 模块)
-
RedisBloom (Redis 布隆过滤器)
-
相关链接:zhuanlan.zhihu.com/p/43263751
-
简介:
本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 某样东西一定不存在或者可能存在。相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。
-
实现原理
- 准备一个 bitmap
- 当一个元素被访问时,会将这个元素经过 x 个映射函数映射到 bitmap 中 x 个二进制位上。
- 当下次该元素被访问时,即可通过相同的 映射函数检查在 bitmap 中对应的二进制位是否为 1 来判断该元素是否存在
-
注意事项
-
当元素被访问时对应的二进制位都为 1 不能证明该元素一定存在,只能说是可能存在,具体原因是因为不同的元素可能在映射函数映射后映射至相同的二进制位上。并且随着元素量增多的时,被置为 1 的二进制位会越来越多。
-
如何选择哈希函数个数和布隆过滤器长度?
如何选择适合业务的 k 和 m 值呢,这里直接贴一个公式:
-
-
Redis LRU算法
- 什么是 LRU 算法
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”
-
相关配置
-
maxmemory
在 redis.conf 中 maxmemory 配置指令用于配置Redis存储数据时指定限制的内存大小。设置maxmemory为0代表没有内存限制。对于64位的系统这是个默认值,对于32位的系统默认内存限制为3GB。
当指定的内存限制大小达到时,需要选择不同的行为,也就是策略。 Redis可以仅仅对命令返回错误,这将使得内存被使用得更多,或者回收一些旧的数据来使得添加数据时可以避免内存限制。
-
maxmemory-policy
配置 redis 的过期策略。
-
-
回收策略
过期集合:即设置了 key 过期时间的键值对
LFU全称是最不经常使用算法(Least Frequently Used)
LRU算法全称是最近最少使用算法(Least Recently Use)
- noeviction: 返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
- allkeys-lru: 尝试回收最近最少使用的键(LRU),使得新添加的数据有空间存放。
- volatile-lru: 尝试回收最近最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-lfu: 尝试回收最少使用的键(LFU),使得新添加的数据有空间存放。
- volatile-lfu:尝试回收最少使用的键(LFU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
-
Redis 如何淘汰过期的 keys
Redis keys 过期有两种方式:被动和主动方式。
-
当一些客户端尝试访问它时,key 会被发现并主动的过期。
当然,这样是不够的,因为有些过期的 keys,永远不会访问他们。 无论如何,这些 keys 应该过期,所以定时随机测试设置 keys 的过期时间。所有这些过期的 keys 将会从密钥空间删除。
具体就是 Redis 每秒 10 次做的事情:
测试随机的 20 个 keys 进行相关过期检测。 删除所有已经过期的 keys。 如果有多于 25% 的 keys 过期,重复步奏1. 这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的 keys 的百分百低于 25%,这意味着,在任何给定的时刻,最多会清除 1/4 的过期 keys。
-
Redis 持久化
Redis 提供了不同级别的持久化方式:
- RDB 持久化方式能够在指定的时间间隔能对你的数据进行快照存储。
- AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF 命令以 redis 协议追加保存每次写的操作到文件末尾。 Redis 还能对 AOF 文件进行后台重写,使得 AOF 文件的体积不至于过大。
- 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。
- 你也可以同时开启两种持久化方式,在这种情况下,当 redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF文件保存的数据集要比 RDB 文件保存的数据集要完整。
RDB 方式
-
RDB的优点:
- RDB 是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。
- RDB 是一个紧凑的单一文件,很方便传送到另一个远端数据中心,非常适用于灾难恢复。
- RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 redis 的性能。
- 与 AOF 相比,在恢复大的数据集的时候,RDB 方式会更快一些.
fork
linux 中的
fork
指令可以很快速的创建子进程,在调用fork
命令时,linux 系统会将父进程中的环境变量使用指针的方式传递给子进程。在 linux 系统中不同进程的数据是相互隔离的,在父进程使用export
命令将环境变量继承给子进程,但在子进程中的修改变量值仍不会破坏父进程中的变量值。所以通过fork
命令来创建子进程的速度是非常快的。copy on write
在使用
fork
命令时会采用copy on write
(写时复制)的方式来修改子进程的数据。 即在子进程不修改变量值时,变量的指针是指向与父进程在内存中相同的指针,在子进程修改时,会先在内存中创建一个新值再将指针指向新值。 -
RDB的缺点:
- 如果你希望在 redis 意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么 RDB 不适合你。虽然你可以配置不同的 save 时间点(例如每隔5分钟并且对数据集有100个写的操作),但是 Redis 要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在 Redis 意外宕机,你可能会丢失几分钟的数据。
- RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大的时候,fork 的过程是非常耗时的,可能会导致 Redis 在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU 性能不是很好的情况下,这种情况会持续1秒,AOF 也需要 fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。
-
RDB配置方式:
-
save <seconds> <changes>
指定时间间隔后,如果数据变化达到指定次数,则导出生成快照文件。如果指定 save "",则相当于清除前面指定的所有 save 设置
save 900 1
900 秒(15 分钟)内至少有1个key被修改save 300 10
300 秒(5分钟)内至少有10个key被修改save 60 10000
60 秒(1分钟)内至少有10000个key被修改
-
rdbcompression yes
RDB 快照中字符串值是否压缩 -
rdbchecksum yes
如果开启,校验和会被放在文件尾部。这将使快照数据更可靠,但会在快照生成与加载时降低大约 10% 的性能,追求高性能时可关闭该功能 -
dbfilename dump.rdb
指定保存快照文件的名称 -
dir /var/lib/redis/6379
指定保存快照文件的目录,AOF(Append Only File) 文件也会生成到该目录
-
-
RDB相关命令:
BGSAVE
后台保存DB。会立即返回 OK 状态码。 Redis forks,父进程继续提供服务以供客户端调用,子进程将 DB l数据保存到磁盘然后退出。如果操作成功,可以通过客户端命令LASTSAVE
来检查操作结果。
AOF 方式
-
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 文件的体积。
- 在 Redis 4.0 之前使用 AOF 方式会使用重写的方式来进行删除抵消命令,合并重复命令、在 Redis 4.0 以后会使用 RDB 和 AOF 合并的方式来缩小 AOF 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
-
AOF配置方式:
-
appendonly no
可以同时启用AOF和RDB持久性而不会出现问题。 如果在启动时检查到启用了 AOF,Redis 将优先加载 AOF。 -
appendfilename "appendonly.aof"
AOF持久化文件名称默认为 appendonly.aof -
appendfsync everysec
fsync() 调用会告诉操作系统将缓冲区的数据同步到磁盘,可取三种值:always、everysec 和 no。在操作系统中向磁盘中写入数据时,会先向缓冲区中写入数据,缓冲区满时操作系统内核会将缓冲区中的数据写入磁盘中以此来加速写入磁盘的数据。对应到代码中的命令就是 flush。
所以以下三种方式对应的就是,always: 每次写入立刻 flush、everysec: 每秒 flush 一次、no: 操作系统自动 flush
- always:实时会极大消弱Redis的性能,因为这种模式下每次 write 后都会调用 fsync。
- no:write 后不会有 fsync 调用,由操作系统自动调度刷磁盘,性能是最好的。
- everysec:每秒调用一次fsync(默认)
-
auto-aof-rewrite-percentage 100
当 AOF 增长超过指定比例时,重写 AOF 文件,设置为 0 表示不自动重写 AOF 文件,重写是为了使 aof 体积保持最小,而确保保存最完整的数据。 -
auto-aof-rewrite-min-size 64mb
触发 aof rewrite的最小文件大小,这里表示,文件大小最小 64mb 才会触发重写机制 -
no-appendfsync-on-rewrite no
在 AOF 文件 rewrite 期间,是否对 aof 新记录的 append 暂缓使用文件同步策略,主要考虑磁盘 IO 开支和请求阻塞时间。默认为 no,表示"不暂缓”,新的 aof 记录仍然会被立即同步。 -
aof-use-rdb-preamble yes
开启混合持久化。
-
-
AOF相关命令:
BGREWRITEAOF
异步执行一个 AOF(AppendOnly File)文件重写操作。重写会创建一个当前AOF文件的体积优化版本。- 如果一个子 Redis 是通过磁盘快照创建的,AOF 重写将会在 RDB 终止后才开始保存。这种情况下
BGREWRITEAOF
仍然会返回 OK 状态码。从 Redis 2.6 起你可以通过 INFO 命令查看 AOF 重写执行情况。 - 如果在执行的 AOF 重写返回一个错误,AOF 重写将会在稍后一点的时间重新调用。
- 如果一个子 Redis 是通过磁盘快照创建的,AOF 重写将会在 RDB 终止后才开始保存。这种情况下
-
AOF文件详解:
*2 // 代表 Redis 命令由几段组成 $6 // 代表 Redis 命令由几个字符组成 SELECT $1 0 *3 $3 set $2 k1 $5 hello 复制代码
*[num]
代表 Redis 命令由几段组成,即接下来的 num*2 行为命令的组成$[num]
代表 Redis 命令由几个字符组成,即接下来的一行的 num 字符为命令- 其余为命令本身
Redis 集群
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis 集群并不支持处理多个 keys 的命令,因为这需要在不同的节点间移动数据,从而达不到像 Redis 所需要的那样的性能,在高负载的情况下可能会导致不可预料的错误。
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。
Redis 集群的优势:
- 自动分割数据到不同的节点上。
- 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
Redis 的 CAP 保证
- 在 redis 中并没有保证数据的强一致性,既在 redis 中满足了 CAP 理论中的 AP。这意味着在实际过程中 redis 集群在特定情况下可能会丢失写操作。
- 其主要原因是在 redis 的集群方式中采用数据异步复制的方式。写操作过程:
- 客户端向主节点 A 写入一条命令
- 主节点 A 向客户端回复命令状态
- 主节点将写操作复制给他的从节点 A1、A2、A3
- 其主要原因是在 redis 的集群方式中采用数据异步复制的方式。写操作过程:
- 在监控某一个 redis 服务中,为确保高可用及避免网络分区的问题导致出现脑裂问题。redis 采用了 (n/2)+1(n/2) + 1(n/2)+1 的方式来确定集群的势力范围。
Redis 的主从复制
*Redis使用默认的异步复制,其特点是低延迟和高性能*
Redis 主从复制的三个主要机制
- 当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave ,包括客户端的写入、key 的过期或被逐出等等。
- 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
- 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。
Redis 主从复制要点
- Redis 使用异步复制,slave 和 master 之间异步地确认处理的数据量
- 一个 master 可以拥有多个 slave
- slave 可以接受其他 slave 的连接。除了多个 slave 可以连接到同一个 master 之外, slave 之间也可以像层叠状的结构(cascading-like structure)连接到其他 slave 。自 Redis 4.0 起,所有的 sub-slave 将会从 master 收到完全一样的复制流。
- Redis 复制在 master 侧是非阻塞的。这意味着 master 在一个或多个 slave 进行初次同步或者是部分重同步时,可以继续处理查询请求。
- 复制在 slave 侧大部分也是非阻塞的。当 slave 进行初次同步时,它可以使用旧数据集处理查询请求,前提是你在 redis.conf 中配置了让 Redis 这样做的话。否则,你可以配置如果复制流断开, Redis slave 会返回一个 error 给客户端。但是,在初次同步之后,旧数据集必须被删除,同时加载新的数据集。 slave 在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自 Redis 4.0 开始,可以配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞 slave 。
- 复制既可以被用在可伸缩性,以便只读查询可以有多个 slave 进行(例如 O(N) 复杂度的慢操作可以被下放到 slave ),或者仅用于数据安全。
- 可以使用复制来避免 master 将全部数据集写入磁盘造成的开销:一种典型的技术是配置你的 master 节点的 Redis.conf 以避免对磁盘进行持久化,然后连接一个 slave ,其配置为不定期保存或是启用 AOF。但是,这个设置必须小心处理,因为重新启动的 master 程序将从一个空数据集开始:如果一个 slave 试图与它同步,那么这个 slave 也会被清空。
全量复制的工作流程:
- master 节点 fork 一个子进程用来生成一个 RDB 文件。同时缓冲新到来的写入命令。
- 当 RDB 保存完成时,master 将文件发送给 slave,slave 保存在磁盘上再加载文件至内存。
- master 发送所有缓冲指令到 slave,同步新到来的命令。
Redis 主从复制的配置
replicaof <masterip> <masterport>
主从复制。 使 Redis 实例成为另一台 Redis 服务器的副本。masterauth <master-password>
如果主服务器受密码保护,则可以在启动复制同步过程之前告知副本服务器进行身份验证,否则主服务器将拒绝副本服务器请求。replica-serve-stale-data yes
当从库与主库连接中断,或者主从同步正在进行时,如果有客户端向从库读取数据:- yes: 从库答复现有数据,可能是旧数据(初始从未修改的值则为空值)
- no: 从库报错“正在从主库同步”
replica-read-only yes
从库只允许读取repl-diskless-sync no
无磁盘形式:主库创建子进程,子进程把 RDB 文件直接写入从库的 SOCKET 连接。repl-backlog-size 1mb
设置复制积压大小(backlog)。 积压是一个缓冲区,当副本断开连接一段时间后会累积副本数据,因此当副本想要再次重新连接时,通常不需要完全重新同步,只需要部分重新同步就足够了- 复制 backlog 越大,副本可以断开连接的时间越长。
- 如果可用连接的副本数少于 N 个,并且延迟小于或等于 M 秒,则 master 节点停止接受写入。以秒为单位的延迟(必须<=指定值)是根据从副本接收的最后一次 ping 计算的,通常每秒发送一次。
- 例如,要求至少3个在线且滞后时间<= 10秒的副本:
min-replicas-to-write 3
min-replicas-max-lag 10
- 例如,要求至少3个在线且滞后时间<= 10秒的副本:
配置 Redis 的 Sentinel 系统
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
-
配置 Sentinel
# sentinel.confsentinel monitor mymaster 127.0.0.1 6379 2 # 配置 sentinel 监听一个名为 mymaster 的 redis 主服务器,而将这个主服务器判断失效至少需要两个 sentinel 同意(势力范围为 2) sentinel down-after-milliseconds mymaster 60000 # 指定了 Sentinel 认为服务器已经断线所需的毫秒数 sentinel parallel-syncs mymaster 1 # 在故障转移期间,多少个副本节点进行数据同步 复制代码
搭建 Redis 集群
-
配置项:
cluster-enabled yes
开启集群功能,此redis实例作为集群的一个节点cluster-config-file nodes.conf
集群配置文件此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。通常是在收到请求之后这个文件就会被更新cluster-node-timeout 5000
集群中的节点能够失联的最大时间,超过这个时间,该节点就会被认为故障。如果主节点超过这个时间还是不可达,则用它的从节点将启动故障迁移,升级成主节点appendonly yes
-
Redis 集群的数据分片
Redis 集群方案没有使用一次性 hash,而是引入了哈希槽的概念。在 Redis 中有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定当前 key 具体要放置在哪个槽位。集群的每一个节点都复制一部分的槽位。举个例子:假设当前集群有 3 个节点,那么
- 节点 A 包含 0 到 5500 号哈希槽
- 节点 B 包含5501 到 11000 号哈希槽
- 节点 C 包含11001 到 16384号哈希槽
这种结构的优点是很容易添加或删除节点,比如要添加一个节点 D 时,只需从节点 A、B、C 中的部分槽分到节点 D 上。如果要移除节点 A,只需将节点 A 中的槽移到 B 和 C节点上。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
-
Redis 集群的实现方案
- TwemProxy
- Predixy
- Redis Cluster
Redis 常见问题
缓存击穿
-
原因:
- 当 Redis 的某一个 key 值是热点数据,不停地扛住大并发的请求,这是当此 key 过期时所带来的持续的大并发请求就会透过这个 key 值打到 DB造成 DB 的宕机。
-
解决方案:
- 设置热点 key 不过期。或者加上互斥锁。
缓存雪崩
-
原因:
- 同一时间缓存大面积失效,就像没有缓存一样,所有的请求直接打到 DB 上来
-
解决方案:
- 批量往 redis 存数据的时候,把每个 key 的失效时间加上个随机数,这样的话就能保证数据不会在同一个时间大面积失效。
缓存穿透
-
原因:
- 用户不断请求的数据在 DB 和 Redis 中都没有,则这类请求会不停地通过 Redis 打到 DB 上造成宕机。因为每次都绕开了缓存直接查询 DB。
-
解决方案:
- 在接口层增加校验,不合法的参数直接返回。
- 若出现在缓存中查不到在 DB 中也查不到的数据则将此条数据对应的 key 值的 value 设置为 null 或是其他特殊值写入缓存。同时将过期时间设置的短一些以免影响正常情况。
- 为避免大量同一 ip 的请求可以在网关中设置 ip 黑名单。
- 使用 Bloom 过滤器防止。原理就是利用高效的数据结构和算法快速判断出你这个 key 是否在 DB 中存在,不存在 return 就好了,存在就查了 DB 刷新 K-V 再 return。
Redis 补充知识
RESP 协议
-
协议特点
- 简单的实现
- 快速地被计算机解析
- 简单得可以能被人工解析
-
应用场景
- 开发定制化的客户端:RESP 设计成简单的文本协议, 一大原因就是为了降低各种语言开发客户端的复杂度
- 理解RESP方便:我们分析 AOF 文件,了解 redis 的内部设计
- 在没有 redis-cli 的情况下, 方便开发调试 redis 命令
-
数据类型
-
simple string 简单的字符串
- 第一个字节是
+
中间是字符串的的内容,最后以 CRLF (\r\n) 结尾。例如"+OK\r\n"
- 第一个字节是
-
error 表示一个错误异常
- 第一个字节是
-
后面接着的是错误的信息,最后以 CRLF(\r\n) 结尾。例如"-ERR unknown command 'foobar'\r\n"
- 第一个字节是
-
integer 表示一个整数
- 第一个字节是
:
后面是整数,最后以 CRLF(\r\n) 结尾。例如":1000\r\n"
- 第一个字节是
-
bulk string 表示一个长字符串但必须小于 512M
- 第一个字节是
$
紧接着是一个整数,表示字符串的字节数,字节数后面接一个 CRLF。CRLF 后面是字符串的内容,最后以 CRLF(\r\n) 结尾。例如"$0\r\n”
$ 后面的 0 表示这是一个空字符串"$-1\r\n"
$后面的-1表示这是一个 null 字符串,Null Bulk String 要求客户端返回空对象,而不能简单地返回个空字符串"$6\r\nABCDEF\r\n”
ABCDEF 是 6 个字节,所以 $ 后面是6
- 第一个字节是
-
arrays 表示一个数组
-
第一个字节是
*
紧接着后面是一个数字,表示这个数组的长度,数字后面是一个 CRLF。需要注意的是这个 CRLF 之后才是数组的真正内容,而且数组内容可以是任意类型,包括 arrays 和 bulk string,每个元素也要以 CRLF 结尾. 最后以 CRLF(\r\n) 结尾-
"*0\r\n”
后面的 0 表示表示空的数组 -
"*-1\r\n"
*后面的 -1 表示表示是 null 数组 -
"*5\r\n
*5 表示这是一个拥有 5 个元素的数组+bar\r\n
第1个元素是简单的字符串-unknown command\r\n
第 2 个元素是个异常:3\r\n
第 3 个元素是个整数$3\r\n
第 4 个元素是长度为 3 个字节的长字符串 foofoo\r\n
第4个元素的内容*2\r\n
第 5 个元素又是个数组:1\r\n
第 5 个元素数组的第 1 元素:2\r\n
第 5 个元素数组的第 2 元素\r\n
第 5 个元素数组的结束\r\n
数组结束
-
-
-
使用 Redis 实现分布式锁
分布式锁在很多场景中是非常有用的原语, 不同的进程必须以独占资源的方式实现资源共享就是一个典型的例子。
有很多分布式锁的库和描述怎么实现分布式锁管理器(DLM) 的博客,但是每个库的实现方式都不太一样,很多库的实现方式为了简单降低了可靠性,而有的使用了稍微复杂的设计。
Redis 提出了一种算法叫RedisLock,认为这种实现比普通的但实例更安全
-
实现细节:
- Redisson (Java 版)
- Redlock-py (Python 版)
- Redsync.go (Go 版)
Redis Lua 脚本
-
相关命令
-
EVAL script numkeys key [key ...] arg [arg ...]
-
EVAL的第一个参数是一段 Lua 5.1 脚本程序。 这段Lua脚本不需要(也不应该)定义函数。它运行在 Redis 服务器中。
-
EVAL的第二个参数是参数的个数。
-
EVAL的第三个参数表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
-
EVAL的第四个参数那些不是键名参数的附加参数 arg [arg …] ,可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
-
举例:
> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second" 复制代码
-
-
-
参考引用
-
redis 中文官网
-
SkipList的原理与实现
-
Redis 5.0.5 redis.conf 配置文件说明
-
sentinel.conf 配置文件说明
-
redis通讯协议(RESP )是什么
-
Redis缓存的雪崩,穿透,击穿总结
总结
总的来说 Redis 涉及到的知识非常复杂,不仅有基本的数据类型,磁盘I/O 和 内存的地址都有涉猎到,正是因为这些细节的把控,才让 Redis 成为目前市面上最快的 key-value 数据库,也可以发现在 Redis 的设计理念里所有的行为都是为了让 Redis 更快。
如果我在哪一部分写的不够到位或者写错了,还请在座的各位大佬提出意见。
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- Ceph剖析:Leader选举
Ceph剖析:Leader选举 Paxos算法存在活锁问题。从节点中选出Leader,然后将所有对数据的修改都通过Leader作为提案提出,可以让算法快速收敛。Leader的选举规则是,由当前活动的Monitor节点中rank值最小的节点当选。选举不仅会产生Le…...
2024/4/9 22:07:05 - LeakCanary源码分析以及ContentProvider的优化方案
1.使用 LeakCancary 2.0使用,只需要配置如下代码,便可以进行使用,比LeakCanary1.0不知道高到哪里去了~ debugImplementation com.squareup.leakcanary:leakcanary-android:2.0-alpha-22.源码分析 阅读源码后可以看到leakcancary-leaksentr…...
2024/4/14 2:32:03 - OpenCV3.4.1+Contrib+Cuda+VS2015+Win10 编译
网上已经有很多关于OpenCV的编译了 ,官网上直接exe下载安装的OpenCV包从3.0版本之后就不含Contrib了,基本使用是够的,但是很多时候我们需要使用GPU编程,并且期望使用一些SIFT等这些包含在Contrib中的库,我自己配置成功…...
2024/4/17 17:25:26 - 开机播放音乐,解锁后音乐暂停
安卓小程序需求步骤代码展示需求 开机播放音乐,解锁后音乐暂停 步骤 1.监听开机广播 2.开启服务(因为onReceive方法中不因执行耗时的操作,这些操作基本在服务中进行)3.在服务当中播放音频文件4.监听手机解锁的广播在该广播接收…...
2024/4/27 1:39:17 - 纯干货!北京市工作居住证个人办事指南
个人经验,适合毕业工作两年的朋友进行参考,至于工作居住证的作用什么的,就不废话了,直接上干货 准备的材料 (1)学历证书、学位证书、职称证书及身份证原件和复印件; (2)…...
2024/4/25 10:04:55 - 面试阿里P6惨败,室友怒怼:你这就是标准的程序员“垃圾简历”
一石激起千层浪,三天收到两百多封简历。 花光了两个星期的所有空闲时间,一一点评,一一回复,一一讨论与修正。 看光了所有简历以后,能称得上为范本的寥寥无几。 有些同学非常有实力,但看到他的简历时&#…...
2024/4/27 16:10:52 - 面试腾讯,字节跳动首先要掌握的Java多线程,一次帮你全掌握
其实程序是一段静态的代码,它是应用程序执行的脚本。进程就是程序动态的执行过程,它具有动态性,并发性,独立性。线程是进程调度和执行的单位。 进程:每个进程都有独立的代码和数据空间(进程上下文…...
2024/4/23 17:45:59 - windows破解连接过的wife密码
windows破解连接过的wife密码 step 1:打开控制台 step 2:输入命令:netsh wlan show profiles step 3:找到需要查找的网络名称,输入命令:netsh wlan show profiles 【网络名称】 keyclear...
2024/4/24 6:47:39 - 【大数据】Hadoop安装(VMware + 进入BIOS开启Intel VT-x + Ubuntu16.04 + Hadoop2.7.7 + jdk1.8.0)
环境:VMwareUbuntu16.04Hadoop2.7.7jdk1.8.0 1、超稳进入BIOS,开启虚拟技术,Intel VT-x 左下角右键,设置,更新和安全,恢复,立即重新启动。疑难解答,高级选项,UEFI固件设置…...
2024/4/13 20:13:42 - 「Java并发编程」常见基础问题整理
进程和线程? 进程? 进程是程序的一次执行过程,是系统运行程序的基本单位,进程是动态的。系统运行一个程序就是一个进程从创建,运行到消亡的过程。 Java中,启动main函数的时候其实就是启动了一个JVM进程&a…...
2024/4/15 18:07:56 - 【Java并发编程】线程池相关知识点整理
为什么要用线程池? 池化技术:减少每次获取资源的消耗,提高对资源的利用率。 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。 使用线程池的…...
2024/4/17 12:12:31 - Git 将本地项目上传到Github
一、开始二、git add 命令1、详解2、总结三、相关地址一、开始 如图: 步骤: 1、git init (建立本地仓库)2、git add * (将代码添加到本地仓库,《*是添加全部代码,代码全部更新》)3、git commit -m &quo…...
2024/4/23 5:42:24 - 自动化测试工程
我想一个基本的自动化测试工程应该需要包含这些吧,当然不同的项目和不同的人最终出来的东西肯定有差别,我觉得应该大同小异吧 1.测试用例的组织逻辑,其中包括用例组织的存储方式,用例的测试开关,用例的描述,…...
2024/4/21 6:13:11 - layui扩展组件(组合输入框inputTags)
inputTags.js内容(从layui官方网站下载后修改的,主要是将限定id改为class(id在html中是唯一的,当需要在同个html页面多处使用时就不能满足需求)) layui.define([jquery,layer],function(exports){"use strict";var $ layui.jquery,layer layui.layer,/…...
2024/4/27 17:44:29 - PageHelper的基础使用
0.从源码层面上理解PageHelper 简单的点击了一下,觉得挺复杂的,决定把设计模式透析之后,再来分析。PageHelper结合MyBatis进行使用,通过拦截器保证pageNum和pageSize以及total,然后一个 wrapper,还有一个代…...
2024/4/12 6:11:34 - 树莓派编译安装Openssl
wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz tar zxf openssl-1.1.1d.tar.gz cd openssl-1.1.1d ./config --prefix/usr/local/openssl --openssldir/usr/local/openssl make -j4 && make install...
2024/4/24 10:22:58 - 【Window】解决window的bat脚本执行出现中文乱码的问题
中文那么好,你为什么不好好善待她... window下通过新建txt文件然后改成.bat的文件,输入内容后,执行出现中文乱码? 原因: 批处理文件,是以ANSI编码方式。若以别的方式(如UTF-8)编辑…...
2024/4/20 18:02:32 - log4j日志传送至flume至kafka显示输出
妈耶,一个简简单单的功能,废了我大半天功夫,反思了一下原因,1是自己之前学的东西记不清了,各种配置搞的很晕,看了半天,2是网上的教程实在不堪入目,跟着走让人云里雾里,费…...
2024/4/24 21:14:20 - Mac安装nacos
一、前言 初次使用Mac,还不太习惯,但是鉴于朋友们都说mac用久了,你就会鄙视windows了,于是,步入了新系统的开发队伍中,本次安装nacos,特此记录一下; 二、下载 1、下载安装包 nac…...
2024/4/27 0:55:23 - 程序员艰苦奋战三个月后终于成功斩获字节跳动offer[Java研发岗]
前言: 经历不断学习加上总结,终于开始出效果。努力没有白费。 相比来说等offer真煎熬,但是终于还是到了。发完就去搬砖啦,明天还有其他面试呢~ 面的是Java研发实习生... 一、字节跳动技术一面(算法) Java 的 16 进…...
2024/4/20 9:53:02
最新文章
- 『大模型OS笔记』Meta 宣布推出 Llama 3 的介绍视频
Meta 宣布推出 Llama 3 的介绍视频 文章目录 一. Meta 宣布推出 Llama 3 的介绍视频一、引言二、Llama 模型历史回顾三、Llama 3 模型介绍四、Llama 3 背后的开发思路五、许可证和生态系统六、安全和信任七、其他亮点八、未来计划九、现场演示四. 参考文献一. Meta 宣布推出 Ll…...
2024/4/27 21:21:11 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - Nginx配置文件修改结合内网穿透实现公网访问多个本地web站点
文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…...
2024/4/22 22:16:59 - 策略模式图
策略模式 小小的图解 主要的三个角色 Strategy—抽象策略角色ConcreateStrategy—具体策略角色Context—上下文角色 封装了对具体策略的调用可以使用set的依赖注入也可以使用构造方法 核心是上下文角色 只要调用上下文角色就行,实现解耦 策略 工厂 将上下文角…...
2024/4/25 20:06:50 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/4/27 1:53:53 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/4/27 3:39:11 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/4/27 12:24:35 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/4/27 12:24:46 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/4/27 3:39:08 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/4/27 3:39:07 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/4/27 3:39:07 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/4/27 12:44:49 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/4/27 21:08:20 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/4/26 22:35:59 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/4/27 18:40:35 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/4/27 3:39:03 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/4/27 13:52:15 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/4/27 13:38:13 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/4/27 1:03:20 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/4/27 3:22:12 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/4/26 21:29:56 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/4/27 3:39:00 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/4/26 23:53:24 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/4/27 20:28:35 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57