搭建redis-sentinel(哨兵机制)集群
redis怎么才能做到高可用
对于redis主从架构,slave可以对应多个本身可以保障高可用,但是对于一个master节点,如果宕机,整个缓存系统就无法进行写的操作,显然整个系统会无法做到高可用
sentinel哨兵可以监测master节点是否正常运行(会自动识别出所有的slave信息),如果出现宕机,则会在对应的slave节点中通过投票的方式来选取一个slave节点作为新的master节点,
旧的master节点恢复之后会被接管成为新的master节点的slave节点。同时sentinel哨兵节点本身也是集群的方式部署来保障自身的高可用,并且一个sentinel是可以同时监听多个master节点
对于sentinel哨兵节点的一些核心概念:
1、sdown和odown转换机制
sdown和odown两种失败状态
sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机
odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机
sdown达成的条件很简单,如果一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机
sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机
2、哨兵集群的自动发现机制
哨兵互相之间的发现,是通过redis的pub/sub系统实现的,每个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在
每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置
每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在
每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步
3、slave配置的自动纠正
哨兵会负责自动纠正slave的一些配置,比如slave如果要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据; 如果slave连接到了一个错误的master上,比如故障转移之后,那么哨兵会确保它们连接到正确的master上
4、slave->master选举算法
如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来
会考虑slave的一些信息
(1)跟master断开连接的时长
(2)slave优先级
(3)复制offset
(4)run id
如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对slave进行排序
(1)按照slave优先级进行排序,slave priority越低,优先级就越高
(2)如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高
(3)如果上面两个条件都相同,那么选择一个run id比较小的那个slave
5、quorum和majority
每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换
如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换
但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换
6、configuration epoch
哨兵会对一套redis master+slave进行监控,有相应的监控的配置
执行切换的那个哨兵,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个version号,每次切换的version号都必须是唯一的
如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号
7、configuraiton传播
哨兵完成切换之后,会在自己本地更新生成最新的master配置,然后同步给其他的哨兵,就是通过之前说的pub/sub消息机制
这里之前的version号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的version号的
其他的哨兵都是根据版本号的大小来更新自己的master配置的
1redis安装
解压完成后可以看到INSTALL和README.md文件,查看以获取更多有用信息。
在README文件中可以获取到软件的安装步骤。以下安装步骤基于此。
#step1 进入文件夹,执行编译命令
[root@ redis-3.2.8]# make
#step2 为了后面开发测试的方便,把启动脚本,配置文件,日志文件统一放到redis目录下
[root@ redis-3.2.8]# mkdir /usr/local/redis
[root@ redis-3.2.8]# mkdir /usr/local/redis/logs
[root@ redis-3.2.8]# mkdir /usr/local/redis/bin
[root@ redis-3.2.8]# mkdir /usr/local/redis/conf
[root@ redis-3.2.8]# mkdir /etc/sentinel
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26377
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26378
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26379
[root@ redis-3.2.8]# cp redis.conf sentinel.conf /usr/local/redis/conf/
[root@ src]# cp redis-server redis-sentinel redis-cli /usr/local/redis/bin/
#step3 开启Redis服务,检测其可用性
[root@ bin]# redis-server ../conf/redis.conf
可以看到日志信息
其中有3个警告
第一个警告:The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
意思是:TCP backlog设置值,511没有成功,因为 /proc/sys/net/core/somaxconn这个设置的是更小的128.
第二个警告:overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to/etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
意思是:overcommit_memory参数设置为0!在内存不足的情况下,后台程序save可能失败。建议在文件 /etc/sysctl.conf 中将overcommit_memory修改为1。
第三个警告:you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix thisissue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain thesetting after a reboot. Redis must be restarted after THP is disabled.
意思是:你使用的是透明大页,可能导致redis延迟和内存使用问题。执行 echo never > /sys/kernel/mm/transparent_hugepage/enabled 修复该问题。
临时解决方法:
echo 511 > /proc/sys/net/core/somaxconn
echo "vm.overcommit_memory=1" > /etc/sysctl.conf
echo never > /sys/kernel/mm/transparent_hugepage/enabled。
永久解决方法:
vim /etc/sysctl.conf
net.core.somaxconn = 512
vm.overcommit_memory = 1
sysctl -p #-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf中加载
[root@centos224]# vi /etc/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
Redis server使用默认端口6379启动成功。
#step4 修改配置文件,使其以后台服务方式运行。
#what?局域网内本机IP。
#我是部署到同一机器上所以IP都一样,端口不同
bind 127.0.0.1
#修改默认端口,避免被恶意脚本扫描。
port 9999
loglevel debug
logfile /usr/local/redis/logs/redis.log.9999
#为服务设置安全密码
requirepass redispass
#以守护进程方式运行
daemonize yes
#step5 重新启动redis。
[root@ bin]# redis-cli -p 9999 -a redispass shutdown
我使用脚本启动方式
启动脚本 redis_init_script 位于位于Redis的 /utils/ 目录下,redis_init_script脚本代码如下:
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem. #redis服务器监听的端口
REDISPORT= #服务端所处位置
EXEC=/usr/local/bin/redis-server #客户端位置
CLIEXEC=/usr/local/bin/redis-cli #redis的PID文件位置,需要修改
PIDFILE=/var/run/redis_${REDISPORT}.pid #redis的配置文件位置,需将${REDISPORT}修改为文件名
CONF="/etc/redis/${REDISPORT}.conf" case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
可以根据你自己端口进行修改
mkdir /etc/redis
cp redis.conf /etc/redis/9999.conf
将启动脚本复制到/etc/init.d目录下,本例将启动脚本命名为redisd(通常都以d结尾表示是后台自启动服务)。
cp redis_init_script /etc/init.d/redis_9999
./redis_9999 start
2开启主从复制(master-slave)
主从模式的两个重要目的,提升系统可靠性和读写分离提升性能。
这里通过修改端口的方式,再启动端口为9997和9998的服务作为备(从)机。
备机启动需要修改配置文件部分属性(在9999配置的基础上)。
port 9997
logfile /usr/local/redis/logs/redis.log.9997
#指定master ip port
slaveof 127.0.0.1 9999
#认证master时需要的密码。必须和master配置的requirepass 保持一致
masterauth redispass
requirepass redispass
protected-mode no
从机9998配置同理
port 9998
logfile /usr/local/redis/logs/redis.log.9998
slaveof 127.0.0.1 9999
masterauth redispass
requirepass redispass
protected-mode no
开启从机服务
[root@ bin]# ./redis_9997 start
[root@ bin]# ./redis_9998 start
查看slave 9998日志(省略部分信息),可以看出,slave在启动时成功连接master,并接收到了104字节的同步数据。
:S Mar ::17.206 * Connecting to MASTER 127.0.0.1:
:S Mar ::17.206 * MASTER <-> SLAVE sync started
:S Mar ::17.223 * MASTER <-> SLAVE sync: receiving bytes from master
:S Mar ::17.223 * MASTER <-> SLAVE sync: Finished with success
redis做一个基准的压测
你如果要对自己刚刚搭建好的redis做一个基准的压测,测一下你的redis的性能和QPS(query per second)
redis自己提供的redis-benchmark压测工具,是最快捷最方便的,当然啦,这个工具比较简单,用一些简单的操作和场景去压测
1、对redis读写分离架构进行压测,单实例写QPS+单实例读QPS
redis-3.2./src ./redis-benchmark -h 127.0.0.1 -c <clients> Number of parallel connections (default )
-n <requests> Total number of requests (default )
-d <size> Data size of SET/GET value in bytes (default )
根据你自己的高峰期的访问量,在高峰期,瞬时最大用户量会达到10万+,-c 100000,-n 10000000,-d 500
1、QPS,自己不同公司,不同服务器,自己去测试,跟生产环境还有区别
生产环境,大量的网络请求的调用,网络本身就有开销,你的redis的吞吐量就不一定那么高了
QPS的两个杀手:一个是复杂操作,lrange,挺多的; value很大,2 byte,我之前用redis做大规模的缓存
做商品详情页的cache,可能是需要把大串数据,拼接在一起,作为一个json串,大小可能都几k,几个byte
2、水平扩容redis读节点,提升度吞吐量
就按照上一节课讲解的,再在其他服务器上搭建redis从节点,单个从节点读请QPS在5万左右,两个redis从节点,所有的读请求打到两台机器上去,承载整个集群读QPS在10万+
3 sentinel模式故障自动迁移
Master-slave主从复制避免了数据丢失带来的灾难性后果。
但是单点故障仍然存在,在运行期间master宕机需要停机手动切换。
Sentinel很好的解决了这个问题,当Master-slave模式中的Master宕机后,能够自主切换,选择另一个可靠的redis-server充当master角色,使系统仍正常运行。
一般来说sentinel server需要大于等于3个。
这里通过修改端口的方式开启3个sentinel server。修改配置文件sentinel.conf部分属性
#服务运行端口号
port 26379
sentinel monitor mumaster 1270.0.0.1 9999 2
#mymaster为指定的master服务器起一个别名
#master IP和端口号
#2的含义:当开启的sentinel server认为当前master主观下线的(+sdown)数量达到2时,则sentinel server认为当前master客观下线(+odown)系统开始自动迁移。2的计算(建议):
#sentinel server数量的大多数,至少为count(sentinel server)/2 向上取整。2>3/2(主观下线与客观下线?)
#master别名和认证密码。这就提醒了用户,在master-slave系统中,各服务的认证密码应该保持一致。
sentinel auth-pass mymaster redispass
#以守护进程方式运行
daemonize yes
logfile /usr/local/redis/logs/sentinel.log.26379
protected-mode no
sentinel down-after-milliseconds mymaster 6000
sentinel failover-timeout mymaster 18000
(多开服务只需要在以上配置基础上修改端口号,其它保持不变 port 26378/port 26377)
开启Sentinel服务
redis-sentinel /etc/sentinel/26377.conf
redis-sentinel /etc/sentinel/26378.conf
redis-sentinel /etc/sentinel/26379.conf
启动之后可以看到日志信息,每个哨兵都能去监控到对应的redis master,并能够自动发现对应的slave,哨兵之间,互相会自动进行发现,用的就是之前说的pub/sub,消息发布和订阅channel消息系统和机制
检查哨兵状态
redis-cli -h 127.0.0.1 -p 26377 -a "redispass"
sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster
SENTINEL get-master-addr-by-name mymaster
哨兵节点相关配置
1、哨兵节点的增加和删除
增加sentinal,会自动发现
删除sentinal的步骤
(1)停止sentinal进程
(2)SENTINEL RESET *,在所有sentinal上执行,清理所有的master状态
(3)SENTINEL MASTER mastername,在所有sentinal上执行,查看所有sentinal对数量是否达成了一致
2、slave的永久下线
让master摘除某个已经下线的slave:SENTINEL RESET mastername,在所有的哨兵上面执行
3、slave切换为Master的优先级
slave->master选举优先级:slave-priority,值越小优先级越高
4、基于哨兵集群架构下的安全认证
每个slave都有可能切换成master,所以每个实例都要配置两个指令
master上启用安全认证,requirepass
master连接口令,masterauth
sentinal,sentinel auth-pass <master-group-name> <pass>
5、容灾演练
通过哨兵看一下当前的master:SENTINEL get-master-addr-by-name mymaster
把master节点kill -9掉,pid文件也删除掉
查看sentinal的日志,是否出现+sdown字样,识别出了master的宕机问题; 然后出现+odown字样,就是指定的quorum哨兵数量,都认为master宕机了
(1)三个哨兵进程都认为master是sdown了
(2)超过quorum指定的哨兵进程都认为sdown之后,就变为odown
(3)哨兵1是被选举为要执行后续的主备切换的那个哨兵
(4)哨兵1去新的master(slave)获取了一个新的config version
(5)尝试执行failover
(6)投票选举出一个slave区切换成master,每隔哨兵都会执行一次投票
(7)让salve,slaveof noone,不让它去做任何节点的slave了; 把slave提拔成master; 旧的master认为不再是master了
(8)哨兵就自动认为之前的master变成slave,将投票出的slave变成master
(9)哨兵去探查了一下之前的master(变成来salve)的状态,认为它sdown了
故障恢复,再将旧的master重新启动,查看是否被哨兵自动切换成slave节点
查看到结果将9999 切换为slave节点
容灾演练日志
Sentinel ID is ea82430cf7f6d452eb22bbf29b92fcf001c734c8
3010:X 21 Nov 22:37:31.405 # +monitor master mymaster 127.0.0.1 9999 quorum 2
3010:X 21 Nov 23:01:12.589 # +sdown master mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:12.642 # +odown master mymaster 127.0.0.1 9999 #quorum 3/2 -- 进入ODOWN状态时。有三个哨兵认为master当机了
3010:X 21 Nov 23:01:12.642 # +new-epoch 7 -- 当前配置版本被更新时。
3010:X 21 Nov 23:01:12.642 # +try-failover master mymaster 127.0.0.1 9999 -- 尝试故障转移,正等待其他sentinel的选举。
3010:X 21 Nov 23:01:12.658 # +vote-for-leader ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7 -- 投票给领导
3010:X 21 Nov 23:01:12.668 # edace82644513417b676ee6eced3184771d6361d voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.668 # 7e68a54266703cbf429f5c6512a50a39ab94b943 voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.716 # +elected-leader master mymaster 127.0.0.1 9999 -- 被选举为去执行failover的时候。
3010:X 21 Nov 23:01:12.716 # +failover-state-select-slave master mymaster 127.0.0.1 9999 -- 开始要选择一个slave当选新master时。
3010:X 21 Nov 23:01:12.792 # +selected-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 -- 找到了port:9998一个适合的slave来担当新master
-- 当把选择为新master的slave的身份进行切换的时候。
3010:X 21 Nov 23:01:12.792 * +failover-state-send-slaveof-noone slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999
-- 等待提升 9998 为新的master
3010:X 21 Nov 23:01:12.851 * +failover-state-wait-promotion slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:13.699 # +promoted-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 -- 提升 9998 master
3010:X 21 Nov 23:01:13.699 # +failover-state-reconf-slaves master mymaster 127.0.0.1 9999 -- Failover状态变为reconf-slaves状态时
3010:X 21 Nov 23:01:13.749 * +slave-reconf-sent slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999 -- 重新配置 9997为slave
3010:X 21 Nov 23:01:14.770 # -odown master mymaster 127.0.0.1 9999 -- 离开ODOWN状态时。
-- inprog 9997 slave被重新配置为9998的master的slave,但数据复制还未发生时。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-inprog slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999
-- done 9997 slave被重新配置为9998的master的slave,并且数据复制已经与master同步时。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-done slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:14.841 # +failover-end master mymaster 127.0.0.1 9999 -- 故障转移结束
3010:X 21 Nov 23:01:14.841 # +switch-master mymaster 127.0.0.1 9999 127.0.0.1 9998 -- master由9999 替换为 9998
3010:X 21 Nov 23:01:14.841 * +slave slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9998 -- 检测到9997slave并添加进slave列表时
3010:X 21 Nov 23:01:14.842 * +slave slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998 -- 检测到9999slave
3010:X 21 Nov 23:01:44.849 # +sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998 -- 进入SDOWN状态时;
3010:X 21 Nov 23:04:19.457 # -sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998 -- 离开SDOWN状态时
搭建redis-sentinel(哨兵机制)集群的更多相关文章
- redis sentinel哨兵模式集群搭建教程
1.环境说明 我们将使用192.168.220.128.192.168.220.129两台机器搭建sentinel交叉主从为例 当前我们已在192.168.220.128上按redis安装教程安装了r ...
- Redis sentinel 哨兵模式集群方案配置
第一个方案是创建 redis cluster,第二种方案就是用哨兵模式来进行主从替换以及故障恢复.兵模式集群方案配置 一.sentinel介绍 Sentinel作用: 1):Master状态检测 2) ...
- Redis的主从复制与Redis Sentinel哨兵机制
1 Redis的主从复制 1.1 什么是主从复制 持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损 ...
- Redis主从哨兵和集群搭建
主从配置 哨兵配置 集群配置 1.主从: 国王和丞相,国王权力大(读写),丞相权利小(读) 2.哨兵: 国王和王子,国王死了(主服务挂掉),王子继位(从服务变主服务) 3.集群: 国王和国王,一个国王 ...
- redis主从复制,哨兵以及集群搭建部署
redis主从复制 1.redis支持多实例的功能,一台机器上,可以运行多个单个的redis数据库 环境准备,运行3个redis数据库,达到 1主 2从的配置 主库 6379.conf port 63 ...
- Redis Sentinel哨兵配置
概述 Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都 ...
- redis 主从、哨兵、集群
出处: redis主从复制和哨兵 Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式 一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步 ...
- Redis 哨兵(sentinel)模式集群配置(5.0.3版本)
一.准备工作 1.系统环境:centos6.4 2.服务器六台(1主5从): 192.168.1.161(master) 192.168.1.162(slave) 192.168.1.163(slav ...
- 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...
随机推荐
- VS 自动展开选中当前代码所在的文件位置的功能
这个功能相当好,自动在Solution Explorer中展开并定位到当前代码所在的文件,免得自己找位置要找很久. 设置方法: tool>>options>>projects ...
- idea jdk版本问题
问题描述: Information:Using javac 1.6.0_43 to compile java sourcesInformation:java: Errors occurred whil ...
- Asynchronous programming in javascript
Javascript是单线程的,因此异步编程对其尤为重要. ES 6以前: * 回调函数* 事件监听(事件发布/订阅)* Promise对象 ES 6: * Generator函数(协程corouti ...
- leetcode 189 旋转数组
class Solution(object): def rotate(self, nums, k): """ :type nums: List[int] :type k: ...
- [转][C#]ImageHelper
{ internal static class ImageHelper { public static Bitmap CloneBitmap(Image source) { if (source == ...
- IE6设置li的float:left,不能自适应宽的解决方法
原文地址:https://blog.csdn.net/u012299002/article/details/50589453 做个divcss页面,发现在IE6下,设置了li的float:left,L ...
- 搭建 Jest+ Enzyme 测试环境
1.为什么要使用单元测试工具? 因为代码之间的相互调用关系,又希望测试过程单元相互独立,又能正常运行,这就需要我们对被测函数的依赖函数和环境进行mock,在测试数据输入.测试执行和测试结果检查方面存在 ...
- mybatis使用枚举优化
文章转自: https://segmentfault.com/a/1190000010755321 问题 在编码过程中,经常会遇到用某个数值来表示某种状态.类型或者阶段的情况,比如有这样一个枚举: p ...
- 检测Tensorflow可用设备(比如:显卡)
打开python命令行,输入以下命令: python -c "from tensorflow.python.client import device_lib;device_lib.list_ ...
- 服务注册中心,Eureka比Zookeeper好在哪里?
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性).A(可用性).和P(分区容错性).由于分区容错性P在分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡. 因此: Zookeep ...