Redis sentinel哨兵集群的实现步骤


Posted in Redis onJuly 15, 2022

一、Redis sentinel哨兵集群概述

(1)Redis哨兵概述

*Sentinel 哨兵:这是一个分布式系统,该进程是用于监控Redis集群中Master主服务器的工作状态,在Master主服务器发生故障时,可以实现Master和Slave服务器的秒级切换,保证系统有一个Master主服务器,提供了Redis集群的高可用,在Reids2.6.版本时被加入,到2.8版本之后得到了稳定

Redis哨兵和Redis主从的区别:

Redis哨兵:主服务器出现故障后,会有一个从服务器代替主服务器

Redis主从:主服务器出现故障后,从服务器不会做任何事

Redis sentinel哨兵集群的实现步骤

(2)Redis哨兵的工作机制

哨兵只需要部署在master主服务器上即可

工作进程:

监控(Monitoring):哨兵通过流言协议(gossip protocols)会不断检查集群中每一台服务器是否运作正常

提醒(Notification):当哨兵监控的某个redis服务器出现问题时,哨兵可以通过API(应用程序接口)向管理员或者其他应用程序发送通知

自动故障转移(Automatic failover):在集群中如果有一个Master主服务器出现故障时,哨兵会通过投票协议(Agreement Protocols)开始一次自动故障迁移操作,他会选择一台数据较完整的Slave从服务器升级为主服务器,当客户端试图连接失效的Master主服务器时,集群也会向客户端返回新的Master主服务器的地址,使得集群可以使用现在的Master替换掉失效的Master。

Master和Slave切换后,Master的redis主配置文件、Slave的redis主配置文件和哨兵的配置文件的内容都会发生相应的改变,即原来的Master的redis主配置文件会多一行Slave服务器的配置,之后哨兵的监控目标就会改变到现在的Master主服务器上

Redis sentinel哨兵集群的实现步骤

(3)哨兵的三个定时监控任务

每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取Redis数据节点的信息

作用:

通过向主节点执行info命令,获取从节点的信息,这也是为什么Sentinel节点不需要显式配置监控从节点。当有新的从节点加入时都可以立刻感知出来,当节点不可达或者故障转移后,可以通过info命令实时更新节点拓扑信息。

每隔1秒,每个Sentinel节点会向主节点、从节点、发送一条ping命令做一次心跳检测,来确认这些节点当前是否可达如果主节点挂掉,那么sentinel,就会从剩余的从节点选择一个数据比较完整来做主节点

二、部署Redis哨兵系统

(1)实验环境

系统 ip 主机名 Redis版本 端口 扮演角色
Centos7.4 192.168.100.202 master Redis-5.0.4 Redis:6379 Sentinel:26379 Master
Centos7.4 192.168.100.203 slave1 Redis-5.0.4 Redis:6379 Slave
Centos7.4 192.168.100.204 slave2 Redis-5.0.4 Redis:6379 Slave

(2)实验步骤 -在每台服务器上都安装Redis

安装步骤相同,主机名、ip不同,下面只写Master配置

[root@Centos7 ~]# hostnamectl set-hostname master
[root@Centos7 ~]# su
[root@master ~]# systemctl stop firewalld
[root@master ~]# setenforce 0
setenforce: SELinux is disabled
[root@master ~]# mount /dev/cdrom /mnt/
mount: /dev/sr0 写保护,将以只读方式挂载
mount: /dev/sr0 已经挂载或 /mnt 忙
       /dev/sr0 已经挂载到 /mnt 上
[root@master ~]# ll
总用量 1928
-rw-------. 1 root root    1264 1月  12 18:27 anaconda-ks.cfg
-rw-r--r--  1 root root 1966337 6月   9 01:16 redis-5.0.4.tar.gz
[root@master ~]# tar xf redis-5.0.4.tar.gz
[root@master ~]# cd redis-5.0.4
[root@master redis-5.0.4]# make
[root@master redis-5.0.4]# mkdir -p /usr/local/redis
[root@master redis-5.0.4]# cp /root/redis-5.0.4/src/redis-server /usr/local/redis/
[root@master redis-5.0.4]# cp /root/redis-5.0.4/src/redis-cli /usr/local/redis/
[root@master redis-5.0.4]# cp /root/redis-5.0.4/redis.conf  /usr/local/redis/ 
[root@master redis-5.0.4]# vim /usr/local/redis/redis.conf   #修改
。。。。。。
  68 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  69 bind 192.168.100.202  #修改为本机地址,如果为127.0.0.1就只能本机访问
  70 
