Redis6.2/5.0 集群两种快速搭建方式

2023-11-17

一、集群常识

1.redis在3.0之前是集群,仅支持单实例的,3.0以后开始支持集群。

2.3.0的集群命令也不是那么亲和,需要用ruby编写的脚本(而且需要登录redis客户端操作),启动、增删节点、移动槽位等。redis-5.0以后,可以使用比较亲和的redis-cli --cluster 不需要登录客户端,直接可以进行各种操作(前提:集群模式已开启)。

3.redis集群是没有统一的入口的,不存在中心节点或者代理节点,通过#redis-cli -c - h -p  登录任一客户端后,集群客户端各节点数据可以互通,(默认会开启梦游模式你要的数据,我没有,但是我可以告诉你哪台机器有并且给你跳转到那台机器,并返回你要的数据)。

4.对于事务的支持,仅支持被Hashtag统一前缀{}后的key(这些统一前缀的key会落到同一组主从机器)上的数据,才可以支持事务,如果是普通key散列到不同的主从上是不支持事务的。

5.redis集群为了达到高可用,会考虑到宕机,那么里面有个投票机制,需要一半以上的投票认为某台master宕机了(哨兵也是这个机制),然后推举新的slave为master。2台机器,投票方式只有1:1和0:2(对于过半这条要求,2台有些牵强),所以,集群的搭建至少是3台master。又因为集群要求1个master至少有一个小弟slave,那么一个集群至少需要6台redis实例。

6.Redis 集群引入了槽位的概念,整个集群共有哈希槽位16384个。假如集群中有三对主从,也就是三个节点,称作A节点、B节点、C节点,那么默认槽位是平均分配的。

节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.

槽位的移动,不会造成数据丢失,但是,如果某个节点的主从全部宕机,那么整个节点所对应槽位中的数据将会暂时全部丢失(不可访问),直到节点被恢复正常。

好了,了解了这些知识点后,做到心中不慌,下面跟随我一起愉快的玩耍吧,开启梦游之旅………

意犹未尽,如需了解更多,点击redis英文官网redis中文官网,进入后点击文档进行查看。 

二、准备工作

1.redis的安装部署

点击CentOS7.9+Redis6.2.6CentOS6.5+Redis5.0.4协助部署,这两个版本均可,不影响步骤。

2.从熟悉redis解压目录结构到README

#cd /usr/src/redis-5.0.4/ && ls  进入redis解压目录,并查看目录列表
#cd utils && ls  查看utils下的目录结构
#cd  create-cluster && ls   查看集群命令所在目录的结构

#vim README   学会看这个文件,你就基本学会了走路,它很重要!

 创建步骤:

1.编辑绿色的create-cluster可执行文件,修改里的端口,默认是30000,本案例暂不修改。

2.使用./create-cluster start命令,自动依次启动30001-30006,六个redis实例(默认就好)

3.使用./create-cluster create命令,自动依次创建一个redis集群(把6个实例组合一起)

4.此刻集群已经创建并准备完毕,可以发现rdb和aof文件已经在当前命令执行目录自动创建

关闭步骤:

