redis 学习笔记(6)-cluster集群搭建
上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞sharding,现在方便多了,直接上cluster功能就行了,而且还支持节点动态添加、HA、节点增减后缓存重新分布(resharding)。
下面是参考官方教程cluster-tutorial 在mac机上搭建cluster的过程:
一、下载最新版redis 编译
目前最新版是3.0.7,下载地址:http://www.redis.io/download
编译很简单,一个make命令即可,不清楚的同学,可参考我之前的笔记: redis 学习笔记(1)-编译、启动、停止
二、建6个目录
mkdir ~/app/redis-cluster/ #先建一个根目录
mkdir 7000 7001 7002 7003 7004 7005
注:与大多数分布式中间件一样,redis的cluster也是依赖选举算法来保证集群的高可用,所以类似ZK一样,一般是奇数个节点(可以允许N/2以下的节点失效),再考虑到每个节点做Master-Slave互为备份,所以一个redis cluster集群最少也得6个节点。
然后把步骤1里编译好的redis,复制到这6个目录下。
三、配置文件
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
把上面这段保存成redis-cluster.conf,放到每个目录的redis目录中,注意修改port端口,即7000目录下的port为7000,7001目录下的port为7001...
cluster-node-timeout 是集群中各节点相互通讯时,允许"失联"的最大毫秒数,上面的配置为5秒,如果超过5秒某个节点没向其它节点汇报成功,认为该节点挂了。
四、依次启动各个redis
在每个目录redis的src子目录下,输入:
./redis-server ../redis-cluster.conf
这样7000~7005这6个节点就启动了。
五、安装redis的ruby模块
brew update
brew install ruby
sudo gem install redis #注:这个步骤建议翻^墙,不然你懂的
解释:虽然步骤4把6个redis server启动成功了,但是彼此之间是完全独立的,需要借助其它工具将其加入cluster,而这个工具就是redis提供的一个名为redis-trib.rb的ruby脚本(个人估计redis的作者比较偏爱ruby),mac自带了ruby2.0环境,但是没有redis模块,所以要安装这玩意儿,否则接下来的创建cluster将失败。
六、创建cluster
./redis-trib.rb create --replicas 1 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
仍然保持在某个目录的src子目录下,运行上面这段shell脚本,cluster就创建成功了,replicas 1的意思,就是每个节点创建1个副本(即:slave),所以最终的结果,就是后面的127.0.0.1:7000~127.0.0.1:7005中,会有3个会指定成master,而其它3个会指定成slave。
注:利用redis-trib创建cluster的操作,只需要一次即可,假设系统关机,把所有6个节点全关闭后,下次重启后,即自动进入cluster模式,不用再次redis-trib.rb create。
此时,如何用ps查看redis进程,会看到每个进程后附带了cluster的字样
如果想知道,哪些端口的节点是master,哪些端口的节点是slave,可以用下面的命令:
./redis-trib.rb check 127.0.0.1:7000
输出结果如下:
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000
slots: (0 slots) slave
replicates 38910c5baafea02c5303505acfd9bd331c608cfc
M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005
slots: (0 slots) slave
replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa
S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004
slots: (0 slots) slave
replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa
M: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
从上面的输出,可以看出7000、7004、7005是slave,而7001、7003、7002是master(如果大家人为做过一些failover的测试,比如把某个节点手动停掉,再恢复,输出的结果可能与上面不太一样),除了check参数,还有一个常用的参数info
./redis-trib.rb info 127.0.0.1:7000
输出结果如下:
127.0.0.1:7001 (e0e8dfdd...) -> 2 keys | 5462 slots | 1 slaves.
127.0.0.1:7003 (38910c5b...) -> 2 keys | 5461 slots | 1 slaves.
127.0.0.1:7002 (ec964a7c...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 4 keys in 3 masters.
0.00 keys per slot on average.
它会把所有的master信息输出,包括这个master上有几个缓存key,有几个slave,所有master上的keys合计,以及平均每个slot上有多少key,想了解更多redis-trib脚本的其它参数,可以用
./redis-trib.rb help
输出如下:
Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN
--replicas <arg>
check host:port
info host:port
fix host:port
--timeout <arg>
reshard host:port
--from <arg>
--to <arg>
--slots <arg>
--yes
--timeout <arg>
--pipeline <arg>
rebalance host:port
--weight <arg>
--auto-weights
--use-empty-masters
--timeout <arg>
--simulate
--pipeline <arg>
--threshold <arg>
add-node new_host:new_port existing_host:existing_port
--slave
--master-id <arg>
del-node host:port node_id
set-timeout host:port milliseconds
call host:port command arg arg .. arg
import host:port
--from <arg>
--copy
--replace
help (show this help) For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
上面已经多次出现了slot这个词,略为解释一下:
如上图,redis-cluster把整个集群的存储空间划分为16384个slot(译为:插槽?),当6个节点分为3主3从时,相当于整个cluster中有3组HA的节点,3个master会平均分摊所有slot,每次向cluster中的key做操作时(比如:读取/写入缓存),redis会对key值做CRC32算法处理,得到一个数值,然后再对16384取模,通过余数判断该缓存项应该落在哪个slot上,确定了slot,也就确定了保存在哪个master节点上,当cluster扩容或删除节点时,只需要将slot重新分配即可(即:把部分slot从一些节点移动到其它节点)。
七、redis-cli客户端操作
./redis-cli -c -h localhost -p 7000
注意加参数-c,表示进入cluster模式,随便添加一个缓存试试:
localhost:7000> set user1 jimmy
-> Redirected to slot [8106] located at 127.0.0.1:7001
OK
注意第2行的输出,表示user1这个缓存通过计算后,落在8106这个slot上,最终定位在7001这个端口对应的节点上(解释:因为7000是slave,7001才是master,只有master才能写入),如果是在7001上重复上面的操作时,不会出现第2行(解释:7001是master,所以不存在redirect的过程)
➜ src ./redis-cli -c -h localhost -p 7001
localhost:7001> set user1 yang
OK
localhost:7001>
八、FailOver测试
先用redis-trib.rb 查看下当前的主、从情况
➜ src ./redis-trib.rb check localhost:7000
>>> Performing Cluster Check (using node localhost:7000)
S: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e localhost:7000
slots: (0 slots) slave
replicates 38910c5baafea02c5303505acfd9bd331c608cfc
M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004
slots: (0 slots) slave
replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa
S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005
slots: (0 slots) slave
replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa
M: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
从输出上看7000是7003(38910c5baafea02c5303505acfd9bd331c608cfc)的slave,现在我们人工把7003的redis进程给kill掉,然后观察7000的终端输出:
872:S 21 Mar 10:55:55.663 * Connecting to MASTER 127.0.0.1:7003
3872:S 21 Mar 10:55:55.663 * MASTER <-> SLAVE sync started
3872:S 21 Mar 10:55:55.663 # Error condition on socket for SYNC: Connection refused
3872:S 21 Mar 10:55:55.771 * Marking node 38910c5baafea02c5303505acfd9bd331c608cfc as failing (quorum reached).
3872:S 21 Mar 10:55:55.771 # Cluster state changed: fail
3872:S 21 Mar 10:55:55.869 # Start of election delayed for 954 milliseconds (rank #0, offset 183).
3872:S 21 Mar 10:55:56.703 * Connecting to MASTER 127.0.0.1:7003
3872:S 21 Mar 10:55:56.703 * MASTER <-> SLAVE sync started
3872:S 21 Mar 10:55:56.703 # Error condition on socket for SYNC: Connection refused
3872:S 21 Mar 10:55:56.909 # Starting a failover election for epoch 10.
3872:S 21 Mar 10:55:56.911 # Failover election won: I'm the new master.
3872:S 21 Mar 10:55:56.911 # configEpoch set to 10 after successful failover
3872:M 21 Mar 10:55:56.911 * Discarding previously cached master state.
3872:M 21 Mar 10:55:56.911 # Cluster state changed: ok
注意5,6,11这几行,第5行表明由于7003宕机,cluster状态已经切换到fail状态,第6行表示发起选举,第11行表示7000端口对应的节点当选为new master。
注:如果一组分片中的master、slave全挂了,整个cluster集群不再接受任何读/写指令,redis-cli终端里会直接报cluster down,但是info等其它指令仍然可用,直到这一组分片中,有一个节点恢复为止。
九、cluster 扩容
业务规模变大后,集群扩容是早晚的事情,下面演示如何再添加2个节点,先把7000复制二份,变成7006,7007,然后进入7006/7007目录redis的src子目录下
rm nodes.conf dump.rdb appendonly.aof
由于7000我们刚才启动过,里面有已经有一些数据了,所以要把数据文件,日志文件,以及cluster的nodes.conf文件删除,变成一个空的redis独立节点,否则无法加入cluster。
然后修改redis-cluster.conf
port 7000
cluster-enabled yes
cluster-config-file "nodes.conf"
cluster-node-timeout 10000
appendonly yes
# Generated by CONFIG REWRITE
dir "/Users/yjmyzz/app/redis-cluster/7000/redis-3.0.7/src"
要修改的地方有二处,1是第一行的端口,改成与7006/7007匹配的端口,2是最后2行,这是7000运行后,自动添加的,把最后二行删除。
做完这些后,启动7006,7007这二个redis节点,此时这2个新节点与cluster没有任何关系,可以用下面的命令将7006做为master添加到cluster中。
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
注:第1个参数为新节点的"IP:端口",第2个参数为集群中的任一有效的节点。
顺利的话,输出如下:
>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004
slots: (0 slots) slave
replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa
M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005
slots: (0 slots) slave
replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa
S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003
slots: (0 slots) slave
replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.
可以再用check确认下状态:
➜ src ./redis-trib.rb check 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004
slots: (0 slots) slave
replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa
M: 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7006
slots: (0 slots) master
0 additional replica(s)
M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005
slots: (0 slots) slave
replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa
S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003
slots: (0 slots) slave
replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
12-14行说明7006已经是cluster的新master了,继续,用下面的命令把7007当成slave加入:
./redis-trib.rb add-node --slave --master-id 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7007 127.0.0.1:7000
这里多出了二个参数:--slave 表示准备将新节点当成slave加入,--master-id xxxxx 则是指定要当谁的slave,后面的xxx部分,即为前面check的输出结果中,7006的ID,完事之后,可以再次确认状态:
➜ src ./redis-trib.rb check 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 792bcccf35845c4922dd33d7f9827420ebb89bc9 127.0.0.1:7007
slots: (0 slots) slave
replicates 226d1af3c95bf0798ea9fed86373b89347f889da
M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004
slots: (0 slots) slave
replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa
M: 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7006
slots: (0 slots) master
1 additional replica(s)
M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005
slots: (0 slots) slave
replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa
S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003
slots: (0 slots) slave
replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
观察6-8行、15-17行,说明7007已经是7006的slave。
十、reshard 重新划分slot
增加新的节点之后,问题就来了,16384个slot已经被其它3组节点分完了,新节点没有slot,没办法存放缓存,所以需要将slot重新分布。
➜ src ./redis-trib.rb info 127.0.0.1:7000
127.0.0.1:7000 (0b7e0d53...) -> 4 keys | 5461 slots | 1 slaves.
127.0.0.1:7001 (e0e8dfdd...) -> 4 keys | 5462 slots | 1 slaves.
127.0.0.1:7006 (226d1af3...) -> 0 keys | 0 slots | 1 slaves. #7006上完全没有slot
127.0.0.1:7002 (ec964a7c...) -> 9 keys | 5461 slots | 1 slaves.
[OK] 17 keys in 4 masters.
0.00 keys per slot on average.
用下面的命令可以重新分配slot
./redis-trib.rb reshard 127.0.0.1:7000
reshard后面的IP:port,只要是在cluster中的有效节点即可。
➜ src ./redis-trib.rb reshard 127.0.0.1:7000
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000
slots:1792-4095 (2304 slots) master
0 additional replica(s)
...
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 1000 #这里输入要移动多少slot
What is the receiving node ID? 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e #这里输入目标节点的id
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:all #将所有node都当成源节点
...
Moving slot 4309 from ec964a7c7cd53b986f54318a190c1426fc53a5fa
Moving slot 4310 from ec964a7c7cd53b986f54318a190c1426fc53a5fa
Moving slot 4311 from ec964a7c7cd53b986f54318a190c1426fc53a5fa
Moving slot 4312 from ec964a7c7cd53b986f54318a190c1426fc53a5fa
Moving slot 4313 from ec964a7c7cd53b986f54318a190c1426fc53a5fa
Do you want to proceed with the proposed reshard plan (yes/no)? yes #确认执行
注:第一个交互询问,填写多少slot移动时,要好好想想,如果填成16384,则将所有slot都移动到一个固定节点上,会导致更加不均衡!建议每次移动500~1000,这样对线上的影响比较小。
另外在填写source node时,除了all之外,还可以直接填写源节点的id,即:
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 300
What is the receiving node ID? 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:226d1af3c95bf0798ea9fed86373b89347f889da #这里填写源节点的id
Source node #2:done #这里输入done表示,不再继续添加源节点了
reshard可以多次操作,直到达到期望的分布为止(注:个人觉得redis的reshard这里有点麻烦,要移动多少slot需要人工计算,如果能提供一个参数之类,让16384个slot自动平均分配就好了),调整完成后,可以再看看分布情况:
➜ src ./redis-trib.rb info 127.0.0.1:7000
127.0.0.1:7000 (0b7e0d53...) -> 4 keys | 4072 slots | 0 slaves.
127.0.0.1:7001 (e0e8dfdd...) -> 5 keys | 4099 slots | 0 slaves.
127.0.0.1:7006 (226d1af3...) -> 5 keys | 4132 slots | 4 slaves.
127.0.0.1:7002 (ec964a7c...) -> 3 keys | 4081 slots | 0 slaves.
[OK] 17 keys in 4 masters.
0.00 keys per slot on average.
十一、删除节点del-node
既然有扩容,就会有反向需求,某些节点不再需要时,可以用del-node删除,比如刚才我一阵乱倒腾后,发现7006已经有4个slave了,而其它master一个slave都没有,这明显不合理。
删除节点命令:
./redis-trib.rb del-node 127.0.0.1:7006 88e16f91609c03277f2ee6ce5285932f58c221c1
del-node后面的ip:port只要是cluster中有效节点即可,最后一个参数为目标节点的id,注意:只有slave节点和空的master节点可以删除,如果master非空,先用reshard把上面的slot移动到其它node后再删除,如果有一组master-slave节点,将master上所有slot移到其它节点,然后将master删除,剩下的slave会另寻他主,变成其它master的slave。
另外:删除节点的含义,不仅仅是从cluster中将这个节点移除,还会直接将目标节点的redis服务停止。
参考文章:
http://www.redis.io/topics/cluster-tutorial
redis 学习笔记(6)-cluster集群搭建的更多相关文章
- Redis学习笔记八:集群模式
作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...
- ZooKeeper学习笔记一:集群搭建
作者:Grey 原文地址:ZooKeeper学习笔记一:集群搭建 说明 单机版的zk安装和运行参考:https://zookeeper.apache.org/doc/r3.6.3/zookeeperS ...
- Redis学习笔记~conf自主集群模式
回到目录 Redis自主提供了集群模式,当然也只是比较简单的读写分离模式,或者叫主从模式,它在各个redis服务端自己做数据同步机制,当然就是将主服务端的信息同步到各个slave服务器上,在客户端集成 ...
- 开源流媒体服务器SRS学习笔记(4) - Cluster集群方案
单台服务器做直播,总归有单点风险,利用SRS的Forward机制 + Edge Server设计,可以很容易搭建一个大规模的高可用集群,示意图如下 源站服务器集群:origin server clus ...
- Redis Cluster集群搭建与应用
1.redis-cluster设计 Redis集群搭建的方式有多种,例如使用zookeeper,但从redis 3.0之后版本支持redis-cluster集群,redis-cluster采用无中心结 ...
- 重要参考步骤---ProxySQL Cluster 集群搭建步骤
环境 proxysql-1:192.168.20.202 proxysql-2:192.168.20.203 均采用yum方式安装 # cat <<EOF | tee /etc/yum.r ...
- redis 学习笔记-cluster集群搭建
一.下载最新版redis 编译 目前最新版是3.0.7,下载地址:http://www.redis.io/download 编译很简单,一个make命令即可,不清楚的同学,可参考我之前的笔记: red ...
- Redis Cluster集群搭建与配置
Redis Cluster是一种服务器sharding分片技术,关于Redis的集群方案应该怎么做,请参考我的另一篇博客http://www.cnblogs.com/xckk/p/6134655.ht ...
- Redis进阶实践之十一 Redis的Cluster集群搭建
一.引言 本文档只对Redis的Cluster集群做简单的介绍,并没有对分布式系统的详细概念做深入的探讨.本文只是提供了有关如何设置集群.测试和操作集群的说明,而不涉及Redis集群规范中涵 ...
随机推荐
- 有向无环图的应用—AOV网 和 拓扑排序
有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...
- Python(八)进程、线程、协程篇
本章内容: 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 线程 Threading用于提供线程相关的操作.线程是应用 ...
- 重定向Http status code 303 和 302
http 302 http 303 Http 302 302是一个普通的重定向代码.直观的看来是,请求者(浏览器或者模拟http请求)发起一个请求,然后服务端重定向到另一个地址.而事实上,服务端仅仅是 ...
- MyCat源码分析系列之——SQL下发
更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...
- C# WCF服务端搭建和客户端调用
1) 打开Visual Studio 2012,在菜单上点击文件->新建->项目->WCF服务应用程序.在弹出界面的"名称"对应的文本框中输入"WcfS ...
- Could not find a suitable SDK to target
安装windows-10-sdk 应该可解决此问题 windows-10-sdk下载地址: developer.microsoft.com/en-us/windows/downloads/wi ...
- 2015年软件测试STATE报告
STATE OF TESTING 2015 Report 测试职业的地理位置分配 大部分有5年以上工作经验 大部分是Test Leader 测试工程师角色 测试工程师怎么工作的? 测试中的软件 ...
- activiti工作流的web流程设计器整合视频教程 SSM和独立部署
本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...
- .Net 搭建 RESTful
1.新建项目 ---> 选择 web 应用程序 选择 webApi 2. 创建一个httpmodeule类 放到app_data文件夹下 public class MyHttpModule : ...
- Quartz框架(第一版)
任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维 ...