。。。。。。
  87 # are explicitly listed using the "bind" directive.
  88 protected-mode no  #关闭redis的保护模式,如果为yes的话其他客户端就无法连接到此服务器
  89 
。。。。。。
 135 # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
 136 daemonize yes  #开启redis的后台守护程序,即在redis开启之后是放在后台运行的
 137 
。。。。。。
 262 # Note that you must specify a directory here, not a file name.
 263 dir /usr/local/redis/rdb
 264 
。。。。。。
 506 #
 507 requirepass 123123  #去掉注释,修改redis的密码为123123
 508 
#保存退出
[root@slave2 redis-5.0.4]# mkdir /usr/local/redis/rdb
[root@master redis-5.0.4]# vim /etc/init.d/redis
#!/bin/sh
# chkconfig: 2345 80 90
# description: Start and Stop redis
#PATH=/usr/local/bin:/sbin:/usr/bin:/bin
REDISPORT=6379
EXEC=/usr/local/redis/redis-server
REDIS_CLI=/usr/local/redis/redis-cli
PIDFILE=/var/run/redis_6379.pid
CONF="/usr/local/redis/redis.conf"
AUTH="123123"
LISTEN_IP=$(netstat -utpln |grep redis-server |awk '{print $4}'|awk -F':' '{print $1}')

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
        if [ "$?"="0" ]
        then
              echo "Redis is running..."
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $REDIS_CLI -h $LISTEN_IP -p $REDISPORT -a $AUTH SHUTDOWN
                while [ -x ${PIDFILE} ]
               do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
   restart|force-reload)
        ${0} stop
        ${0} start
        ;;
  *)
    echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2
        exit 1
esac
[root@master redis-5.0.4]# chkconfig --add redis
[root@master redis-5.0.4]# chmod 755 /etc/init.d/redis
[root@master redis-5.0.4]# ln -s /usr/local/redis/* /usr/local/bin/
[root@master redis-5.0.4]# /etc/init.d/redis start 
Starting Redis server...
5233:C 09 Jun 2021 01:25:53.069 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5233:C 09 Jun 2021 01:25:53.069 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=5233, just started
5233:C 09 Jun 2021 01:25:53.069 # Configuration loaded
Redis is running...
[root@master redis-5.0.4]# netstat -anpt | grep 6379
tcp        0      0 192.168.100.202:6379    0.0.0.0:*               LISTEN      5234/redis-server 1

-做redis主从

******(1)Master配置
[root@master redis-5.0.4]# vim /usr/local/redis/redis.conf #修改
。。。。。。
 292 #
 293  masterauth 123123  #配置主服务器密码,哨兵有一个问题,就是当主服务器坏掉,切换到从服务器时,原来的主服务器可以正常运行之后,再次加入集群是加不进去的,因为哨兵没有配置主服务器的密码,所以无法连接,所以在使用哨兵集群时,要把每台的主服务器密码都配置上,每台redis的密码最好都一样
 294 
。。。。。。
 456 #
 457  min-replicas-to-write 1 #设置slave服务器的数量,当slave服务器少于这个数量时,Master主服务器会停止接收客户端的一切写请求
 458  min-replicas-max-lag 10 #设置主服务器和从服务器之间同步数据的超时时间,当超过此时间时,master主服务器会停止客户端的一切写操作,单位为秒
 459 #
。。。。。。
[root@master redis-5.0.4]# /etc/init.d/redis restart   #重启redis
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped
Starting Redis server...
5291:C 09 Jun 2021 02:04:39.132 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5291:C 09 Jun 2021 02:04:39.132 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=5291, just started
5291:C 09 Jun 2021 02:04:39.132 # Configuration loaded
Redis is running...

******(2)Slave1配置
[root@slave1 redis-5.0.4]# vim /usr/local/redis/redis.conf 
。。。。。。
 285 #
 286 replicaof 192.168.100.202 6379  #在从服务器上指定主服务器的ip和端口
 287 
。。。。。。
 292 #
 293 masterauth 123123  #指定主服务器上redis的密码
 294
。。。。。。
#保存退出
[root@slave redis-5.0.4]# /etc/init.d/redis restart  #重启服务
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped
Starting Redis server...
5304:C 09 Jun 2021 02:11:32.241 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5304:C 09 Jun 2021 02:11:32.241 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=5304, just started
5304:C 09 Jun 2021 02:11:32.241 # Configuration loaded
Redis is running...