1. 使用./create-cluster stop命令后,所有实例会自动关闭,如需重启集群,使用./create-cluster start即可 (英文帮助信息也挺苦口婆心的,如果你改变主意的话,O(∩_∩)O哈哈~

2./create-cluster clean 会自动移除所有的aof日志,返还你一个纯净的运行环境

英文的一看就懵,给你大白话翻译一下,是不是很prefect,还是看不懂,表要紧,go on !

最后意犹未尽,可以返还此处,回味一下哦……

3.跟随README的旨意,看一下create-cluster脚本

#vim create-cluster  查看这个绿色的可执行文件(它也是操作集群的一个命令)

PORT=30000    集群的默认端口,这里可以不用修改
TIMEOUT=2000  超时时间,超时后集群要搞些事情,比如选举新的master
NODES=6  集群最少要求,要配置6个节点(默认即可)
REPLICAS=为集群中的每个主节点创建1个从节点。

在NODES节点是6的前提下:

如果REPLICAS=1 配置为1,意味着一个主只跟1个从(一套主从两台机器),这个集群中会有3套主从。

如果REPLICAS=2 配置为2,意味着一个主只跟2个从(一套主从三台机器),这个集群中会有2套主从。明显,集群不建议这么做,一个集群被要求最少要有3个master。

以上配置文件看一下就可以,学习节点,可以不用修改 

好了,跟随README的旨意,我们继续吧!没想象的那么难 ^_^ 

三、方法一:用集群命令create-cluster create 开启集群(系统自动指定redis实例)

1.启动集群create-cluster start

#pwd  查看当前目录的位置
/usr/src/redis-5.0.4/utils/create-cluster  
#ls
create-cluster  README
#./create-cluster start   使用当前目录的命令,创建并启动集群, 看到6个redis实例跑起来了。
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006
注:start命令作用是,自动创建30001-30006六个redis实例,并自动启动。

  

2.创建集群,并自动分配主从create-cluster create

#./create-cluster create 正式创建集群,中间过程会询问是否同意分配方案,选Y即可。

注:create 命令作用,首先把6台redis实例,这帮散兵游勇集合到一起形成一个集群团伙,内部自动分配master、是slave,以及槽位

特别提示:README里4.指明,create命令被运行后会在当前目录自动生成持久化数据文件,这些文件在实验结束后,可以删除。

3.集群客户端的三种使用方式(错误的、梦游模式、非梦游模式)

Adding replica 127.0.0.1:30005 to 127.0.0.1:30001
Adding replica 127.0.0.1:30006 to 127.0.0.1:30002
Adding replica 127.0.0.1:30004 to 127.0.0.1:30003
上面中是系统自动启动的6个redis server服务,他们的主从关系,前面是从,后面是主。

1.错误方式启动集群客户端redis-cli -p (不会梦游,也不能使用) 

#redis-cli -p 30001           尝试以常规方式启动集群中的第一分组的redis30001 客户端
127.0.0.1:30001> set k1 aaa
(error) MOVED 12706 127.0.0.1:30003            被提示k1b被转移到30003 了
127.0.0.1:30001> get k1           取不到k1,被提示k1被转移到30003
(error) MOVED 12706 127.0.0.1:30003

注:之所以不会自动返回k1,是启动集群的方式不对,需要带-c参数。 

其中的原理具体见:开篇“一、集群常识”的“第3条”,已说明。

  

2.正确方式启动集群客户端redis-cli -c -p (会梦游,难以支持事务)

#redis-cli -p 30001  错误启动集群客户端的方式
127.0.0.1:30001> set k1 aaa
(error) MOVED 12706 127.0.0.1:30003
127.0.0.1:30001> get k1
(error) MOVED 12706 127.0.0.1:30003
127.0.0.1:30001> exit   退出错误的启动方式
# redis-cli -c -p 30001 正确启动集群的方式(带-c,c就是cluster)
127.0.0.1:30001> get k1
-> Redirected to slot [12706] located at 127.0.0.1:30003
(nil)
127.0.0.1:30003> set k2 bbb
-> Redirected to slot [449] located at 127.0.0.1:30001
OK
127.0.0.1:30001> get k2
"bbb"
127.0.0.1:30001> set k3 ccc
OK
127.0.0.1:30001> get k3
"ccc"
127.0.0.1:30001> set k4 ddd
-> Redirected to slot [8455] located at 127.0.0.1:30002
OK
127.0.0.1:30002> get k4
"ddd"

反复设key,为目睹梦游模式芳容,发现集群中的客户端来回跳跃,感觉像是开启了梦游模式。 

3.尝试使用事务watch multi

127.0.0.1:30002> watch k1
-> Redirected to slot [12706] located at 127.0.0.1:30003
OK
127.0.0.1:30003> multi  开启事务
OK
127.0.0.1:30003> get k4
-> Redirected to slot [8455] located at 127.0.0.1:30002
"ddd"
127.0.0.1:30002> set k5 66
-> Redirected to slot [12582] located at 127.0.0.1:30003
OK
127.0.0.1:30003> exec 提交事务
(error) ERR EXEC without MULTI   事务报错了
127.0.0.1:30003> 

事务在梦游中如愿以偿的失败了,究其原因
向集群保存数据时,因为hash算法的原因,后台会把数据保存在不同的主从上,被操作的数据不在同一套主从上,(事务开启在30003上,中间操作的数据在30002或者30001上),就无法保证数据的一致性,所以报错。 

4.用Hashtag{}标签设置key(开启非梦游模式,用来支持事务)

127.0.0.1:30003> set {oo}k1 222
-> Redirected to slot [1629] located at 127.0.0.1:30001
OK
127.0.0.1:30001> set {oo}k2 333  用Hashtag标签,设置一批数据,发现都会落在30001上
OK
127.0.0.1:30001> set {oo}k3 444
OK
127.0.0.1:30001> set {oo}k5 555
OK
127.0.0.1:30001> watch {oo}k1
OK
127.0.0.1:30001> multi  开启事务
OK
127.0.0.1:30001> get {oo}k1
QUEUED
127.0.0.1:30001> set {oo}k1 xxx
QUEUED
127.0.0.1:30001> set {oo}k6 666
QUEUED
127.0.0.1:30001> mget {oo}k1 {oo}k6
QUEUED
127.0.0.1:30001> exec  提交事务
1) "222"
2) OK
3) OK
4) 1) "xxx"
  2) "666"
