Redis简介
Redis:开源、免费、高性能、K-V数据库、内存数据库、非关系型数据库,支持持久化、集群和事务
REDIS安装及配置
- 用docker运行Redis
docker pull redis
docker run -d --name redis -p 6379:6379 redis
docker exec -it redis redis-cli
- Linux安装
确保Linux已经安装gcc
下载Redis wget http://download.redis.io/releases/redis-4.0.1.tar.gz
解压 tar -zxvf redis-4.0.1.tar.gz
进入目录后编译 cd redis-4.0.1 make MALLOC=libc
安装 make PREFIX=/usr/local/redis install #指定安装目录为/usr/local/redis
启动 /usr/local/redis/bin/redis-server
- Redis配置
进入解压的Redis目录,将redis.conf复制到安装文件的目录下 cp redis.conf /usr/local/redis
启动自定义配置的Redis/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf配置详解
- daemonize : 默认为no,修改为yes启用守护线程
- port :设定端口号,默认为6379
- bind :绑定IP地址
- databases :数据库数量,默认16
- save <second> <changes> :指定多少时间、有多少次更新操作,就将数据同步到数据文件
#redis默认配置有三个条件,满足一个即进行持久化
save 900 1 #900s有1个更改
save 300 10 #300s有10个更改
save 60 10000 #60s有10000更改
- dbfilename :指定本地数据库的文件名,默认为dump.rdb
- dir :指定本地数据库的存放目录,默认为./当前文件夹
- requirepass :设置密码,默认关闭
redis -cli -h host -p port -a passwordRedis关闭
- 使用kill命令 (非正常关闭,数据易丢失)
ps -ef|grep -i redis
kill -9 PID
- 正常关闭
redis-cli shutdown
REDIS常用命令
Redis五种数据类型:string、hash、list、set、zset
公用命令
DEL key
DUMP key:序列化给定key,返回被序列化的值
EXISTS key:检查key是否存在
EXPIRE key second:为key设定过期时间
TTL key:返回key剩余时间
PERSIST key:移除key的过期时间,key将持久保存
KEY pattern:查询所有符号给定模式的key
RANDOM key:随机返回一个key
RANAME key newkey:修改key的名称
MOVE key db:移动key至指定数据库中
TYPE key:返回key所储存的值的类型
EXPIRE key second的使用场景:
1、限时的优惠活动
2、网站数据缓存
3、手机验证码
4、限制网站访客频率
KEY的命名建议
- key不要太长,尽量不要超过1024字节。不仅消耗内存,也会降低查找的效率
- key不要太短,太短可读性会降低
- 在一个项目中,key最好使用统一的命名模式,如user:123:password
- key区分大小写
STRING
string类型是二进制安全的,redis的string可以包含任何数据,如图像、序列化对象。一个键最多能存储512MB。二进制安全是指,在传输数据的时候,能保证二进制数据的信息安全,也就是不会被篡改、破译;如果被攻击,能够及时检测出来
setkey_name value:命令不区分大小写,但是key_name区分大小写
SETNX key value:当key不存在时设置key的值。(SET if Not eXists)
get key_name
GETRANGE key start end:获取key中字符串的子字符串,从start开始,end结束
MGET key1 [key2 …]:获取多个key
GETSET KEY_NAME VALUE:设定key的值,并返回key的旧值。当key不存在,返回nil
STRLEN key:返回key所存储的字符串的长度
INCR KEY_NAME :INCR命令key中存储的值+1,如果不存在key,则key中的值话先被初始化为0再加1
INCRBY KEY_NAME 增量
DECR KEY_NAME:key中的值自减一
DECRBY KEY_NAME append key_name value:字符串拼接,追加至末尾,如果不存在,为其赋值(注意这些key对应的必须是数字类型字符串,否则会出错)
String应用场景:
1、String通常用于保存单个字符串或JSON字符串数据
2、因为String是二进制安全的,所以可以把保密要求高的图片文件内容作为字符串来存储
3、计数器:常规Key-Value缓存应用,如微博数、粉丝数。INCR本身就具有原子性特性,所以不会有线程安全问题
HASH
Redis hash是一个string类型的field和value的映射表,hash特别适用于存储对象。每个hash可以存储232-1键值对。可以看成KEY和VALUE的MAP容器。相比于JSON,hash占用很少的内存空间。
常用命令
- HSET key_name field value:为指定的key设定field和value
- hmset key field value[field1,value1]
- hget key field
- hmget key field[field1]
- hgetall key:返回hash表中所有字段和值
- hkeys key:获取hash表所有字段
- hlen key:获取hash表中的字段数量 -hdel key field [field1]:删除一个或多个hash表的字段
其他命令
- hsetnx key field value: 只有在字段field不存在时,设置哈希表字段的值
- hincrby key field increment: 为哈希表key中的指定字段的整数值加上增量increment.
- hincrbyfloat key field increment: 为哈希表key中的指定字段的浮点数值加上增量increment.
- hexists key field: 查看哈希表key中,指定的字段是否存在
应用场景
Hash的应用场景,通常用来存储一个用户信息的对象数据。
1、相比于存储对象的string类型的json串,json串修改单个属性需要将整个值取出来。而hash不需要。
2、相比于多个key-value存储对象,hash节省了很多内存空间
3、如果hash的属性值被删除完,那么hash的key也会被redis删除
LIST
类似于Java中的LinkedList。
常用命令
lpush key value1 [value2]
rpush key value1 [value2]
lpushx key value:从左侧插入值,如果list不存在,则不操作
rpushx key value:从右侧插入值,如果list不存在,则不操作
llen key:获取列表长度
lindex key index:获取指定索引的元素
lrange key start stop:获取列表指定范围的元素
lpop key :从左侧移除第一个元素
rpop key:移除列表最后一个元素
blpop key [key1] timeout:移除并获取列表第一个元素,如果列表没有元素会阻塞列表到等待超时或发现可弹出元素为止
brpop key [key1] timeout:移除并获取列表最后一个元素,如果列表没有元素会阻塞列表到等待超时或发现可弹出元素为止
ltrim key start stop :对列表进行修改,让列表只保留指定区间的元素,不在指定区间的元素就会被删除
lset key index value :指定索引的值
linsert key before|after world value:在列表元素前或则后插入元素
应用场景
1. 对数据大的集合数据删减
列表显示、关注列表、粉丝列表、留言评价...分页、热点新闻等
2. 任务队列
list通常用来实现一个消息队列,而且可以确保先后顺序,不必像MySQL那样通过order by来排序
补充:
rpoplpush list1 list2 移除list1最后一个元素,并将该元素添加到list2的左侧,并返回此元素 用此命令可以实现订单下单流程、用户系统登录注册短信等。
lrange list1 0 -1 查询所有列表中的数据
lindex list1 -1 查询倒数第一个数据
brpoplpush list1 list2 timeout 移除list1最后一个元素,并将该元素添加到list2的左侧,并返回此元 素;如果列表没有元素会阻塞列表到等待超时或发现可弹出元素为止
SET
set是String类型的无序集合;集合成员唯一
sadd key value1[value2]:向集合添加成员
scard key:返回集合成员数
smembers key:返回集合中所有成员
sismember key member:判断memeber元素是否是集合key成员的成员
srandmember key [count]:返回集合中一个或多个随机数
srem key member1 [member2]:移除集合中一个或多个成员
spop key:移除并返回集合中的一个随机元素
smove source destination member:将member元素从source集合移动到destination集合
sdiff key1 [key2]:返回所有集合的差集
sdiffstore destination key1[key2]:返回给定所有集合的差集并存储在destination中
应用场景
对两个集合间的数据[计算]进行交集、并集、差集运算
1、以非常方便的实现如共同关注、共同喜好、二度好友等功能。对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存储到一个新的集合中。
2、利用唯一性,可以统计访问网站的所有独立 IP
ZSET
有序且不重复。每个元素都会关联一个double类型的分数,Redis通过分数进行从小到大的排序。分数可以重复
ZADD key score1 memeber1
ZCARD key :获取集合中的元素数量
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
ZRANK key member:返回有序集合指定成员的索引
zrange key start stop: 通过索引区间返回有序集合指定区间的成员,分数从低到高
zrangebyscore key min max: 通过分数返回有序集合指定区间内的成员
ZREVRANGE key start stop :返回有序集中指定区间内的成员,通过索引,分数从高到底
zrevrangebyscore key max min: 返回有序集中指定分数区间内的成员,分数从高到底ZREM key member [member …] 移除有序集合中的一个或多个成员ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员(第一名是0)(低到高排序)ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员zincrby key increment member: 增加member元素的分数increment,返回值是更改后的分数
应用场景
常用于排行榜:
1、如推特可以以发表时间作为score来存储
2、存储成绩
3、还可以用zset来做带权重的队列,让重要的任务先执行
HYPERLOGLOG
Redis HyperLoglog 是用来做基数统计的算法
pfadd key element [element …] :添加指定元素到HyperLoglog中
pfcount key [key …]:返回给定HyperLoglog的基数估算值
pfmerge destkey sourcekey [sourcekey …]:将多个Hyper合并为一个HyperLoglog
应用场景
基数不大,数据量不大就用不上,会有点大材小用浪费空间;有局限性,就是只能统计基数数量,而没办法去指导具体的内容是什么
统计注册IP数
统计每日访问IP数
统计页面实时UV数
统计在线用户数
统计用户每天搜索不同词条的个数
统计真实文章阅读数
JEDIS和SPRING-DATA-REDIS
- 连接redis
@Test
public void test(){
Jedis jedis = new Jedis("host",port);
jedis.auth("password");
// 操作redis
jedis.close();
}
- JedisPool
// 创建config
JedisPoolConfig config = new JedisPoolConfig();
con.setMaxTotal(5);// 最大连接数
...
// 创建连接池
JedisPool pool = new JedisPool(config,host,port);
Jedis jedis = pool.getResource();
jedis.auth();
jedis.close();
SPRING-DATA
- 导入Jedis和Spring-data-redis 配置文件如下
server:
port: 8081
spring:
redis:
host: 192.168.1.110
password: 123456
port: 6379
lettuce:
pool:
max-active: 8 #最大连接数
max-idle: 8 #最大空闲数
min-idle: 0 #最小空闲数
shutdown-timeout: 100 #连接超时
database: 0
- 测试连接
配置序列化方法:
把任何数据保存到redis中,都需要经过序列化,默认使用JdkSerializationRedisSerializer进行序列化。JdkSerializationRedisSerializer会对所有的key和value还有hashkey和hashvalue的原始字符前,都加了一串字符串。
REDIS功能特性
发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
常用命令
subscribe channel [channel…]:订阅一个或多个频道的信息
psubscribe pattern [pattern…]:订阅一个或多个符合规定模式的频道
publish channel message :将信息发送到指定频道
unsubscribe [channel[channel…]]:退订频道
punsubscribe [pattern[pattern…]]:退订所有给定模式的频道
应用场景
构建实时的消息系统,比如普通聊天、群聊等功能。
1、博客网站订阅,当作者发布就可以推送给粉丝
2、微信公众号模式
REDIS多数据库
常用命令
select db # 数据库的切换
move key db # 移动数据(将当前key移动到另一个库)
flushdb #清空当前数据库的所有key
flushall #清空整个Redis的数据库所有key
REDIS 事务
Redis事务可以一次执行多个命令,(按顺序地串行化执行,执行过程中不允许其他命令插入执行序列中)。
- Redis会将一个事务中的所有命令序列化,然后按顺序执行
- 执行中不会被其他命令插入,不允许加塞行为
常用命令
discard:取消事务,放弃执行事务块内的所有命令。
exec:执行所有事务块内的命令。
multi:标记一个事务的开始
unwatch:取消watch命令对所有key的监视
watch key [key…]:监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
实例:
重点补充
输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行
直到输入exec后,Redis会将之前队列中的命令依次执行
discard放弃队列执行
如果某个命令报出错,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
如果队列中某个命令出现报告错误(语法错误),执行时整个队列都会被取消
应用场景
一组命令必须同时都执行,或者都不执行。
我们想要保证一组命令在执行的过程之中不被其他命令插入
REDIS持久化
RDB
RDB是Redis默认持久化机制。RDB相当于快照,保存的是一种状态
- 优点:保存速度、还原速度极快适用于灾难备份
- 缺点:小内存的机器不符合使用。RDB机制符合要求就会快照。
#redis默认配置有三个条件,满足一个即进行持久化
save 900 1 #900s有1个更改
save 300 10 #300s有10个更改
save 60 10000 #60s有10000更改
AOF
如果Redis意外down掉,RDB方式会丢失最后一次快照后的所有修改。如果要求应用不能丢失任何修改,可以采用AOF持久化方式。 AOF(Append-Only File):Redis会将没一个收到写命令都追加到文件中(默认是appendonly.aof)。当Redis重启时会通过重新执行文件中的写命令重建整个数据库的内容。
- 产生的问题: 有些命令是多余的。
总结
穿透
缓存穿透是查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透
- 解决办法
持久层查询不到就缓存空结果(eg:redis.set(key, "null"),查询时先判断缓存中是否exists(key),如果有直接返回空,没有则查询后返回,注意insert时需要清除查询时的key,否则即便DB中有值也查询不到(当然也可以设置空缓存的过期时间)
雪崩
缓存大量失效的时候,引发大量查询数据库
- 解决办法
- 用锁/分布式锁或者队列串行访问
- 缓存失效事件均匀分布
热点key
某个key访问非常频繁,当key失效的时候有大量的线程来构建缓存,导致负载增加,系统崩溃
- 解决办法
1.使用锁,单机用synchronized, lock等,分布式用分布式锁
2.缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。
3.在value设置一个比过期时间t0小的过期时间t1,当t1过期的时候,延长t1并做更新缓存操作。
4.设置标签缓存,标签缓存设置过期时间,标签缓存设置过期时间,标签缓存过期后,需异步的更新实际缓存
REDIS主从复制
一个Redis服务可以有多个该服务的复制品,这个Redis服务称为Master,其他复制称为Slaves
好处:
读写分离不仅可以提高服务器的负载能力,并且可以根据请求的规模自由增加或者减少从库的数量。数据被复制成了好几份就算有一台机器出现故障,也可以使用其他机器的数据快速回复。在redis主从模式中,一台主库可以有多个从库,但一个从库只能隶属一个主库
Redis主从复制配置
- 主数据库中不需要任何配置,创建一个从数据库:
redis.conf(配置文件信息)
-- port 6380 #从服务的端口号
-- slaveof 127.0.0.1 6379 #指定主服务器
- 启动从数据库:
./bin/redis-server ./redis.conf --port 6380 --slaveof 127.0.0.1 6379
加上slaveof参数启动另一个Redis实例作为从库,并且监听6380端口
- 登录到从服务客户端
./bin/redis-cli -p 6380 -a 123456
命令:
变回主库: slaveof no one #不是任何库的从库
变回从库: slaveof ip地址 端口号
哨兵模式
Redis-Sentinel 哨兵模式是高可用解决方案,当redis在做master-slave的高可用方案时,加入master宕机了,redis本身(以及很多客户端)都没有实现自动进行主备切换,而redis-sentinel本身是独立运行的进程,可以部署在其他与redis集群可通讯的机器中监控redis集群。哨兵监控Reis系统的运行状况
哨兵模式的特点
- 不时地监控redi s是否按照预期良好地运行;
- 如果发现某个redis节点运行出现状况,能够通知另外-一个进程(例如它的客户端)
- 能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave (如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址
- 哨兵为客户端提供服务发现,客户端链接哨兵,哨兵提供当前master的地址然后提供服务,如果出现切换,也就是master挂了,哨兵会提供客户端一个新地址。
REDIS CLUSTER集群
为了在大数据访问下提供稳定的业务,集群化是存储的必然形态
未来的发展趋势肯定是云计算和大数据的紧密结合
只有分布式架构能满足要求
Redis集群搭建的方式有很多种,但从redis3.0之后版本支持redis-cluster集群,至少需要3(Master)+3(Slave)才能建立集群。Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。其redis-cluster架构图如下所示:
Redis-Cluster集群节点最小配置6个节点以上(3主3从),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。
Redis-Cluster集群特点
所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
节点的fail是通过集群中超过半数的节点检测失效时才生效。
客户端与redis节点直连,不需要中间proxy层. 客户端不需要连接集群所有节点, 连接集群中任何一个可用节点即可。
redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配) ,cluster负责维护
Redis集群预分好16384个哈希槽,当需要在 Redis集群中放置一个 key-value时,redis 先对key使用crc16算法算出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在 0-16383之间的哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同的节
Redis-Cluster容错
容错性,是指软件检测应用程序所运行的软件或硬件中发生的错误并从错误中恢复的能力,通常可以从系统的可靠性、可用性、可测性等几个方面来衡量。
1. 什么时候判断master不可用?
投票机制。投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉.s
2. 什么时候整个集群不可用(cluster_state:fail)?
如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态.如果集群超过半数以上master挂掉,无论是否有slave ,集群进入fail状态.
Redis Cluster节点分配
Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~ 16383个整数槽内,每个节负责维护一部分槽以及槽所映射的键值数据。
三个主节点分别是:A, B, C三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽(hash slot)的方式来分配16384个slot的话,它们三个节点分别承担的slot区间是
节点A要盖 0- 5460;
节点B覆盖 5461 - 10922;
节点C覆盖 10923 - 16383
REDIS CLUSTER集群搭建
集群搭建参考官网: https://redis.io/topics/cluster-tutorial redis集群需要至少要三个master节点,我们这里搭建三个master节点,并且给每个master再搭建一个slave节点,总共6个redis节点,这里用一台机器(可以多台机器部署,修改一下ip地址就可以了 )部署6个redis实例。三主三从,搭建集群(只适用Redis5以上)的步骤如下:
- 创建Redis节点安装目录
mkdir -p /usr/loca1/redis_cluster #指定目录下创建redis_ cluster
- 在redis_cluster目录下,创建7000-7005个文件夹
mkdir 7000 7001 7002 7003 7004 7005
- 并将redis-conf分别拷贝到7000-7005文件夹
cp /opt/redis-5 .0.4/redis. conf ./7000
- 修改Redis配置文件 /usr/local/redis_ cluster/7000/redis.conf
#关闭保护模式用于公网访问
protected-mode no
port 7000
#开启集群模式
cluster-ensbled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
#后台启动
daemonize yes
pidfile /var/run/redis_7000.pid
logfile "7000.log"
#dir /redis/data
#此处绑定ip可以是阿里内网ip和本地ip也可以直接注释掉该项
#bind 127.0.0.1
#用于连接主节点密码
masterauth 123456
#设置redis密码各个节点请保持密码一一致
requirepass 123456
- 依次复制并修改6个redis.conf
cp ./7000/redis.conf ./7001/ #依次进行复制
vim ./7001/redis.conf #执行%s/o1d/new/g全部替换
- 依次启动6个节点
# 将安装的redis目录下的src复制到cluster下,方便启动服务端
cd /opt/redis-5.0.0 : 进入redis安装目录
cp -r ./src/ /usr/1oca1/redis_cluster/ :将src文件复制到redis_cluster目录中
./src/redis-server ./7000/redis.conf
./src/redis-server ./7001/redis.conf
./src/redis-server ./7002/redis.conf
./src/redis-server ./7003/redis.conf
./src/redis-server ./7004/redis.conf
./src/redis-server ./7005/redis.conf
启动后,可以用PS查看进程:
ps -ef | grep -i redis
- 创建集群 Redis 5版本后通过redis-cli 客户端命令来创建集群。
./src/redis-cli --cluster create -a 123456 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
Redis Cluster集群验证
在某台机器上(或)连接集群的7001端口的节点:
redis-cli -h 127.0.0.1 -C -p 7000 -a 123456 #加参数 -C可连接到集群
redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都 是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点 ,就可以获取到其他节点的数据
Redis Cluster关闭集群
- 开启全部redis节点redisall.sh
/usr/1ocal/redis_cluster/src/redis-server ./7000/redis.conf
/usr/1ocal/redis_cluster/src/redis-server ./7001/redis.conf
/usr/local/redis_cluster/src/redis-server ./7002/redis.conf
/usr/local/redis_cluster/src/redis-server ./7003/redis.conf
/usr/1ocal/redis_cluster/src/redis-server ./7004/redis.conf
/usr/1ocal/redis_cluster/src/redis-server ./7005/redis.conf
chmod u+x redisall.sh #执行将redisall.sh变成可执行文件
./redisall.sh #在当前目录下启动
启动集群 vim starall.sh追加如下内容: (记得改自己ip地址和密码)
/usr/loca1/redis_cluster/src/redis-cli --cluster create -a 123456 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
关闭集群 /usr/local/redis_ cluster目录下编写脚本文件: vim shutdown.sh 内容如下:
/usr/1ocal/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7000 -a 123456 shut down
/usr/1ocal/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7001 -a 123456 shut down
/usr/1ocal/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7002 -a 123456 shut down
/usr/local/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7003 -a 123456 shut down
/usr/local/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7004 -a 123456 shut down
/usr/1ocal/redis_cluster/src/redis-cli -C -h 127.0.0.1 -p 7005 -a 123456 shut down
chmod u+x shutdown.sh #然后执行将shutdown.sh变成可执行文件
./shutdown.sh #在当前目录下启动
查看:ps aux | grep redis
官方: /usr/1oca1/redis_cluster/redis-cli -a xxx -c -h 192.168.5.100 -p 8001
提示: -a访问服务端密码,-c表示集群模式,-h指定ip地址,-p指定端口号