******(3)Slave2配置
[root@slave2 redis-5.0.4]# vim /usr/local/redis/redis.conf 
。。。。。。
 286  replicaof 192.168.100.204 6379
 287 
 288 # If the master is password protected (using the "requirepass" configuration
 289 # directive below) it is possible to tell the replica to authenticate before
 290 # starting the replication synchronization process, otherwise the master will
 291 # refuse the replica request.
 292 #
 293  masterauth 123123
 294 
。。。。。。
#保存退出
[root@slave2 redis-5.0.4]# /etc/init.d/redis restart 
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped
Starting Redis server...
5253:C 09 Jun 2021 17:50:25.680 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5253:C 09 Jun 2021 17:50:25.680 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=5253, just started
5253:C 09 Jun 2021 17:50:25.680 # Configuration loaded
Redis is running...

******(3)验证主从是否成功
[root@master ~]# redis-cli -h 192.168.100.202 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.202:6379> set aaa bbb
OK
192.168.100.202:6379> set bbb ccc 
OK
192.168.100.202:6379> keys *
1) "aaa"
2) "bbb"

[root@slave1 ~]# redis-cli -h 192.168.100.203 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.203:6379> keys *
1) "bbb"
2) "aaa"
192.168.100.203:6379> set ttt fff
(error) READONLY You can't write against a read only replica.  #从服务器无法写入数据

[root@slave2 redis-5.0.4]# redis-cli -h 192.168.100.204 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.204:6379> keys *
1) "aaa"
2) "bbb"
192.168.100.204:6379> set ggg aaa
(error) READONLY You can't write against a read only replica.

#主从配置完成

-配置哨兵

******(1)在master上配置sentinel哨兵
[root@master ~]# cp redis-5.0.4/src/redis-sentinel /usr/local/redis/  #复制哨兵启动脚本
[root@master ~]# cp redis-5.0.4/sentinel.conf /usr/local/redis/  #复制哨兵配置文件
[root@master ~]# mkdir -p /var/redis/data  #创建日志文件存放位置	
[root@master ~]# vim /usr/local/redis/sentinel.conf   #修改哨兵配置文件
。。。。。。
 21 port 26379  #指定端口默认为26379
 22 
 23 # By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it.
 24 # Note that Redis will write a pid file in /var/run/redis-sentinel.pid when
 25 # daemonized.
 26 daemonize yes  #yes为放在后台运行,使用no放在前台运行可以看到主从切换时候的信息
 27 
。。。。。。
 64 # unmounting filesystems.
 65 dir /var/redis/data  #指定日志存放位置,就是刚才创建的路径
 66 
。。。。。。
 83 # The valid charset is A-z 0-9 and the three characters ".-_".
 84 sentinel monitor mymaster 192.168.100.202  6379 1  #指定用户为mymaster,ip为202,端口为6379,1表示当有一台master出现故障时,就进行切换
 85 
 86 # sentinel a
。。。。。。
112 # Default is 30 seconds.
113 sentinel down-after-milliseconds mymaster 3000  #指定master的失效时间,单位为毫秒3000为3秒,表示master超过3秒没响应就判定为故障
114 
。。。。。。
145 # Default is 3 minutes.
146 sentinel failover-timeout mymaster 180000  #切换操作完成的超时时间,单位为毫秒180000为180秒,在主从切换超过这个时间就判定为切换失败
147 
148 # SCRIPTS EXE
。。。。。。
102 #
103  sentinel auth-pass mymaster 123123  #连接master和slave的密码
104 sentinel config-epoch mymaster  1  #切换后最多有多少节点可以于新的master进行同步数据
105 
#保存退出
[root@master ~]# /usr/local/redis/redis-sentinel /usr/local/redis/sentinel.conf  #启动哨兵
1118:X 09 Jun 2021 18:09:29.027 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1118:X 09 Jun 2021 18:09:29.027 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1118, just started
1118:X 09 Jun 2021 18:09:29.027 # Configuration loaded
[root@master ~]# netstat -anpt | grep 26379
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN      1119/redis-sentinel 
tcp6       0      0 :::26379                :::*                    LISTEN      1119/redis-sentinel 
[root@master ~]# kill -9 1119  #先关闭哨兵
[root@master ~]# netstat -anpt | grep 26379
[root@master ~]# sed -i '26s/yes/no/g' /usr/local/redis/sentinel.conf  #修改为前台启动
[root@master ~]# /usr/local/redis/redis-sentinel /usr/local/redis/sentinel.conf  #再次开启哨兵,稍等一段时间会有提示
1129:X 09 Jun 2021 18:11:02.585 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1129:X 09 Jun 2021 18:11:02.585 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1129, just started
1129:X 09 Jun 2021 18:11:02.585 # Configuration loaded
1129:X 09 Jun 2021 18:11:02.586 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.4 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 1129
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