127.0.0.1:30001>  这次没有报错,原因是数据都在同一套主从上,没有发生梦游模式 

说明:Hash tag标签{},在官网[键哈希标签]一栏有明确说明;另外在predix代理源码目录的/conf/sentinel.conf中也有明确定义(同时也定义了hash算法),如下代码片段所示。

SentinelServerPool {
Databases 16
Hash crc16
HashTag "{}"

小结:
使用Hashtag标签模式时,无论你怎么设值,相同前缀的数据都通过hash算法,命中在一台机器上,便于事务的正常运行。
只要是key 使用标签的前缀是一致的{} 大括号中的内容一致,就不会出现梦游(来回切换不同端口的redis实例)。

结论:集群在Hashtag标签模式的加持下,是支持事务的!  

4.收尾工作,清除实验数据

# pwd
/usr/src/redis-5.0.4/utils/create-cluster  操作前,确保目录位置,还在集群目录下,便于清场
#./create-cluster stop  先关闭前面启动的集群
#./create-cluster clean 清理持久化测试文件

四、方法二:用客户端命令redis-cli --cluster create 开启集群(手动指定redis实例)

1.redis-cli --cluster help查看集群手动创建命令的语法格式

#redis-cli --cluster help  查看帮助命令
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN             手动指定N个IP+端口
                 --cluster-replicas <arg>                      后缀参数replicas ,指明一个主跟几个从
……  

据此帮助得知,如果用这个命令,那么就要准备Host1~HostN,也就是要准备N台redis-server服务,这里我们依然准备6台,端口从7000~7005,同时给各redis-server服务配套自己的redis.conf文件。 

  

2.手动准备6个redis实例的持久化目录和配置文件,并逐一启动

本步骤的操作目的:
创建6个目录用来分别存放6台redis-server启动时用到的conf文件,同时它们也分别作为各redis-server服务的持久化目录。

好处:
1.把测试数据集中存放,便于清理
2.稍后这六台redis-server手动启动后,需要用redis-cli --cluster 命令把6兄弟组成一个集群

1.创建持久化目录

#cd && make -p test/cluster-test  创建持久化目录所在的根目录
#cd && cd test/cluster-test  && mkdir 7000 7001 7002 7003 7004 7005 && ls 创建持久化目录

2.创建redis-server所需要的配置文件

#cd 7000 
#vim 7000.conf  注:这个文件,是redis源码目录下redis.conf的精简版。

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

然后:wq保存并退出即可。
注:nodes.conf,你也可以根据自己的口味命名为nodes_7000.conf,本案例为了方便起见,就不这么配置了。

配置解析:
port 7000 指明,用该配置文件启动的redis-server时,该服务的端口就是配置的7000
cluster-enabled yes 开启集群模式,允许用集群命令(redis-cli --cluster create )拉这台redis-server入伙,默认是no,关闭的
cluster-config-file nodes.conf 集群和该服务之间的配置信息存放位置,不用理会,这个文件集群内部自己管理,自己创建、修改、更新
cluster-node-timeout 5000 该服务和集群失去联系的超时时间,一旦超时5秒,集群将会对该服务采取一些措施
appendonly yes 是否开启AOF,数据操作日志追加,默认是no(仅开启rdb)

附注:redis中文官网文档 (版本有点儿老,是3.0的,需要安装ruby,如果按官网配,后面还会安装一些tar包,中间会多次报错,感兴趣的,可以挑战一下官网步骤

3.分别给其它5个redis-server的conf文件进行修改(仅修改端口就可以)

#cd && test/cluster-test && ls 切回持久化根目录,确保目录位置没弄错,开启一波骚操作
#cp ./7000.conf ./7001/7001.conf 以一步配置的7000.conf为模板,逐个复制配置文件到其它持久化目录
#cp ./7000.conf ./7002/7002.conf
#cp ./7000.conf ./7003/7003.conf
#cp ./7000.conf ./7004/7004.conf
#cp ./7000.conf ./7005/7005.conf

#vim ./7001/7001.conf 把第一行的端口修改为7001后,保存并退出
#vim ./7002/7002.conf 把第一行的端口修改为7002后,保存并退出
#vim ./7003/7003.conf 把第一行的端口修改为7003后,保存并退出
#vim ./7004/7004.conf 把第一行的端口修改为7004后,保存并退出
#vim ./7005/7005.conf 把第一行的端口修改为7005后,保存并退出

最后以7005为例展示一下,每个文件只需要修改端口即可,其它不在一一累述。
port 7005
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

以上步骤简单而繁琐,但是便于理解,如果你比较好学,sed -i 也比较适合你的口味。

#cp 7000.conf  ./7001/7001.conf && sed -i "s/7000/7001/g" ./7001/7001.conf 复制配置文件7000.confg,并修改新文件70001.conf里的端口7000为70001,最后回写到7001.conf

注:-i 表示我要修改文件内容(没有-i修改不会生效);s/替换以某字符开头的文件内容,后面是正则;/g 全部替换(此处写不写都可以) 

4.分别开启新窗口逐个启动redis-server服务

由于操作步骤简单,图片不再一一截取,要注意的是:每个服务都要开启新窗口操作。

新窗口一

#cd && clear && cd test/cluster-test/7000  切换到redis-server 7000的持久化目录
#redis-server 7000.conf  启动7000端口的redis服务(该命令在哪个窗口启动,哪个目录就会被默认认定为其持久化目录,所以上面要切换到7000目录下)

新窗口二

#cd && clear && cd test/cluster-test/7001  切换到redis-server 7001的持久化目录
#redis-server 7001.conf  启动7001端口的redis服务

新窗口二

#cd && clear && cd test/cluster-test/7002  切换到redis-server 7002的持久化目录
#redis-server 7002.conf  启动7002端口的redis服务

新窗口四

#cd && clear && cd test/cluster-test/7002  切换到redis-server 7002的持久化目录
#redis-server 7002.conf  启动7002端口的redis服务

新窗口五

#cd && clear && cd test/cluster-test/7004  切换到redis-server 7004的持久化目录
#redis-server 7004.conf  启动7004端口的redis服务

 新窗口六

#cd && clear && cd test/cluster-test/7005  切换到redis-server 7005的持久化目录
#redis-server 7005.conf  启动7005端口的redis服务

注:
1.这些命令可以写在一个shell中,一次性批量启动,在此不做过多展开。启动图片信息如下,不再一一截取。
2.如果在后续步骤中有误操作,导致实验中断,需回头进入test/cluster-test下的各个目录,把自动生成的文件逐个删除,删除命令如下:
#rm -rf  /root/test/cluster-test/700*/appendonly.aof    
#rm -rf  /root/test/cluster-test/700*/dump.rdb
#rm -rf  /root/test/cluster-test/700*/nodes.conf  

3.根据上述帮助逐个指定服务器的ip、端口,以replicas 数,手动开启集群

redis-cli  --cluster create  127.0.0.1:7000 127.0.0.1:7001  127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1  指定每个master副本数量为1

中间会暂停一下,询问是否同意上述分配方案,输入:yes即可。 

4.手动启动redis客户端(该模式,也会上演梦游,同理使用Hashtag可以避免梦游)

#redis-cli -c -p 7000
127.0.0.1:7000> set k1 111
-> Redirected to slot [12706] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set k2 222
-> Redirected to slot [449] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get k1
-> Redirected to slot [12706] located at 127.0.0.1:7002
"111"
127.0.0.1:7002

此处不重复演示Hashtag的非梦游模式(如有需要查看,请参考上面方法一的最后一步),至此,第二种方法演示完毕,这种更为灵活和常用。 

  

五、槽位转移命令的使用:数据分配不均时,槽位移动

#redis-cli --cluster help  查看reshard槽位操作帮助 
Cluster Manager Commands:
……
  reshard        host:port                  语法格式,后面的是各个需要经过交互的确认步骤
                 --cluster-from <arg>
                 --cluster-to <arg>
                 --cluster-slots <arg>
                 --cluster-yes
                 --cluster-timeout <arg>
                 --cluster-pipeline <arg>
                 --cluster-replace

小提示:下面的步骤非常简单,基本是傻瓜式操作,由于需要展示效果,显得篇幅略长。

1.指定需要操作转移的主机

#redis-cli  --cluster reshard  127.0.0.1:7000 开始运行槽位分配命令

 2.指定要把多少槽位转移走

槽位转移的个数,最好是整十数的倍数,这里定义为2000(可以根据实际情况调整)

3.指定接收槽位的主机的node ID

从上面复制7000端口主机的node ID,把槽位转移给7000

4.需要被转移的2000槽位,由哪些主机提供

Source node #1  提供槽位的node id,这里可以是一台或多台
Source node #2
Source node #3 doneg如果果没有其他主机来贡献槽位了,最后一行就写Done

特别提示一下:这里提供槽位方,必须是master的node id才可以,否则会报如下错误:

5.回车键,确定命令的执行,开始槽位转移

输入:yes    开始执行槽位转移。(一旦输入yes后,开工没有回头箭了,直到执行完毕,并且上面命令,会被大串的日志信息覆盖!!)
注:被移动的2000个槽位,具体是从槽位提供者的哪些槽位,是系统自己决断的,不受人为控制。

6.info命令查看,各节点槽位移动后的变化

#redis-cli --cluster info 127.0.0.1:7000 

 注:#redis-cli --cluster check 127.0.0.1:7000 这个命令,也可以查看槽位消息,且更为详细一些

六、新增、移除节点

#redis-cli --cluster help   查看语法帮助,后面不再过多开展
……
add-node       new_host:new_port existing_host:existing_port     #新主机添加到集群中
                       --cluster-slave
                       --cluster-master-id <arg>
del-node       host:port node_id                                          #从集群中移除某台主机

……

先写到这儿吧,后期如有需要再做更新,总之能看到这里,基本也对整个集群搭建有了一定了解了,边角料慢慢研究。

尾言

全文纯手工打造,难免有纰漏之处,欢迎批评指导,不过中间遇到的坑,大都已注明。

创作不易,本文如能解决您遇到的疑惑,动动您发财的小手,予以点赞,谢谢!

附注:predixy、twemproxy搭理的搭建


1、Redis分片代理predixy快速搭建

2、 Redis分片代理twemproxy快速搭建

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis6.2/5.0 集群两种快速搭建方式 的相关文章

  • 在Rails环境中执行Ruby Worker脚本

    我有以下案例 我希望能够将独立的 Ruby 脚本作为守护进程运行 我希望能够在我的 Rails 项目的上下文 环境中执行此脚本 例如 以便该脚本可以访问后端 我的 Rails 模型 有没有一种简单的方法可以实现这一点 Thanks Use
  • sRails 4.2 / Rspec / rspec-retry - 关联属于/has_many 失败

    我在 rspec 上面临着一个巨大的问题 每次我尝试解决一个错误时 它都会创建另一个错误 我有一个模型交易 其中有 许多步骤 模型 步骤 rb belongs to deal foreign key gt deal id 模型 deal r
  • 使用Redis从有限范围内生成唯一ID

    我有一些数据库项目 除了主键之外 还需要项目所属组的唯一索引 我们来调用属性nbr 以及将项目分组在一起并定义唯一范围的属性nbr 我们会打电话group This nbr必须在 1 N 范围内 并且may从外部源导入项目时进行设置 由于所
  • 对于 testunit 或其他 nunit 风格框架来说,什么才是好的失败消息?

    在 Ruby 的 test unit 和其他此类 nunit 风格框架中 什么才是好的失败消息 失败消息是否应该仅仅描述预期值与预期值不匹配的情况 assert match hey hey this is a test The word d
  • Ruby popen3 和 ANSI 颜色

    我试图让 watchr 在文件更改时自动运行测试 并获得了我需要的大部分工作 除了 RSpec 中的所有 ANSI 颜色都被忽略这一事实 违规代码如下 stdin stdout stderr Open3 popen3 cmd stdout
  • Ruby 中的日期时间和时间之间的转换

    在 Ruby 中如何在 DateTime 和 Time 对象之间进行转换 require time require date t Time now d DateTime now dd DateTime parse t to s tt Tim
  • 在 Ruby 中,哈希中标识符后面的冒号的含义是什么?

    我正在了解 Factory Girl 我看到了这段代码 factory post do association author factory user last name Writely end why do factory and las
  • 为 Ruby/Rails 动态更改 iTerm2 选项卡标题

    我使用的是 iTerm2 通常会打开许多 选项卡 不幸的是 所有选项卡都显示相同的标题 ruby 因为它都是 ruby 脚本 但一个是rails服务器 另一个是rails控制台 下一个是 spork 我想将选项卡标题动态设置为 服务器 控制
  • Redis SYNC 套接字上的错误情况:连接被拒绝

    在我的 django 应用程序中使用 celery 和 redis 一切都工作正常 直到我遇到了问题 redis 文件的位置已更改 redis 无法访问它们 经过查找 原来这是由于网络随机攻击造成的 需要添加confg 我添加文件后 一段时
  • 在 Ruby/Rails 模型/控制器中引用关联/属性时 *、self.* 和 @* 之间的差异

    假设 Rails 模型具有持久 非持久属性 那么引用它们的最佳实践是什么 如果您查看公开可用的代码 就会发现使用了不同的模式 例如 如果您有从一个模型到另一个模型的关联 使用有什么区别self association name and 协会
  • Gem .gemspec 中的本地依赖关系

    我正在开发一个 gem Gem A 它使用了我也编写的另一个 gem Gem B 到目前为止 Gem B 已添加到 Gem A 的 gemspec 中 gem add dependency gem a gt 0 0 4 但我现在发现需要使用
  • 在 Ruby 中覆盖 BigDecimal to_s 默认值

    当我从数据库表中检索数据时 会填充一个数组 某些字段被定义为小数和货币字段 并且在数组中它们表示为 BigDecimal 我使用这些数组值来填充 CSV 文件 但问题是所有 BigDecimal 值默认都以科学格式表示 这是 BigDeci
  • Ruby 枚举器链接

    在这个例子中 1 2 3 each with index map i j i j gt 0 2 6 我的理解是 既然each with index枚举器链接到map map表现得像each with index通过在块内传递索引 并返回一个
  • 在 Rails 控制台中创建实例时,Rails 4 强参数失败

    可能在这里做了一些愚蠢的事情 但这是我的基本千篇一律的课程 class League lt ActiveRecord Base private def league params params require full name permi
  • 初始化父类时如何返回子类的新实例?

    给定一个类层次结构如下 class A def initialize param if param 1 then initialize and return instance of B else initialize and return
  • Twitter-Typeahead 不提供建议

    我正在尝试使用twitter typeahead rails 我的目的是当我在 Typeahead 输入框中键入内容时 通过下拉框建议模型 User 的实例 但是 当我打字时什么也没有发生 有人看到我的代码有什么问题吗 Gemfile ge
  • 如何随机生成文件的链接?

    我有一个 PDF 文件 我不想通过我网站上的 URL 公开访问该文件 作为 轻微 安全层 我想通过电子邮件向用户发送一个唯一的 随机生成的 URL 他们可以从中下载 PDF 我将把该 PDF 存储在 AWS 或类似的地方 我感觉自己被困在r
  • 哪个版本的 ruby​​ bug 较少?

    我最近编写了一些复杂的 ruby 脚本 最终会在随机时间和随机位置因段错误而失败 例如 nokogiri mechanize inov 超时 我在 Windows 7 下的 1 9 1 p 129 1 8 6 p 369 和 ubuntu
  • 如何在Redis中进行持久化存储?

    关闭redis服务器后 使用set存储的值被破坏 在这里我找到了使用持久性存储的方法 有人帮助我 如何使用javascript实现这一点 我想将客户端的一些值存储在 redis 数据库中 并且必须在其他客户端中使用该值 您需要配置 Redi
  • gem 如何提供 Cucumber 功能和步骤定义?

    我有两个 Rails 项目 A 和 B 其中包含以下宝石 project A gem green theme path gt dev themes green theme gem devel tasks path gt dev themes

随机推荐

  • Windows驱动开发第11课(R3与R0通信交换数据第二节)

    在上一节课我们证实了在用户层调用CreateFile函数时 相应的在驱动层会响应一个IRP MJ CREATE的事件 这节课我们来看看用户层和驱动层是怎么交换数据的 首先来介绍一下控制码 由CTL CODE宏创建 是一个唯一的32位系统I
  • 数据库系统原理(第二版)知识点总结

    目录 第一章 概述 基本知识 数据模型 数据模型的组成要素 数据模型的分类 数据库系统的结构 第二章 关系运算 2 1 关系运算语言 1 关系代数语言 第三章 数据完整性 实体完整性 主属性的取值不能为空值 主属性的候选键的取值要非空且唯一
  • Python中的一些特殊函数

    https www cnblogs com maybe2030 p 4678920 html
  • centos7系统启动流程

    开机自检 gt 查找第一启动项设备 gt 加载第一启动项设备上的bootloader 存在于MBR中 gt 加载内核 initramfs gt 只读加载rootfs gt sbin init 即systemd
  • Flask 数据库 连接池、DBUtils、http 连接池

    1 DBUtils 简介 使用 DBUtils 简介 DBUtils 是一套用于管理 数据库 连接池 的Python包 为 高频度 高并发 的数据库访问提供更好的性能 可以自动管理连接对象的创建和释放 并允许对非线程安全的数据库接口进行线程
  • vector 查找_怎么写出无bug的二分查找算法代码

    封面图来自 geeksforgeeks 1 简介 二分查找算法是一类比较基础的算法 然而想要短时间内 写出二分查找的无 bug 版本 也不是很容易的 为此我查找了一些资料 终于弄清了二分查找算法的套路 在此分享给大家 也算是对自己学习知识的
  • Chisel3实践用例,安装

    新建SBT工程 sbt version 1 2 8 name ScalaExample version 0 1 scalaVersion 2 12 8
  • @Transient 理解

    transient使用小结 1 一旦变量被transient修饰 变量将不再是对象持久化的一部分 该变量内容在序列化后无法获得访问 2 transient关键字只能修饰变量 而不能修饰方法和类 注意 本地变量是不能被transient关键字
  • YOLOV2个人理解总结

    YOLOv2框架图 YOLOv2改进之处 1 Batch Normalization BN Batch Normalization 层简单讲就是对网络的每一层的输入都做了归一化 这样网络就不需要每层都去学数据的分布 收敛会快点 原来的YOL
  • 面试题:如何测试登录功能

    最近在做一个创新项目 这个项目有二个平台 每个平台都有前后端 故有四个系统 每个系统都有登录功能 而且不同系统代码设计方式都有所差异 所以就这个登录功能而言就要测试四次 看似一个简单的登录功能其中设计的测试点也是相当复杂 今天就讲讲如何测试
  • php scp跨服器拷贝文件到sftp

    一般要装php的ssh2扩展 比较麻烦 所以转念一想 为什么不用我们经常用的scp 但是scp跨服务器拷贝需要输入密码 这里就用到了一个工具试试sshpass 可以指定密码 1 工具安装 ubuntu安装 sudo apt get inst
  • 【问题解决】org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io

    1 出现问题异常 核心错误输出 org springframework dao QueryTimeoutException Redis command timed out nested exception is io lettuce cor
  • B站马士兵python入门基础版详细笔记(3)

    一 input函数的使用 他的返回值类型一定是str类型 m1 input please input the first word m2 input please input the second word print int m1 int
  • c++库 Android调用

    如果您想在Android应用程序中使用C 库 您可以通过以下几个步骤封装C 库以供Android调用 创建一个新的Android项目并设置C 支持 在Android Studio中创建一个新的Android项目 并选择包含C 支持的选项 将
  • [学C日记]---递归

    递归 自己调用自己 大事化小 必要条件 1 有限制条件 当满足限制条件时 递归便不继续 2 每次递归调用之后越来越接近这个限制条件 3 递归层次不能太深 太深容易栈溢出 每次递归调用都要给函数分栈区 次数过多容易空间不足 1 一串数字挨个输
  • 深聊自动化测试之:小鱼整理21条避坑指南,让你完美运行自动化

    自动化测试避坑总结 1 引言 2 避坑内容总结 2 1无法定位到元素 2 2 Indentation Error 2 3 PO设计模式类 2 4 页面封装类中没有已定义函数的问题 2 4 1 提示没有该方法 2 4 2 没有定义好的函数 2
  • Android Netd

    一 概述 所谓 Netd 就是Network Daemon 的缩写 表示Network守护进程 类似的命名还有很多 例如 Vold Volumn Deamon Rild Radio Interface Layer Deamon Netd负责
  • 根据面试的过程修正2022年学习规划

    上周由于全员降薪 所以对于在招聘网站上这30天内主动给我打招呼的hr和猎头 我都投了简历 结果是投简历16家公司 给与面试机会的七家 斩获了两家offer 一家七百多人的军事仿真类的公司 一家小到不能再小的ue4公司 好的方面是还能找到工作
  • python爬虫-33个Python爬虫项目实战(推荐)

    今天为大家整理了32个Python爬虫项目 整理的原因是 爬虫入门简单快速 也非常适合新入门的小伙伴培养信心 所有链接指向GitHub 祝大家玩的愉快 O O WechatSogou 1 微信公众号爬虫 基于搜狗微信搜索的微信公众号爬虫接口
  • Redis6.2/5.0 集群两种快速搭建方式

    一 集群常识 1 redis在3 0之前是集群 仅支持单实例的 3 0以后开始支持集群 2 3 0的集群命令也不是那么亲和 需要用ruby编写的脚本 而且需要登录redis客户端操作 启动 增删节点 移动槽位等 redis 5 0以后 可以