1129:X 09 Jun 2021 18:11:02.586 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1129:X 09 Jun 2021 18:11:02.586 # Sentinel ID is fce7776020cf12792fd239f6f9d34f2d3fdef98c
1129:X 09 Jun 2021 18:11:02.586 # +monitor master mymaster 192.168.100.202 6379 quorum 1
1129:X 09 Jun 2021 18:18:04.434 * +reboot slave 192.168.100.204:6379 192.168.100.204 6379 @ mymaster 192.168.100.202 6379  #看到新增两条消息,从服务器增加了203和204主服务器时202
1129:X 09 Jun 2021 18:18:14.478 * +reboot slave 192.168.100.203:6379 192.168.100.203 6379 @ mymaster 192.168.100.202 6379

#哨兵配置完成

-测试哨兵的故障切换

******(1)把master服务器在开启一个终端,在新开启的终端中关闭redis,测试是否可以主从切换
[root@master ~]# /etc/init.d/redis stop 
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped

******(2)切换到开启哨兵的终端,查看新弹出的信息
1129:X 09 Jun 2021 18:20:36.588 # +failover-end master mymaster 192.168.100.202 6379
1129:X 09 Jun 2021 18:20:36.588 # +switch-master mymaster 192.168.100.202 6379 192.168.100.203 6379
1129:X 09 Jun 2021 18:20:36.588 * +slave slave 192.168.100.204:6379 192.168.100.204 6379 @ mymaster 192.168.100.203 6379  #发现主服务器变成了203
1129:X 09 Jun 2021 18:20:36.588 * +slave slave 192.168.100.202:6379 192.168.100.202 6379 @ mymaster 192.168.100.203 6379
1129:X 09 Jun 2021 18:20:39.607 # +sdown slave 192.168.100.202:6379 192.168.100.202 6379 @ mymaster 192.168.100.203 6379‘

******(3)在203上测试主从复制是否可以正常同步
[root@slave1 ~]# redis-cli -h 192.168.100.203 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.203:6379> keys *
1) "aaa"
2) "bbb"
192.168.100.203:6379> set yyy aaa
OK
192.168.100.203:6379> keys *
1) "yyy"
2) "aaa"
3) "bbb"

[root@slave2 redis-5.0.4]# redis-cli -h 192.168.100.204 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.204:6379> keys *  #发现同步成功
1) "yyy"
2) "bbb"
3) "aaa"

******(4)此时重新开启202的redis,并且查看哨兵的提示消息
[root@master ~]# /etc/init.d/redis start 
Starting Redis server...
1167:C 09 Jun 2021 18:23:39.756 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1167:C 09 Jun 2021 18:23:39.756 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1167, just started
1167:C 09 Jun 2021 18:23:39.756 # Configuration loaded
Redis is running...

1129:X 09 Jun 2021 18:23:50.324 * +convert-to-slave slave 192.168.100.202:6379 192.168.100.202 6379 @ mymaster 192.168.100.203 6379   #提示增加了一台slave

******(5)在202的新终端上查看redis的数据是否成功同步
[root@master ~]# redis-cli -h 192.168.100.202 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.100.202:6379> keys *  #发现已经成功同步
1) "bbb"
2) "aaa"
3) "yyy"

#测试故障切换缓存,发现在master主机出现故障然后重新连接到集群后,master角色不会进行转移

-哨兵日志分析

#把哨兵放在前台运行时,日志信息会直接输出到终端上,放到后台运行时,日志会写到指定的路径中
+reset-master <instance details>   #当master被重置时.
+slave <instance details>  #当检测到一个slave并添加进slave列表时.
+failover-state-reconf-slaves <instance details> #Failover状态变为reconf-slaves状态时
+failover-detected <instance details> #当failover发生时
+slave-reconf-sent <instance details> #sentinel发送SLAVEOF命令把它重新配置时
+slave-reconf-inprog <instance details> #slave被重新配置为另外一个master的slave,但数据复制还未发生时。
+slave-reconf-done <instance details> #slave被重新配置为另外一个master的slave并且数据复制已经与master同步时。
-dup-sentinel <instance details> #删除指定master上的冗余sentinel时,当一个sentinel重新启动时,可能会发生这个事件
+sentinel <instance details> #当master增加了一个sentinel时。
+sdown <instance details> #进入SDOWN状态时;
-sdown <instance details> #离开SDOWN状态时。
+odown <instance details> #进入ODOWN状态时。
-odown <instance details> #离开ODOWN状态时。
+new-epoch <instance details>  #当前配置版本被更新时。
+try-failover <instance details> #达到failover条件,正等待其他sentinel的选举。
+elected-leader <instance details> #被选举为去执行failover的时候。
+failover-state-select-slave <instance details> #开始要选择一个slave当选新master时。
no-good-slave <instance details> #没有合适的slave来担当新master
selected-slave <instance details> #找到了一个适合的slave来担当新master
failover-state-send-slaveof-noone <instance details> #当把选择为新master的slave的身份进行切换的时候。
failover-end-for-timeout <instance details>   #failover由于超时而失败时。
failover-end <instance details> #failover成功完成时。
switch-master <master name> <oldip> <oldport> <newip> <newport> #当master的地址发生变化时。通常这是客户端最感兴趣的消息了。
+tilt #进入Tilt模式。
-tilt #退出Tilt模式。

到此这篇关于Redis sentinel哨兵集群的实现步骤的文章就介绍到这了,更多相关Redis sentinel哨兵集群内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Redis 相关文章推荐
浅谈Redis在直播场景的实践方案
Apr 27 Redis
基于Redis位图实现用户签到功能
May 08 Redis
详解Redis瘦身指南
May 26 Redis
比较几种Redis集群方案
Jun 21 Redis
Jedis操作Redis实现模拟验证码发送功能
Sep 25 Redis
redis中lua脚本使用教程
Nov 01 Redis
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
Mar 16 Redis
Redis实战高并发之扣减库存项目
Apr 14 Redis
Redis基本数据类型哈希Hash常用操作命令
Jun 01 Redis
Redis实现短信验证码登录的示例代码
Jun 14 Redis
Redis实现主从复制方式(Master&Slave)
Jun 21 Redis
Redis唯一ID生成器的实现
Jul 07 #Redis
Redis+AOP+自定义注解实现限流
Jun 28 #Redis
利用Redis实现点赞功能的示例代码
Jun 28 #Redis
一文教你快速生成MySQL数据库关系图
Jun 28 #Redis
Redis实现主从复制方式(Master&Slave)
Jun 21 #Redis
浅谈Redis变慢的原因及排查方法
使用Redis实现分布式锁的方法
Jun 16 #Redis
You might like
PHP的一个完整SMTP类(解决邮件服务器需要验证时的问题)
2006/10/09 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十)
2014/06/24 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
Windows Live的@live.com域名注册漏洞 利用代码
2006/12/27 Javascript
vs2003 js文件编码问题的解决方法
2010/03/20 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
jQuery悬停文字提示框插件jquery.tooltipster.js用法示例【附demo源码下载】
2016/07/19 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
2017/03/14 Javascript
Vue引用Swiper4插件无法重写分页器样式的解决方法
2018/09/27 Javascript
es6 filter() 数组过滤方法总结
2019/04/03 Javascript
防止Layui form表单重复提交的实现方法
2019/09/10 Javascript
Vue触发input选取文件点击事件操作
2020/08/07 Javascript
[55:26]DOTA2-DPC中国联赛 正赛 Aster vs LBZS BO3 第一场 2月23日
2021/03/11 DOTA
浅析Python中的getattr(),setattr(),delattr(),hasattr()
2016/06/14 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
使用Python在Windows下获取USB PID&amp;VID的方法
2019/07/02 Python
python实现列表中最大最小值输出的示例
2019/07/09 Python
Python json读写方式和字典相互转化
2020/04/18 Python
一款利用纯css3实现的360度翻转按钮的实例教程
2014/11/05 HTML / CSS
科沃斯机器人官网商城:Ecovacs
2016/08/29 全球购物
John Hardy官方网站:手工设计首饰的奢侈品牌
2017/07/05 全球购物
Giglio美国站:意大利奢侈品购物网
2018/02/10 全球购物
精致的手工皮鞋:Shoe Embassy
2019/11/08 全球购物
蒂娜商店:Tiina the Store
2019/12/07 全球购物
C语言怎样定义和声明全局变量和函数最好
2013/11/26 面试题
什么是会话Bean
2015/05/14 面试题
电厂职工自我鉴定
2014/02/20 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
单位租车协议书
2015/01/29 职场文书
中秋节随笔
2015/08/15 职场文书
深入解析NumPy中的Broadcasting广播机制
2021/05/30 Python
Python爬虫基础初探selenium
2021/05/31 Python
Go 语言结构实例分析
2021/07/04 Golang
2022年四月新番
2022/03/15 日漫
草系十大最强宝可梦,纸片人上榜,榜首大家最熟悉
2022/03/18 日漫
Python 第三方库 openpyxl 的安装过程
2022/12/24 Python