赞
踩
Redis 是一个使用 ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对(key-value)存储数据库。从2015年6月开始,Redis的开发由 Redis Labs 赞助,而2013年5月至2015年6月期间,其开发由Pivotal赞助。在2013年5月之前,其开发由VMware赞助。根据月度排行网站DB-Engines.com的数据显示,Redis是最流行的键值对存储数据库。
1、Memcached
2、Redis
3、Tair
1、安装 redis-rpm源
[root@localhost ~]# yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
2、安装 Redis
[root@localhost ~]# yum --enablerepo=remi install redis
3、开机自启 Redis
[root@localhost ~]# systemctl enable redis
4、设置redis.conf
允许远程登录: bind 127.0.0.1 改为 bind 0.0.0.0 (可选)
[root@localhost ~]# vim /etc/redis.conf
1、编译安装 Redis
[root@localhost ~]# wget http://download.redis.io/releases/redis-5.0.5.tar.gz [root@localhost ~]# tar -zxvf redis-5.0.5.tar.gz -C /usr/local [root@localhost ~]# yum install gcc -y # gcc -v查看,如果没有需要安装 [root@localhost ~]# cd /usr/local/redis-5.0.5 [root@localhost redis-5.0.5]# make MALLOC=lib [root@localhost redis-5.0.5]# cd src && make all [root@localhost src]# make install
2、启动 Redis 实例
[root@localhost src]# ./redis-server 21522:C 17 Jun 2019 15:36:52.038 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21522:C 17 Jun 2019 15:36:52.038 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=21522, just started 21522:C 17 Jun 2019 15:36:52.038 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.5 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 21522 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 出现以上界面说明安装成功 [root@localhost src]# ./redis-cli --version # 查询是安装的5.0版本的redis redis-cli 5.0.5 [root@localhost src]# ./redis-server --version Redis server v=5.0.5 sha=00000000:0 malloc=libc bits=64 build=4db47e2324dd3c5
1、开启 Redis 服务守护进程
# 以./redis-server 启动方式,需要一直打开窗口,不能进行其他操作,不太方便,以后台进程方式启动 redis [root@localhost src]# vim /usr/local/redis-5.0.5/redis.conf # 默认安装好的配置文件并不在这个目录下,需要找到复制到该目录下 daemonize no 改为 daemonize yes # 以守护进程运行 [root@localhost src]# ./redis-server /usr/local/redis-5.0.5/redis.conf 21845:C 17 Jun 2019 15:44:14.129 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21845:C 17 Jun 2019 15:44:14.129 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=21845, just started 21845:C 17 Jun 2019 15:44:14.129 # Configuration loaded
2、关闭redis进程
[root@localhost src]# ps -ef|grep redis root 21846 1 0 15:44 ? 00:00:00 ./redis-server 127.0.0.1:6379 root 22042 6950 0 15:46 pts/1 00:00:00 grep --color=auto redis [root@localhost src]# kill -9 21846 # 此方法启动关闭较为麻烦,且不能设置开机自启动
1、编辑Redis 配置文件
# 先编辑配置文件,然后在把配置文件拷贝到/etc/redis下 [root@localhost ~]# vim /usr/local/redis-5.0.5/redis.conf #bind 127.0.0.1 # 将bind 127.0.0.1注释掉,否则数据库只有本机能够使用 或者 修改为 0.0.0.0 daemonize yes # 将no改为yes,使数据库能够以后台守护进程运行 protected-mode no # 把保护模式的yes改为no,否则会阻止远程访问 requirepass redis # 打开注释,设置密码 [root@localhost ~]# cp /root/redis-5.0.5/redis.conf /etc/redis/
2、添加 Redis 系统启动
# 开机自启动,将redis的启动脚本复制一份放到/etc/init.d目录下 [root@localhost ~]# cp /usr/local/redis-5.0.5/utils/redis_init_script /etc/init.d/redis [root@localhost ~]# vim /etc/init.d/redis CONF="/usr/local/redis-5.0.5/redis.conf" # 将conf的变量修改下,否则读不到配置文件 [root@localhost ~]# cd /etc/init.d [root@localhost init.d]# chkconfig redis on # 通过 systemctl 管理 redis [root@localhost ~]# systemctl start redis [root@localhost ~]# systemctl status redis ● redis.service - LSB: Redis data structure server Loaded: loaded (/etc/rc.d/init.d/redis; bad; vendor preset: disabled) Active: active (running) since Mon 2019-06-24 11:10:48 CST; 54s ago Docs: man:systemd-sysv-generator(8) Process: 3184 ExecStop=/etc/rc.d/init.d/redis stop (code=exited, status=0/SUCCESS) Process: 3187 ExecStart=/etc/rc.d/init.d/redis start (code=exited, status=0/SUCCESS) CGroup: /system.slice/redis.service └─3189 /usr/local/bin/redis-server *:6379 Jun 24 11:10:48 test systemd[1]: Starting LSB: Redis data structure server... Jun 24 11:10:48 test redis[3187]: Starting Redis server... Jun 24 11:10:48 test redis[3187]: 3188:C 24 Jun 2019 11:10:48.203 # oO0OoO0OoO0Oo R...0Oo Jun 24 11:10:48 test redis[3187]: 3188:C 24 Jun 2019 11:10:48.203 # Redis version=5...ted Jun 24 11:10:48 test redis[3187]: 3188:C 24 Jun 2019 11:10:48.203 # Configuration loaded Jun 24 11:10:48 test systemd[1]: Started LSB: Redis data structure server. Hint: Some lines were ellipsized, use -l to show in full.
注意:本次多实例配置基于单实例配置完成后
1、创建程序目录
[root@localhost ~]# mkdir /application/redis -p [root@localhost ~]# cd /application/redis/
2、修改配置文件
[root@localhost redis]# vim install-redis.sh #!/bin/bash for i in 0 1 2 3 do # 创建多实例(端口命名)目录 mkdir -p 638$i # 复制启动程序到各实例 \cp /usr/local/redis-5.0.5/src/redis-server /application/redis/638$i/ # 复制配置文件。注意:此处基于单实例配置完成 \cp /usr/local/redis-5.0.5/redis.conf /application/redis/638$i/ # 修改程序存储目录 sed -i "s#^dir .*#dir /application/redis/638$i/#g" /application/redis/638$i/redis.conf # 修改其他端口信息 sed -i "s#6379#638$i#g" /application/redis/638$i/redis.conf # 允许远程连接redis sed -i '/protected-mode/s#yes#no#g' /application/redis/638$i/redis.conf done
3、启动实例
[root@localhost redis]# vim start-redis.sh #!/bin/bash for i in 0 1 2 3 do /application/redis/638$i/redis-server /application/redis/638$i/redis.conf done
4、连接 redis
[root@localhost redis]# redis-cli -h 192.168.152.161 -p 6379 192.168.152.161:6379>
1、是否后台运行
daemonize no/yes
2、默认端口
port 6379
3、AOF 日志开关是否打开
appendonly no/yes
4、日志文件位置
logfile /var/log/redis.log
5、RDB 持久化数据文件
dbfilename dump.rdb
6、指定IP进行监听
bind 10.0.0.51 ip2 ip3 ip4
7、禁止protected-mode
protected-mode yes/no (保护模式,是否只允许本地访问)
8、增加requirepass {password}
requirepass root
9、在redis-cli中使用
auth {password} 进行认证
1、获取当前配置
CONFIG GET *
2、变更运行配置
CONFIG SET loglevel "notice"
3、修改密码为空
192.168.152.161:6379> config set requirepass "" 192.168.152.161:6379> exit 192.168.152.161:6379> config get dir 1) "dir" 2) "/usr/local/redis/data"
redis 提供了两种不同级别的持久化方式:一种是RDB,另一种是AOF.
1、RDB 持久化
可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
2、AOF 持久化
记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以Redis 协议的格式来保存,新命令会被追加到文件的末尾。
Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
你甚至可以关闭持久化功能,让数据只在服务器运行时存在。
1、RDB 的优点
2、RDB 的缺点
1、AOF 优点
2、AOF 缺点
在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
你也可以通过调用 SAVE或者 BGSAVE , 手动让 Redis 进行数据集保存操作。比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集: save 60 1000,这种持久化方式被称为快照 snapshotting。
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
1、Redis 调用forks. 同时拥有父进程和子进程。
2、子进程将数据集写入到一个临时 RDB 文件中。
3、当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。
只进行追加操作的文件(append-only file,AOF)
快照功能并不是非常耐久:如果 Redis 因为某些原因而造成故障停机,那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说,数据的耐久性并不是最重要的考虑因素,但是对于那些追求完全耐久能力的程序员来说,快照功能就不太适用了。
从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。
你可以通过修改配置文件来打开 AOF 功能: appendonly yes
从现在开始,每当 Redis 执行一个改变数据集的命令式(比如 SET),这个命令就会被追加到 AOF 文件的末尾。
这样的话,当 redis 重新启动时,程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的
因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。
举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令.
你可以配置 Redis 多久才将数据 fsync 到磁盘一次。有三种方式:
1、每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
2、每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
3、从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
4、推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:
Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制:
RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。
这也就是说, 无论何时, 复制 RDB 文件都是绝对安全的。
1、RDB 持久化基本配置
1、修改配置文件
save 900 1 save 300 10 save 60 10000
以上配置分别表示:
• 900秒(15分钟)内有1个更改 • 300秒(5分钟)内有10个更改 • 60秒内有10000个更改 • 当达到以上定义的配置时间时,就将内存数据持久化到磁盘。
2、RDB 持久化高级配置
stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir ./clsn/redis/data/6379
以上配置分别表示:
• 后台备份进程出错时,主进程停不停止写入? 主进程不停止容易造成数据不一致 • 导出的rdb文件是否压缩 如果rdb的大小很大的话建议这么做 • 导入rbd恢复时数据时,要不要检验rdb的完整性 验证版本是不是一致 • 导出来的rdb文件名 • rdb的放置路径
1、AOF 持久化基本配置
appendonly yes/no appendfsync always appendfsync everysec appendfsync no
以上配置分别表示:
• 是否打开aof日志功能 • 每1个命令,都立即同步到aof • 每秒写1次 • 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof.
2、AOF 持久化高级配置
no-appendfsync-on-rewrite yes/no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
以上配置分别表示:
• 正在导出rdb快照的过程中,要不要停止同步 aof • aof文件大小比起上次重写时的大小,增长率100%时重写,缺点:业务开始的时候,会重复重写多次。 • aof文件,至少超过64M时,重写
在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :
1、为最新的 dump.rdb 文件创建一个备份。
2、将备份放到一个安全的地方。
3、执行以下两条命令:
redis-cli config set appendonly yes redis-cli config set save ""
4、确保写命令会被正确地追加到 AOF 文件的末尾。
执行说明
执行的第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。 执行的第二条命令用于关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。
注意:别忘了在 redis.conf 中打开 AOF 功能! 否则的话, 服务器重启之后, 之前通过 CONFIG SET 设置的配置不会生效, 程序会按原来的配置来启动服务器。
类型 | 说明 |
String字符串 | Redis 字符串数据类型的相关命令用于管理 redis 字符串值 |
Hash哈希 | Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。 |
List列表 | Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边) 一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。 |
Set集合 | Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。 |
Sorted set有序集合 | Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。 |
1、全局 Key 操作
命令 | 含义 |
KEYS * | 查看KEY支持通配符 |
DEL | 删除给定的一个或多个key |
EXISTS | 检查是否存在 |
RENAME | 变更KEY名 |
SORT | 键值排序,有非数字时报错 |
TYPE | 返回键所存储值的类型 |
DUMP RESTORE | 序例化与反序列化 |
EXPIRE\ PEXPIRE | 以秒\毫秒设定生存时间 |
TTL\ PTTL | 以秒\毫秒为单位返回生存时间 |
PERSIST | 取消生存实现设置 |
RANDOMKEY | 返回数据库中的任意键 |
2、String(字符串)
string是redis最基本的类型,一个key对应一个value。一个键最大能存储 512MB。
命令 | 描述 |
SET key value | 设置指定 key 的值 |
GET key | 获取指定 key 的值。 |
GETRANGE key start end | 返回 key 中字符串值的子字符 |
GETSET key value | 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 |
GETBIT key offset对 key | 所储存的字符串值,获取指定偏移量上的位(bit)。 |
MGET key1 [key2..] | 获取所有(一个或多个)给定 key 的值。 |
SETBIT key offset value | 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。 |
SETEX key seconds value | 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。 |
SETNX key value | 只有在 key 不存在时设置 key 的值。 |
SETRANGE key offset value | 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。 |
STRLEN key | 返回 key 所储存的字符串值的长度。 |
MSET key value [key value ...] | 同时设置一个或多个 key-value 对。 |
MSETNX key value [key value ...] | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。 |
PSETEX key milliseconds value | 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。 |
INCR key | 将 key 中储存的数字值增一。 |
INCRBY key increment | 将 key 所储存的值加上给定的增量值(increment) 。 |
INCRBYFLOAT key increment | 将 key 所储存的值加上给定的浮点增量值(increment) 。 |
DECR key | 将 key 中储存的数字值减一。 |
DECRBY key decrementkey | 所储存的值减去给定的减量值(decrement) 。 |
APPEND key value | 如果 key 已经存在并且是一个字符串, APPEND 命令将 指定value 追加到改 key 原来的值(value)的末尾。 |
应用场景
常规计数:微博数,粉丝数等。
3、Hash(字典)
我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器。
所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储995701749 个键值对。基于 Redis 哈希表大小和最大内存限制进行的估算。但需要注意的是,实际情况下,每个 Hash 数据结构能够存储的键值对数量是受到多种因素的限制的,而且具体数量也需要根据实际情况进行评估和调整。
命令 | 描述 |
HDEL key field1 [field2] | 删除一个或多个哈希表字段 |
HEXISTS key field | 查看哈希表 key 中,指定的字段是否存在。 |
HGET key field | 获取存储在哈希表中指定字段的值。 |
HGETALL key | 获取在哈希表中指定 key 的所有字段和值 |
HINCRBY key field increment | 为哈希表 key 中的指定字段的整数值加上增量 increment 。 |
HINCRBYFLOAT key field increment | 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。 |
HKEYS key | 获取所有哈希表中的字段 |
HLEN key | 获取哈希表中字段的数量 |
HMGET key field1 [field2] | 获取所有给定字段的值 |
HMSET key field1 value1 [field2 value2 ] | 同时将多个 field-value (域-值)对设置到哈希表 key 中。 |
HSET key field value | 将哈希表 key 中的字段 field 的值设为 value 。 |
HSETNX key field value | 只有在字段 field 不存在时,设置哈希表字段的值。 |
HVALS key | 获取哈希表中所有值 |
HSCAN key cursor [MATCH pattern] [COUNT count] | 迭代哈希表中的键值对。 |
应用场景:
存储部分变更的数据,如用户信息等。
4、LIST(列表)
List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。
在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。
List中可以包含的最大元素数量是4294967295。
命令 | 描述 |
BLPOP key1 [key2 ] timeout | 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOP key1 [key2 ] timeout | 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOPLPUSH source destination timeout | 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
LINDEX key index | 通过索引获取列表中的元素 |
LINSERT key BEFORE|AFTER pivot value | 在列表的元素前或者后插入元素 |
LLEN key | 获取列表长度 |
LPOP key | 移出并获取列表的第一个元素 |
LPUSH key value1 [value2] | 将一个或多个值插入到列表头部 |
LPUSHX key value | 将一个值插入到已存在的列表头部 |
LRANGE key start stop | 获取列表指定范围内的元素 |
LREM key count value | 移除列表元素 |
LSET key index value | 通过索引设置列表元素的值 |
LTRIM key start stop | 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 |
RPOP key | 移除并获取列表最后一个元素 |
RPOPLPUSH source destination | 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
RPUSH key value1 [value2] | 在列表中添加一个或多个值 |
RPUSHX key value | 为已存在的列表添加值 |
应用场景
消息队列系统,比如sina微博
在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是做了限制不能超过5000个ID,因此获取ID的函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。
系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。
5、SET(集合)
Set类型看作为没有排序的字符集合。Set可包含的最大元素数量是4294967295。如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。
命令 | 描述 |
SADD key member1 [member2] | 向集合添加一个或多个成员 |
SCARD key | 获取集合的成员数 |
SDIFF key1 [key2] | 返回给定所有集合的差集 |
SDIFFSTORE destination key1 [key2] | 返回给定所有集合的差集并存储在 destination 中 |
SINTER key1 [key2] | 返回给定所有集合的交集 |
SINTERSTORE destination key1 [key2] | 返回给定所有集合的交集并存储在 destination 中 |
SISMEMBER key member | 判断 member 元素是否是集合 key 的成员 |
SMEMBERS key | 返回集合中的所有成员 |
SMOVE source destination member | 将 member 元素从 source 集合移动到 destination 集合 |
SPOP key | 移除并返回集合中的一个随机元素 |
SRANDMEMBER key [count] | 返回集合中一个或多个随机数 |
SREM key member1 [member2] | 移除集合中一个或多个成员 |
SUNION key1 [key2] | 返回所有给定集合的并集 |
SUNIONSTORE destination key1 [key2] | 所有给定集合的并集存储在 destination 集合中 |
SSCAN key cursor [MATCH pattern] [COUNT count] | 迭代集合中的元素 |
应用场景:
在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。
Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
6、SortedSet(有序集合)
Sorted-Sets中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。成员是唯一的,但是分数(score)却是可以重复的。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令 | 描述 |
ZADD key score1 member1 [score2 member2] | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZCARD key | 获取有序集合的成员数 |
ZCOUNT key min max | 计算在有序集合中指定区间分数的成员数 |
ZINCRBY key increment member | 有序集合中对指定成员的分数加上增量 increment |
ZINTERSTORE destination numkeys key [key ...] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
ZLEXCOUNT key min max | 在有序集合中计算指定字典区间内成员数量 |
ZRANGE key start stop [WITHSCORES] | 通过索引区间返回有序集合成指定区间内的成员 |
ZRANGEBYLEX key min max [LIMIT offset count] | 通过字典区间返回有序集合的成员 |
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] | 通过分数返回有序集合指定区间内的成员 |
ZRANK key member | 返回有序集合中指定成员的索引 |
ZREM key member [member ...] | 移除有序集合中的一个或多个成员 |
ZREMRANGEBYLEX key min max | 移除有序集合中给定的字典区间的所有成员 |
ZREMRANGEBYRANK key start stop | 移除有序集合中给定的排名区间的所有成员 |
ZREMRANGEBYSCORE key min max | 移除有序集合中给定的分数区间的所有成员 |
ZREVRANGE key start stop [WITHSCORES] | 返回有序集中指定区间内的成员,通过索引,分数从高到底 |
ZREVRANGEBYSCORE key max min [WITHSCORES] | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
ZREVRANK key member | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
ZSCORE key member | 返回有序集中,成员的分数值 |
ZUNIONSTORE destination numkeys key [key ...] | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
ZSCAN key cursor [MATCH pattern] [COUNT count] | 迭代有序集合中的元素(包括元素成员和元素分值) |
应用场景:
排行榜应用,取TOP N操作这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。
Redis发布消息通常有两种模式:
1、任务队列
顾名思义,就是“传递消息的队列”。与任务队列进行交互的实体有两类,一类是生产者(producer),另一类则是消费者(consumer)。生产者将需要处理的任务放入任务队列中,而消费者则不断地从任务独立中读入任务信息并执行。
1、任务队列的好处
1、松耦合
生产者和消费者只需按照约定的任务描述格式,进行编写代码。
2、易于扩展
多消费者模式下,消费者可以分布在多个不同的服务器中,由此降低单台服务器的负载。
其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个Channel,多个Publisher可以往多个Channel中发布消息。可以这么简单的理解:
1、发布订阅模型
1、一个Publisher,多个Subscriber模型
如下图所示,可以作为消息队列或者消息管道。
主要应用:通知、公告。
2、多个Publisher,一个Subscriber模型
可以将PubSub做成独立的HTTP接口,各应用程序作为Publisher向Channel中发送消息,Subscriber端收到消息后执行相应的业务逻辑,比如写数据库,显示等等。
主要应用:排行榜、投票、计数。
3、多个Publisher,多个Subscriber模型
故名思议,就是可以向不同的Channel中发送消息,由不同的Subscriber接收。
主要应用:群聊、聊天。
2、实践发布订阅
发布订阅实践命令
命令 | 描述 |
PUBLISH channel msg | 将信息 message 发送到指定的频道 channel |
SUBSCRIBE channel [channel ...] | 订阅频道,可以同时订阅多个频道 |
UNSUBSCRIBE [channel ...] | 取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道 |
PSUBSCRIBE pattern [pattern ...] | 订阅一个或多个符合给定模式的频道,每个模式以 作为匹配符,比如 it 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类 |
PUNSUBSCRIBE [pattern [pattern ...]] | 退订指定的规则, 如果没有参数则会退订所有规则 |
PUBSUB subcommand [argument [argument ...]] | 查看订阅与发布系统状态 |
注意:使用发布订阅模式实现的消息队列,当有客户端订阅 channel 后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须 Provider 和 Consumer 同时在线。
3、消息队列系统对比
客户端在执行订阅命令之后进入了订阅状态,只能接收 SUBSCRIBE 、PSUBSCRIBE、 UNSUBSCRIBE 、PUNSUBSCRIBE 四个命令。
开启的订阅客户端,无法收到该频道之前的消息,因为 Redis 不会对发布的消息进行持久化。
和很多专业的消息队列系统(例如Kafka、RocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择。
1、Redis 于 MySQL 对比
MySQL | Redis | |
开启 | start transaction/begin | multi |
语句 | 普通SQL | 普通命令 |
失败 | rollback 回滚 | discard 取消(不叫回滚,是队列里面的命令不执行,队列里面的任务根本就没有执行。而不是执行了也可以撤回来) |
成功 | commit | exec |
2、 Redis 事务命令
命令 | 描述 |
DISCARD | 取消事务,放弃执行事务块内的所有命令。 |
EXEC | 执行所有事务块内的命令。 |
MULTI | 标记一个事务块的开始。 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视。 |
WATCH key [key ...] | 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
1、事务执行举例
ZADD salary 2000 user1 ZADD salary 3000 user2 ZRANGE salary 0 -1 WITHSCORES MULTI ZINCRBY salary 1000 user1 ZINCRBY salary -1000 user2 EXEC
3、Redis 中事务中的锁机制
举例:我正在买票 Ticket -1 , money -100
而票只有1张, 如果在我 multi 之后,和 exec 之前, 票被别人买了,即 ticket 变成0了。
我该如何观察这种情景,并不再提交:
Redis的事务中,启用的是乐观锁,只负责监测 key 没有被改动。
4、Redis服务管理命令
命令 | 描述 |
BGREWRITEAOF | 异步执行一个 AOF(AppendOnly File) 文件重写操作 |
BGSAVE | 在后台异步保存当前数据库的数据到磁盘 |
CLIENT KILL [ip:port] [ID client-id] | 关闭客户端连接 |
CLIENT LIST | 获取连接到服务器的客户端连接列表 |
CLIENT GETNAME | 获取连接的名称 |
CLIENT PAUSE timeout | 在指定时间内终止运行来自客户端的命令 |
CLIENT SETNAME connection-name | 设置当前连接的名称 |
CLUSTER SLOTS | 获取集群节点的映射数组 |
COMMAND | 获取 Redis 命令详情数组 |
COMMAND COUNT | 获取 Redis 命令总数 |
COMMAND GETKEYS | 获取给定命令的所有键 |
TIME | 返回当前服务器时间 |
COMMAND INFO command-name [command-name ...] | 获取指定 Redis 命令描述的数组 |
CONFIG GET parameter | 获取指定配置参数的值 |
CONFIG REWRITE | 对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写 |
CONFIG SET parameter value | 修改 redis 配置参数,无需重启 |
CONFIG RESETSTAT | 重置 INFO 命令中的某些统计数据 |
DBSIZE | 返回当前数据库的 key 的数量 |
DEBUG OBJECT key | 获取 key 的调试信息 |
DEBUG SEGFAULT | 让 Redis 服务崩溃 |
FLUSHALL | 删除所有数据库的所有key |
FLUSHDB | 删除当前数据库的所有key |
INFO [section] | 获取 Redis 服务器的各种信息和统计数值 |
LASTSAVE | 返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示 |
MONITOR | 实时打印出 Redis 服务器接收到的命令,调试用 |
ROLE | 返回主从实例所属的角色 |
SAVE | 异步保存数据到硬盘 |
SHUTDOWN [NOSAVE] [SAVE] | 异步保存数据到硬盘,并关闭服务器 |
SLAVEOF host port | 将当前服务器转变为指定服务器的从属服务器(slave server) |
SLOWLOG subcommand [argument] | 管理 redis 的慢日志 |
SYNC | 用于复制功能(replication)的内部命令 |
可以通过改写 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令对它们动态地进行修改
slowlog-log-slower-than 10000 # 超过多少微秒 CONFIG SET slowlog-log-slower-than 100 CONFIG SET slowlog-max-len 1000 # 保存多少条慢日志 CONFIG GET slow* SLOWLOG GET SLOWLOG RESET
为了帮助理解主服务器关闭持久化时自动拉起的危险性,参考一下以下会导致主从服务器数据全部丢失的例子:
在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用 Sentinel 来实现 Redis 的高可用性,也是非常危险的。 因为主服务器可能拉起得非常快,以至于Sentinel 在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。
无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动拉起。
1、Redis 主从同步方式
redis 主从同步有两种方式(或者所两个阶段):全同步和部分同步。
主从刚刚连接的时候,进行全同步;全同步结束后,进行部分同步。当然,如果有需要,slave 在任何时候都可以发起全同步。
redis 策略是,无论如何,首先会尝试进行部分同步,如不成功,要求从机进行全同步,并启动 BGSAVE……BGSAVE 结束后,传输 RDB 文件;如果成功,允许从机进行部分同步,并传输积压空间中的数据。
下面这幅图,总结了主从同步的机制:
2、Redis 主从复制原理
3、Redis 命令的传播
在主从服务器完成同步之后,主服务器每执行一个写命令,它都会将被执行的写命令发送给从服务器执行,这个操作被称为“命令传播”(command propagate)。
命令传播是一个持续的过程:只要复制仍在继续,命令传播就会一直进行,使得主从服务器的状态可以一直保持一致。
在 Redis 2.8 版本之前, 断线之后重连的从服务器总要执行一次完整重同步(full resynchronization)操作。
从 Redis 2.8 开始,Redis 使用 PSYNC 命令代替 SYNC 命令。PSYNC 比起 SYNC 的最大改进在于 PSYNC 实现了部分重同步(partial resync)特性:在主从服务器断线并且重新连接的时候,只要条件允许,PSYNC 可以让主服务器只向从服务器同步断线期间缺失的数据,而不用重新向从服务器同步整个数据库。
在读写分离环境下,客户端向主服务器发送写命令 SET n 10086,主服务器在执行这个写命令之后,向客户端返回回复,并将这个写命令传播给从服务器。
接到回复的客户端继续向从服务器发送读命令 GET n ,并且因为网络状态的原因,客户端的 GET命令比主服务器传播的SET 命令更快到达了从服务器。
因为从服务器键 n 的值还未被更新,所以客户端在从服务器读取到的将是一个错误(过期)的 n值。
主服务器只在有至少 N 个从服务器的情况下,才执行写操作从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。
不过, 因为 Redis 使用异步复制, 所以主服务器发送的写数据并不一定会被从服务器接收到, 因此, 数据丢失的可能性仍然是存在的。
通过以下两个参数保证数据的安全:
min-slaves-to-write <number of slaves> min-slaves-max-lag <number of seconds>
1、Redis 多实例的配置
准备两个或两个以上redis实例 [root@localhost redis]# tree . ├── 6380 │ ├── redis.conf │ └── redis-server ├── 6381 │ ├── redis.conf │ └── redis-server ├── 6382 │ ├── redis.conf │ └── redis-server ├── install-redis.sh └── start-redis.sh
2、Redis 配置文件示例
[root@localhost redis]# vim 6380/redis.conf bind 127.0.0.1 10.0.0.186 port 6380 daemonize yes pidfile /var/run/redis_6380.pid loglevel notice logfile "/var/log/redis_6380.log" dbfilename dump.rdb dir /application/redis/6380/ appendonly no appendfilename "appendonly.aof" appendfsync everysec slowlog-log-slower-than 10000 slowlog-max-len 128 protected-mode no
3、启动 Redis 实例
[root@localhost redis]# ./6380/redis-server ./6380/redis.conf [root@localhost redis]# ./6381/redis-server ./6381/redis.conf [root@localhost redis]# ./6382/redis-server ./6382/redis.conf
4、Redis 复制环境说明
主节点:6380 从节点:6381、6382
5、Redis 开启主从(在6381 6382实例中执行)
[root@localhost redis]# redis-cli -h 192.168.152.161 -p 6380 192.168.152.161:6380> slaveof 192.168.152.161 6381 OK
6、Redis 主从复制完成
官方文档:https://redis.io/docs/management/sentinel/
Redis-Sentinel 是 Redis 官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
Sentinel 是一个监视器,它可以根据被监视实例的身份和状态来判断应该执行何种动作。
1、监控(Monitoring)
Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
2、提醒(Notification)
当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
3、自动故障迁移(Automatic failover)
当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
1、发现并连接主服务器
Sentinel 通过用户给定的配置文件来发现主服务器。
Sentinel 会与被监视的主服务器创建
两个网络连接:
2、发现并连接从服务器
Sentinel 通过向主服务器发送 INFO 命令来自动获得所有从服务器的地址。
跟主服务器一样,Sentinel 会与每个被发现的从服务器创建命令连接和订阅连接。
3、发现其他 Sentinel
Sentinel 会通过命令连接向被监视的主从服务器发送 “HELLO” 信息,该消息包含Sentinel 的 IP、端口号、ID 等内容,以此来向其他 Sentinel 宣告自己的存在。与此同时Sentinel 会通过订阅连接接收其他 Sentinel 的“HELLO” 信息,以此来发现监视同一个主服务器的其他 Sentinel 。
sentinel1 通过发送HELLO 信息来让sentinel2 和 sentinel3发现自己,其他两个sentinel 也会进行类似的操作。
4、多个 Sentienl 之间的链接
Sentinel 之间只会互相创建命令连接,用于进行通信。因为已经有主从服务器作为发送和接收 HELLO 信息的中介,所以 Sentinel 之间不会创建订阅连接。
Sentinel 使用 PING 命令来检测实例的状态:如果实例在指定的时间内没有返回回复,或者返回错误的回复,那么该实例会被 Sentinel 判断为下线。
Redis 的 Sentinel 中关于下线(down)有两个不同的概念:
如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线。
一次故障转移操作由以下步骤组成:
1、创建程序目录
[root@localhost ~]# cd /application [root@localhost application]# mkdir 26380 [root@localhost application]# cp /usr/local/redis-5.0.5/src/redis-sentinel ./26380/ [root@localhost application]# cd 26380
2、编辑配置文件
[root@localhost 26380]# vim sentinel.conf port 26380 dir "/tmp" daemonize yes sentinel monitor mymaster 127.0.0.1 6380 2 sentinel down-after-milliseconds mymaster 60000 sentinel config-epoch mymaster 0
3、启动 sentinel
[root@localhost 26380]# ./redis-sentinel ./sentinel.conf
4、配置文件说明
# 指定监控master sentinel monitor mymaster 127.0.0.1 6370 2 # {2表示多少个 sentinel 同意} # 安全信息 sentinel auth-pass mymaster root # 超过15000毫秒后认为主机宕机 sentinel down-after-milliseconds mymaster 15000 # 当主从切换多久后认为主从切换失败 sentinel failover-timeout mymaster 900000 # 这两个配置后面的数量主从机需要一样,epoch为master的版本 sentinel leader-epoch mymaster 1 sentinel config-epoch mymaster 1
命令 | 描述 |
PING | 返回 PONG |
SENTINEL masters | 列出所有被监视的主服务器 |
SENTINEL slaves | |
SENTINEL get-master-addr-by-name | 返回给定名字的主服务器的 IP 地址和端口号。 |
SENTINEL reset | 重置所有名字和给定模式 pattern 相匹配的主服务器 |
SENTINEL failover | 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下,强制开始一次自动故障迁移。 |
客户端可以将 Sentinel 看作是一个只提供了订阅功能的 Redis 服务器: 你不可以使用 PUBLISH 命令向这个服务器发送信息, 但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通过订阅给定的频道来获取相应的事件提醒。
一个频道能够接收和这个频道的名字相同的事件。 比如说, 名为 +sdown 的频道就可以接收所有实例进入主观下线(SDOWN)状态的事件。
通过执行 PSUBSCRIBE * 命令可以接收所有事件信息。
以下列出的是客户端可以通过订阅来获得的频道和信息的格式:
第一个英文单词是频道/事件的名字,其余的是数据的格式。
注意, 当格式中包含 instance details 字样时, 表示频道所返回的信息中包
含了以下用于识别目标实例的内容:
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port> @ 字符之后的内容用于指定主服务器, 这些内容是可选的, 它们仅在 @ 字符之前的内容指定的实例不是主服务器时使用。
1、环境准备
机器名称 | IP配置 | 服务角色 | 备注 |
redis-master | 192.168.30.107 | redis主 | 开启 sentinel |
redis-slave1 | 192.168.30.7 | redis从 | 开启 sentinel |
redis-slave2 | 192.168.30.2 | redis从 | 开启 sentinel |
2、按照上实验实现主从
(1)打开所有机器上的redis 服务
[root@redis-master ~]# systemctl start redis
(2)在主上登录查询主从关系,确实主从已经实现
[root@redis-master ~]# redis-cli -h 192.168.30.107 -p 6379 192.168.30.107:6379> info Replication
3、所有节点配置 Redis Sentinel 哨兵
1、Redis Sentinel 配置
[root@redis-master ~]# vim /etc/redis-sentinel.conf port 26379 #默认监听端口26379 #sentinel announce-ip 1.2.3.4 #监听地址,注释默认是0.0.0.0 sentinel monitor mymaster 192.168.30.107 6379 1 #指定主redis和投票裁决的机器数,即至少有1个sentinel节点同时判定主节点故障时,才认为其真的故障 下面保存默认就行,根据自己的需求修改 sentinel down-after-milliseconds mymaster 5000 #如果联系不到节点5000毫秒,我们就认为此节点下线。 sentinel failover-timeout mymaster 60000 #设定转移主节点的目标节点的超时时长。 sentinel auth-pass <master-name> <password> #如果redis节点启用了auth,此处也要设置password。 sentinel parallel-syncs <master-name> <numslaves> #指在failover过程中,能够被sentinel并行配置的从节点的数量;
注意:只需指定主机器的IP,等sentinel 服务开启,它能自己查询到主上的从redis;并能完成自己的操作
2、指定 master 选举优先级
3、开启 Redis Sentienl 服务
1、开启 Redis Sentienl 服务
[root@redis-master ~]# systemctl start redis-sentinel # 在主上开启服务,打开了26379端口
2、开启服务后,/etc/redis-sentinel.conf 配置文件会生成从redis 的信息
Redis在3.0版正式引入redis-cluster集群这个特性。Redis集群是一个提供在多个Redis间节点间共享数据的程序集。Redis集群是一个分布式(distributed)、容错(fault-tolerant)的Redis内存K/V服务,集群可以使用的功能是普通单机Redis所能使用的功能的一个子集(subset),比如Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误。还有比如set里的并集(unions)和交集(intersections)操作,就没有实现。通常来说,那些处理命令的节点获取不到键值的所有操作都不会被实现。在将来,用户或许可以通过使用MIGRATE COPY命令,在集群上用计算节点(Computation Nodes) 来执行多键值的只读操作, 但Redis集群本身不会执行复杂的多键值操作来把键值在节点间移来移去。Redis集群不像单机版本的Redis那样支持多个数据库,集群只有数据库0,而且也不支持SELECT命令。Redis集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。
无中心架构,分布式提供服务。数据按照slot存储分布在多个redis实例上。增加slave做standby数据副本,用于failover,使集群快速恢复。实现故障auto failover,节点之间通过gossip协议交换状态信息;投票机制完成slave到master角色的提升。支持在线增加或减少节点。降低硬件成本和运维成本,提高系统的扩展性和可用性。
client实现复杂,驱动要求实现smart client,缓存slots mapping信息并及时更新。目前仅JedisCluster相对成熟,异常处理部分还不完善,比如常见的“max redirect exception”。客户端的不成熟,影响应用的稳定性,提高开发难度。节点会因为某些原因发生阻塞(阻塞时间大于clutser-node-timeout),被判断下线。这种failover是没有必要,sentinel也存在这种切换场景。
参考:http://redis.io/topics/cluster-tutorial。
集群部署交互式命令行工具:https://github.com/eyjian/redis-tools/tree/master/deploy
集群运维命令行工具:https://github.com/eyjian/redis-tools/tree/master
批量操作工具:Releases · eyjian/libmooon · GitHub
名词 | 解释 |
ASAP | As Soon As Possible,尽可能 |
RESP | Redis Serialization Protocol,redis的序列化协议 |
replica | 从5.0开始,原slave改叫replica,相关的配置参数也做了同样改名 |
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot),数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
1、哈希槽的计算公式
集群使用公式 CRC16(key) & 16383 计算键 key属于哪个槽。
为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作,Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。
1、Redis Cluster 集群里面执行命令的两种情况
1、命令发送到了正确的节点
命令要处理的键所在的槽正好是由接收命令的节点负责,那么该节点执行命令,就像单机 Redis 服务器一样。
槽位说明:
7000:槽 0~5000
7001:槽 5001~10000
7002:槽 10001~16383
键 date 位于 2022 槽,该槽由节点 7000 负责,命令会直接执行。
2、命令发送到了错误的节点
接收到命令的节点并非处理键所在槽的节点,那么节点将向客户端返回一个转向(redirection)错误,告知客户端应该到哪个节点去执行这个命令,客户端会根据错误提示的信息,重新向正确的节点发送命令。
键 date 位于 2022 槽,该槽由节点 7000 负责,但错误发送到了7001节点,7001向客户返回转向错误。
客户端根据转向错误的指引,转向到节点7000,并重新发送命令
在集群中的节点会互相告知对方,自己负责处理哪些槽。
集群中的每个节点都会记录 16384 个槽分别由哪个节点负责,从而形成一个“槽表”(slot table)。
节点在接收到命令请求时,会通过槽表检查键所在的槽是否由本节点处理:
1、部署计划
redis cluster 要求至少三主三从共6个节点才能组成redis集群,测试环境可一台物理上启动6个redis节点,但生产环境至少要准备3台物理机或者虚拟机。
服务端口 | IP地址 | 配置文件名 |
6001 | 192.168.152.193 | /redis/6001/conf/redis.conf |
6002 | 192.168.152.193 | /redis/6002conf/redis.conf |
6001 | 192.168.152.194 | /redis/6001/conf/redis.conf |
6002 | 192.168.152.194 | /redis/6002/conf/redis.conf |
6001 | 192.168.152.198 | /redis/6001/conf/redis.conf |
6002 | 192.168.152.198 | /redis/6002/conf/redis.conf |
2、修改集群主机名
hostnamectl --static set-hostname redis01 hostnamectl --static set-hostname redis02 hostnamectl --static set-hostname redis03
3、hosts文件配置
cat >> /etc/hosts <<-EOF 192.168.152.193 redis01 192.168.152.194 redis02 192.168.152.198 redis03 EOF
从redis 3.0之后版本支持redis-cluster集群,redis-4.0.0开始支持module,redis-5.0.0开始支持类似于kafka那样的消息队列,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。这样就可以很好的保证redis的高可用性,下面就来部署个Redis Cluster,在两台服务器上部署6个redis节点
4、修改系统参数
1、修改最大可打开文件数
cat >> /etc/security/limits.conf << EOF * soft nofile 102400 * hard nofile 102400 EOF
如何确认更改对一个进程生效?按下列方法(其中$PID为被查的进程ID):
cat /proc/$PID/limits
系统关于/etc/security/limits.conf文件的说明:
#This file sets the resource limits for the users logged in via PAM. #It does not affect resource limits of the system services.
PAM:全称“Pluggable Authentication Modules”,中文名“插入式认证模块”。/etc/security/limits.conf实际为pam_limits.so(位置:/lib/security/pam_limits.so)的配置文件,只针对单个会话。要使用limits.conf生效,必须保证pam_limits.so被加入到了启动文件中。
注释说明只对通过PAM登录的用户生效,与PAM相关的文件(均位于/etc/pam.d目录下):
/etc/pam.d/login /etc/pam.d/sshd /etc/pam.d/crond
如果需要设置Linux用户的密码策略,可以修改文件/etc/login.defs,但这个只对新增的用户有效,如果要影响已有用户,可使用命令chage
2、TCP监听队列大小
要想永久生效,需要在文件/etc/sysctl.conf中增加一行:net.core.somaxconn = 32767,然后执行命令“sysctl -p”以生效。
Redis配置项tcp-backlog的值不能超过somaxconn的大小。
echo "net.core.somaxconn = 32767" >> /etc/sysctl.conf sysctl -p
即TCP listen的backlog大小,“/proc/sys/net/core/somaxconn”的默认值一般较小如128,需要修改大一点,比如改成32767。立即生效还可以使用命令:
sysctl -w net.core.somaxconn=32767
3、OOM相关:vm.overcommit_memory
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf sysctl -p
/proc/sys/vm/overcommit_memory”默认值为0,表示不允许申请超过CommitLimmit大小的内存。可以设置为1关闭Overcommit,设置方法请参照net.core.somaxconn完成
4、开启内核的“Transparent Huge Pages (THP)”特性
默认值为“[always] madvise never”,建议设置为never,以开启内核的“Transparent Huge Pages (THP)”特性,设置后redis进程需要重启。
为了永久生效,请将
echo never > /sys/kernel/mm/transparent_hugepage/enabled
加入到文件/etc/rc.local中。
echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.local chmod +x /etc/rc.local
5、安装 redis 并配置 redis-cluster
1、redis01 安装
[root@redis01 ~]# cd /opt [root@redis01 ~]# wget http://download.redis.io/releases/redis-5.0.5.tar.gz [root@redis01 ~]# tar -zxvf redis-5.0.5.tar.gz [root@redis01 ~]# cd redis-5.0.5/ [root@redis01 ~]# make [root@redis01 ~]# make install PREFIX=/usr/local/redis-cluster
1、创建实例目录
[root@redis01 ~]# mkdir -p /redis/{6001,6002}/{conf,data,log}
2、配置
配置官方配置文件,去掉#开头的和空格行
[root@redis01 ~]# cat redis.conf |grep -v ^# |grep -v ^$
1、redis01 6001 配置文件
[root@redis01 ~]#cd /redis/6001/conf/ [root@redis01 conf]# cat >> redis.conf << EOF bind 0.0.0.0 protected-mode no port 6001 daemonize no dir /redis/6001/data cluster-enabled yes cluster-config-file /redis/6001/conf/nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes pidfile /redis/6001/redis.pid logfile /redis/6001/log/redis.log EOF
2、redis01 6002 配置文件
[root@redis01 conf]# sed 's/6001/6002/g' redis.conf > /redis/6002/conf/redis.conf
3、启动脚本 start-redis-cluster.sh
[root@redis01 ~]#cat >/usr/local/redis-cluster/start-redis-cluster.sh<<-EOF #!/bin/bash REDIS_HOME=/usr/local/redis-cluster REDIS_CONF=/redis \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6001/conf/redis.conf \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6002/conf/redis.conf EOF
4、添加权限
[root@redis01 ~]# chmod +x /usr/local/redis-cluster/start-redis-cluster.sh
5、启动 redis
[root@redis01 ~]# /usr/local/redis-cluster/start-redis-cluster.sh
6、查看 redis 启动状态
[root@redis01 ~]# ss -anput | grep redis tcp LISTEN 0 511 *:6001 *:* users:(("redis-server",pid=25993,fd=6)) tcp LISTEN 0 511 *:6002 *:* users:(("redis-server",pid=25995,fd=6)) tcp LISTEN 0 511 *:16001 *:* users:(("redis-server",pid=25993,fd=9)) tcp LISTEN 0 511 *:16002 *:* users:(("redis-server",pid=25995,fd=9))
7、查看redis进程启动状态
[root@redis01 ~]# ps -ef | grep redis root 25993 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6001 [cluster] root 25995 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6002 [cluster] root 26060 6913 0 17:12 pts/0 00:00:00 grep --color=auto redis
2、redis02 安装
[root@redis02 ~]# cd /opt [root@redis02 ~]# wget http://download.redis.io/releases/redis-5.0.5.tar.gz [root@redis02 ~]# tar -zxvf redis-5.0.5.tar.gz [root@redis02 ~]# cd redis-5.0.5/ [root@redis02 ~]# make [root@redis02 ~]# make install PREFIX=/usr/local/redis-cluster
1、创建实例目录
[root@redis02 ~]# mkdir -p /redis/{6001,6002}/{conf,data,log}
2、配置
[root@redis02 ~]#cd /redis/6001/conf/ [root@redis02 conf]# cat >> redis.conf << EOF bind 0.0.0.0 protected-mode no port 6001 daemonize no dir /redis/6001/data cluster-enabled yes cluster-config-file /redis/6001/conf/nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes pidfile /redis/6001/redis.pid logfile /redis/6001/log/redis.log EOF
1、redis02 6002配置文件
[root@redis02 conf]# sed 's/6001/6002/g' redis.conf > /redis/6002/conf/redis.conf
2、写一个启动脚本 start-redis-cluster.sh
[root@redis02 ~]#cat >/usr/local/redis-cluster/start-redis-cluster.sh<<-EOF #!/bin/bash REDIS_HOME=/usr/local/redis-cluster REDIS_CONF=/redis \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6001/conf/redis.conf \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6002/conf/redis.conf EOF
3、添加权限
[root@redis02 ~]# chmod +x /usr/local/redis-cluster/start-redis-cluster.sh
4、启动redis
[root@redis02 ~]# /usr/local/redis-cluster/start-redis-cluster.sh
1、查看 redis 启动状态
[root@redis02 ~]# ss -anput | grep redis tcp LISTEN 0 511 *:6001 *:* users:(("redis-server",pid=25993,fd=6)) tcp LISTEN 0 511 *:6002 *:* users:(("redis-server",pid=25995,fd=6)) tcp LISTEN 0 511 *:16001 *:* users:(("redis-server",pid=25993,fd=9)) tcp LISTEN 0 511 *:16002 *:* users:(("redis-server",pid=25995,fd=9))
2、查看redis进程启动状态
[root@redis02 ~]# ps -ef | grep redis root 25993 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6001 [cluster] root 25995 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6002 [cluster] root 26060 6913 0 17:12 pts/0 00:00:00 grep --color=auto redis
3、redis03 安装
[root@redis03 ~]# cd /opt [root@redis03 ~]# wget http://download.redis.io/releases/redis-5.0.5.tar.gz [root@redis03 ~]# tar -zxvf redis-5.0.5.tar.gz [root@redis03 ~]# cd redis-5.0.5/ [root@redis03 ~]# make [root@redis03 ~]# make install PREFIX=/usr/local/redis-cluster
1、创建实例目录
[root@redis03 ~]# mkdir -p /redis/{6001,6002}/{conf,data,log}
2、配置
[root@redis03 ~]#cd /redis/6001/conf/ [root@redis03 conf]# cat >> redis.conf << EOF bind 0.0.0.0 protected-mode no port 6001 daemonize no dir /redis/6001/data cluster-enabled yes cluster-config-file /redis/6001/conf/nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes pidfile /redis/6001/redis.pid logfile /redis/6001/log/redis.log EOF
1、redis02 6002配置文件
[root@redis03 conf]# sed 's/6001/6002/g' redis.conf > /redis/6002/conf/redis.conf
2、写一个启动脚本 start-redis-cluster.sh
[root@redis03 ~]# cat >/usr/local/redis-cluster/start-redis-cluster.sh<<-EOF #!/bin/bash REDIS_HOME=/usr/local/redis-cluster REDIS_CONF=/redis \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6001/conf/redis.conf \$REDIS_HOME/bin/redis-server \$REDIS_CONF/6002/conf/redis.conf EOF
3、添加权限
[root@redis03 ~]# chmod +x /usr/local/redis-cluster/start-redis-cluster.sh
4、启动 redis
[root@redis03 ~]# /usr/local/redis-cluster/start-redis-cluster.sh
5、查看 redis 启动状态
[root@redis03 ~]# ss -anput | grep redis tcp LISTEN 0 511 *:6001 *:* users:(("redis-server",pid=25993,fd=6)) tcp LISTEN 0 511 *:6002 *:* users:(("redis-server",pid=25995,fd=6)) tcp LISTEN 0 511 *:16001 *:* users:(("redis-server",pid=25993,fd=9)) tcp LISTEN 0 511 *:16002 *:* users:(("redis-server",pid=25995,fd=9))
6、查看redis进程启动状态
[root@redis03 ~]# ps -ef | grep redis root 25993 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6001 [cluster] root 25995 1 0 16:56 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6002 [cluster] root 26060 6913 0 17:12 pts/0 00:00:00 grep --color=auto redis
6、创建 redis cluster
如果只是想快速创建和启动redis集群,可使用redis官方提供的脚本create-cluster,注意redis-5.0.0版本开始才支持“--cluster”
[root@redis01 bin]# cd /usr/local/redis-cluster/bin [root@redis01 bin]# ./redis-cli --cluster create 192.168.152.193:6001 192.168.152.193:6002 192.168.152.194:6001 192.168.152.194:6002 192.168.152.198:6001 192.168.152.198:6002 --cluster-replicas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.152.194:6002 to 192.168.152.193:6001 Adding replica 192.168.152.198:6002 to 192.168.152.194:6001 Adding replica 192.168.152.193:6002 to 192.168.152.198:6001 M: 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001 slots:[0-5460] (5461 slots) master S: 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6002 replicates 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 M: 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001 slots:[5461-10922] (5462 slots) master S: 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002 replicates 9c0c3aac2787af4824110bed08e5c346bc218ca6 M: 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001 slots:[10923-16383] (5461 slots) master S: 41ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002 replicates 60225e8398b1c6cf609ca27c63d968befbf5e3ee Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .... >>> Performing Cluster Check (using node 192.168.152.193:6001) M: 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 41ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002 slots: (0 slots) slave replicates 60225e8398b1c6cf609ca27c63d968befbf5e3ee M: 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002 slots: (0 slots) slave replicates 9c0c3aac2787af4824110bed08e5c346bc218ca6 S: 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6002 slots: (0 slots) slave replicates 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
注意:
如果配置项 cluster-enabled 的值不为yes,则执行时会报错“[ERR] Node 192.168.152.193:6001 is not configured as a cluster node.”。这个时候需要先将cluster-enabled的值改为 yes,然后重启 redis-server 进程,之后才可以重新执行 redis-cli 创建集群。
1、redis-cli 的参数说明
表示创建一个redis集群。
表示为集群中的每一个主节点指定一个从节点,即一比一的复制
2、查看redis进程是否已切换为集群状态(cluster)
[root@redis01 bin]# cd [root@redis01 ~]# ps -ef|grep redis root 25993 1 0 16:56 ? 00:00:02 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6001 [cluster] root 25995 1 0 16:56 ? 00:00:02 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6002 [cluster]
3、停止redis实例,直接使用kill命令即可
kill -9 25993
4、设置命令行工具 redis-cli
[root@redis01 ~]# ln -s /usr/local/redis-cluster/bin/redis-cli /bin/redis-cli [root@redis65 bin]# redis-cli -c -p 6001
5、查看集群中的节点
127.0.0.1:6001> cluster nodes 1ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002@16002 slave 60225e8398b1c6cf609ca27c63d968befbf5e3ee 0 1569404664000 6 connected 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001@16001 master - 0 1569404664529 3 connected 5461-10922 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001@16001 myself,master - 0 1569404662000 1 connected 0-5460 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001@16001 master - 0 1569404664025 5 connected 10923-16383 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002@16002 slave 9c0c3aac2787af4824110bed08e5c346bc218ca6 0 1569404663520 4 connected 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6002@16002 slave 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 0 1569404665032 5 connected
字段从左至右分别是
节点ID、IP地址和端口,节点角色标志、最后发送ping时间、最后接收到pong时间、连接状态、节点负责处理的hash slot。
集群可以自动识别出ip/port的变化,并通过Gossip(最终一致性,分布式服务数据同步算法)协议广播给其他节点知道。Gossip也称“病毒感染算法”、“谣言传播算法”
6、 验证集群
127.0.0.1:6001> set name redis -> Redirected to slot [5798] located at 192.168.152.194:6001 OK 192.168.152.194:6001> quit [root@redis01 ~]# redis-cli -c -p 6002 127.0.0.1:6002> get name -> Redirected to slot [5798] located at 192.168.152.194:6001 "redis"
登录测试
[root@redis01 ~]# redis-cli -h 192.168.152.198 -p 6002
7、检查节点状态
[root@redis65 bin]# redis-cli --cluster check 192.168.152.198:6001 192.168.152.198:6001 (8abc8b5c...) -> 0 keys | 5461 slots | 1 slaves. 192.168.152.193:6001 (9c0c3aac...) -> 0 keys | 5461 slots | 1 slaves. 192.168.152.194:6001 (60225e83...) -> 1 keys | 5462 slots | 1 slaves. [OK] 1 keys in 3 masters. 0.00 keys per slot on average. >>> Performing Cluster Check (using node 192.168.152.198:6001) M: 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6002 slots: (0 slots) slave replicates 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 S: 41ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002 slots: (0 slots) slave replicates 60225e8398b1c6cf609ca27c63d968befbf5e3ee S: 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002 slots: (0 slots) slave replicates 9c0c3aac2787af4824110bed08e5c346bc218ca6 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
8、查看集群信息
[root@redis65 bin]# redis-cli -c -p 6002 127.0.0.1:6003> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:5 cluster_stats_messages_ping_sent:1544 cluster_stats_messages_pong_sent:1577 cluster_stats_messages_meet_sent:3 cluster_stats_messages_sent:3124 cluster_stats_messages_ping_received:1574 cluster_stats_messages_pong_received:1547 cluster_stats_messages_meet_received:3 cluster_stats_messages_received:3124
9、redis cluster 集群加上认证
1、登录到 redis 节点设置登录验证
[root@redis01 ~]# redis-cli -h 192.168.152.193 -p 6001 -c 192.168.152.193:6001> config set masterauth redispws OK 192.168.152.193:6001> config set requirepass redispws OK 192.168.152.193:6001> auth redispws OK 192.168.152.193:6001> config rewrite OK [root@redis02 bin]# ./redis-cli -h 192.168.152.194 -p 6001 -c 192.168.152.194:6001> config set masterauth redispws OK 192.168.152.194:6001> config set requirepass redispws OK 192.168.152.194:6001> auth redispws OK 192.168.152.194:6001> config rewrite OK [root@redis03 bin]# ./redis-cli -h 192.168.152.198 -p 6001 -c 192.168.152.198:6001> config set masterauth redispws OK 192.168.152.198:6001> config set requirepass redispws OK 192.168.152.198:6001> auth redispws OK 192.168.152.198:6001> config rewrite OK
各个节点都完成上面的3条config操作,重启redis各节点,看下各节点的redis.conf,可以发现最后多了3行内容
[root@redis01 ~]# yum -y install psmisc [root@redis01 ~]# killall redis-server [root@redis01 ~]# /usr/local/redis-cluster/start-redis-cluster.sh [root@redis01 ~]# cat /redis/6001/conf/redis.conf bind 0.0.0.0 protected-mode no port 6001 daemonize yes dir "/redis/6001/data" cluster-enabled yes cluster-config-file "/redis/6001/conf/nodes.conf" cluster-node-timeout 5000 appendonly yes pidfile "/redis/6001/redis.pid" logfile "/redis/6001/log/redis.log" # Generated by CONFIG REWRITE masterauth "redispws" requirepass "redispws"
2、通过认证登录 redis
[root@redis01 ~]# redis-cli -h 192.168.152。193 -p 6001 -c -a 'redispws'
1、安装PHP7版本及php-fpm,php-redis,hiredis,swoole 扩展
1、更换 yum 源
[root@web ~]# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm [root@web ~]# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
2、查看 php 信息
[root@web ~]# yum search php71w
3、安装 php7.1 以及扩展
[root@web ~]# yum -y install php71w php71w-fpm php71w-cli php71w-common php71w-devel php71w-gd php71w-pdo php71w-mysql php71w-mbstring php71w-bcmath gcc gcc-c++
4、检查 PHP 版本
[root@web ~]# php -v
5、安装 swoole 扩展
1、下载 swoole 源码
[root@web ~]# git clone https://gitee.com/swoole/swoole.git
2、编译和安装 swoole
[root@web ~]# cd swoole [root@web ~]# phpize (ubuntu 没有安装phpize可执行命令:sudo apt-get install php-dev来安装phpize) [root@web ~]# ./configure [root@web ~]# make [root@web ~]# make install
除了手工下载编译外,还可以通过PHP
官方提供的pecl
命令,一键下载安装
[root@web ~]# pecl install swoole
6、安装 php-redis 扩展
[root@web ~]# yum install redis php-redis
7、安装异步 hiredis
[root@web ~]# yum install hiredis-devel
8、配置 php.ini
编译安装成功后,修改php.ini
加入
[root@web ~]# vim /etc/php.ini extension=redis.so extension=swoole.so # 通过php -m或phpinfo()来查看是否成功加载了swoole.so,如果没有可能是php.ini的路径不对,可以使用php --ini来定位到php.ini的绝对路径
9、安装 php-fpm 扩展
1、安装 php71-fpm
上面已经用 yum 安装过了就不必再次安装
2、创建web用户组及用户
[root@web ~]# groupadd www-data [root@web ~]# useradd -g www-data www-data
3、修改 php-fpm 配置
改如下配置:
[root@web ~]# vim /etc/php-fpm.d/www.conf user=www-data group=www-data
4、修改 nginx 配置
[root@web ~]# vim /etc/nginx/nginx.conf # 整合nginx和 php-fpm # 添加以下内容 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # 重启nginx systemctl reload nginx # 创建 index.php [root@web ~]# vim /usr/share/nginx/html/index.php <?php echo phpinfo(); ?>
5、重启 php-fpm
[root@web ~]# systemctl restart php-fpm.service
6、验证 redis 扩展是否安装成功
浏览器访问 http://192.168.152.193/index.php
7、通过php连接测试连接单节点redis
[root@web ~]# vim /usr/share/nginx/html/redis.php <?php //连接192.168.5.65的Redis服务 $redis = new Redis(); $redis->connect('192.168.5.65', 6001); $redis->auth('zxc789'); //redis认证 echo "Connection to server sucessfully"; //查看服务是否运行 echo "Server is running: " . $redis->ping(); ?>
执行脚本或浏览器访问,输出结果为:
Connection to server sucessfully Server is running: PONG
8、PHP 要操作 redis cluster集群有两种方式
1、phpredis 扩展
这是个c扩展,性能更高,但是这个方案参考资料很少
2、predis 扩展
纯 php 开发,使用了命名空间,需要php5.3+,灵活性高,我这里用的是predis,下载地址https://github.com/nrk/predis
[root@web ~]# git clone https://github.com/nrk/predis.git # 将 predis 放到网站根目录下 [root@web ~]# mv predis /usr/share/nginx/html/ [root@web ~]# cd /usr/share/nginx/html/
3、配置测试 redis cluster
[root@web ~]# cat predis.php <?php require 'predis/autoload.php';//引入predis相关包 //redis实例 $servers = array( 'tcp://192.168.152.193:6001', 'tcp://192.168.152.193:6002', 'tcp://192.168.152.194:6001', 'tcp://192.168.152.194:6002', 'tcp://192.168.152.198:6001', 'tcp://192.168.152.198:6002', ); $options = ['cluster' =>'redis','parameters' => [ 'password' => 'redispws' ]]; $client = new Predis\Client($servers,$options); $client->set('name1', '1111111'); $client->set('name2', '2222222'); $client->set('name3', '3333333'); $name1 = $client->get('name1'); $name2 = $client->get('name2'); $name3 = $client->get('name3'); var_dump($name1, $name2, $name3);die; ?>
4、浏览器访问验证
http://192.168.152.193/predis.php
2、Java 操作 Redis ,redis cluster集群
1、jedis 连接redis(单机)
使用jedis如何操作redis,但是其实方法是跟redis的操作大部分是相对应的。
所有的redis命令都对应jedis的一个方法
1、在macen工程中引入jedis的jar包
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
2、建立测试工程
public class JedisTest { @Test public void testJedis()throws Exception{ Jedis jedis = new Jedis("192.168.241.133",6379); jedis.set("test", "my forst jedis"); String str = jedis.get("test"); System.out.println(str); jedis.close(); } }
3.点击运行
若报下面连接超时,则须关闭防火墙(命令 service iptables stop)
再次运行
每次连接需要创建一个连接、执行完后就关闭,非常浪费资源,所以使用jedispool(连接池)连接
2、jedisPool 连接redis (单机)
@Test public void testJedisPool()throws Exception{ //创建连接池对象 JedisPool jedispool = new JedisPool("192.168.241.133",6379); //从连接池中获取一个连接 Jedis jedis = jedispool.getResource(); //使用jedis操作redis jedis.set("test", "my forst jedis"); String str = jedis.get("test"); System.out.println(str); //使用完毕 ,关闭连接,连接池回收资源 jedis.close(); //关闭连接池 jedispool.close(); }
3、jedisCluster 连接redis(集群)
jedisCluster专门用来连接redis集群
jedisCluster在单例存在的
@Test public void testJedisCluster()throws Exception{ //创建jedisCluster对象,有一个参数 nodes是Set类型,Set包含若干个HostAndPort对象 Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.241.133",7001)); nodes.add(new HostAndPort("192.168.241.133",7002)); nodes.add(new HostAndPort("192.168.241.133",7003)); nodes.add(new HostAndPort("192.168.241.133",7004)); nodes.add(new HostAndPort("192.168.241.133",7005)); nodes.add(new HostAndPort("192.168.241.133",7006)); JedisCluster jedisCluster = new JedisCluster(nodes); //使用jedisCluster操作redis jedisCluster.set("test", "my forst jedis"); String str = jedisCluster.get("test"); System.out.println(str); //关闭连接池 jedisCluster.close(); }
进集群服务器查看值
1、集群 cluster
1. CLUSTER INFO 打印集群的信息 2. CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
2、节点node
1. CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。 2. CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。 3. CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。 4. CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
3、槽 slot
1. CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。 2. CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。 3. CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。 4. CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。 5. CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。 6. CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。 7. CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
4、键 key
1. CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。 2. CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。 3. CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键
1,添加节点
1、创建实例目录
[root@redis01 ~]# mkdir -p /redis/{6003,6004}/{conf,data,log}
2、redis01 6003 配置文件
[root@redis01 conf]# sed 's/6001/6003/g' redis.conf > /redis/6003/conf/redis.conf [root@redis01 conf]# sed 's/6001/6004/g' redis.conf > /redis/6004/conf/redis.conf
3、启动脚本 start-redis-cluster.sh
[root@redis01 ~]# cat >/usr/local/redis-cluster/start-redis-cluster1.sh<<-EOF #!/bin/bash REDIS_HOME=/usr/local/redis-cluster REDIS_CONF=/redis \$REDIS_HOME/src/redis-server \$REDIS_CONF/6003/conf/redis.conf \$REDIS_HOME/src/redis-server \$REDIS_CONF/6004/conf/redis.conf EOF
4、添加权限
[root@redis01 ~]# chmod +x /usr/local/redis-cluster/start-redis-cluster1.sh
5、启动 redis
[root@redis01 ~]# /usr/local/redis-cluster/start-redis-cluster1.sh
6、查看 redis 启动状态
[root@redis01 ~]# ss -anput | grep redis tcp LISTEN 0 511 *:6001 *:* users:(("redis-server",pid=26980,fd=6)) tcp LISTEN 0 511 *:6002 *:* users:(("redis-server",pid=26982,fd=6)) tcp LISTEN 0 511 *:6003 *:* users:(("redis-server",pid=64814,fd=6)) tcp LISTEN 0 511 *:6004 *:* users:(("redis-server",pid=64816,fd=6)) tcp LISTEN 0 511 *:16001 *:* users:(("redis-server",pid=26980,fd=9)) tcp LISTEN 0 511 *:16002 *:* users:(("redis-server",pid=26982,fd=9)) tcp LISTEN 0 511 *:16003 *:* users:(("redis-server",pid=64814,fd=9)) tcp LISTEN 0 511 *:16004 *:* users:(("redis-server",pid=64816,fd=9))
7、查看 redis 进程启动状态
[root@redis01 ~]# ps -ef | grep redis root 26980 1 0 00:20 ? 00:01:54 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6001 [cluster] root 26982 1 0 00:20 ? 00:02:30 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6002 [cluster] root 64814 1 0 17:39 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6003 [cluster] root 64816 1 0 17:39 ? 00:00:00 /usr/local/redis-cluster/bin/redis-server 0.0.0.0:6004 [cluster]
8,添加主节点
[root@redis01 ~]# redis-cli --cluster add-node 192.168.152.193:6003 192.168.152.193:6001 -a redispws
注释:
192.168.152.193:6003 是新增的节点
192.168.152.193:6001集群任一个旧节点
查看节点状态
[root@redis01 ~]# redis-cli -h 192.168.152.193 -p 6003 -a redispws Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.152.193:6003> cluster nodes 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001@16001 master - 0 1569578158000 1 connected 0-5460 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001@16001 master - 0 1569578158000 3 connected 5461-10922 41ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002@16002 slave 60225e8398b1c6cf609ca27c63d968befbf5e3ee 0 1569578157584 6 connected 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002@16002 slave 9c0c3aac2787af4824110bed08e5c346bc218ca6 0 1569578157000 4 connected 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001@16001 master - 0 1569578158992 5 connected 10923-16383 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6003@16003 myself,slave 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 0 1569578158000 2 connected
9,添加从节点
[root@redis01 ~]# redis-cli --cluster add-node 192.168.152.193:6004 192.168.152.193:6001 --cluster-slave -a 'redispws'
注释:
--cluster-slave 表示添加从节点
192.168.152.193:6004 新节点
192.168.152.193:6001 集群任一个旧节点
查看集群节点状态
[root@redis01 ~]# redis-cli -h 192.168.152.193 -p 6004 -a redispws Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.152.193:6004> cluster node (error) ERR Unknown subcommand or wrong number of arguments for 'node'. Try CLUSTER HELP. 192.168.152.193:6004> cluster nodes 41ffe24a976c1698590e739a95c7b221d406ca75 192.168.152.198:6002@16002 slave 60225e8398b1c6cf609ca27c63d968befbf5e3ee 0 1569579181151 3 connected 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001@16001 master - 0 1569579180547 3 connected 5461-10922 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001@16001 master - 0 1569579179037 1 connected 0-5460 255a59264a7fd7daef67ba1180ba0458a593b28b 192.168.152.194:6002@16002 slave 9c0c3aac2787af4824110bed08e5c346bc218ca6 0 1569579179138 1 connected 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001@16001 master - 0 1569579180146 5 connected 10923-16383 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6002@16002 slave 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 0 1569579180000 5 connected 0f50f59b6186513f32d77641678e14521d5dc485 192.168.152.193:6004@16004 myself,slave 9c0c3aac2787af4824110bed08e5c346bc218ca6 0 1569579179000 0 connected
可以看到6003节点的 connected 后面没有 Hash 槽(slot),新加入的加点是一个主节点, 当集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中,也不会参与选举。
10、给新节点分配哈希槽
#参数192.168.152.193:6001只是表示连接到这个集群,具体对哪个节点进行操作后面会提示输入 [root@redis01 ~]# redis-cli --cluster reshard 192.168.152.193:6001 返回信息: >>> Performing Cluster Check (using node 192.168.152.193:6001) M: 9c0c3aac2787af4824110bed08e5c346bc218ca6 192.168.152.193:6001 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 0f50f59b6186513f32d77641678e14521d5dc485 192.168.152.193:6004 slots: (0 slots) slave replicates 9c0c3aac2787af4824110bed08e5c346bc218ca6 S: 41591f7b35be3e5aa89320c0927e83ec915faac6 192.168.152.193:6003 slots: (0 slots) slave replicates 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 M: 60225e8398b1c6cf609ca27c63d968befbf5e3ee 192.168.152.194:6001 slots:[5461-10922] (5462 slots) master M: 8abc8b5c438e34d345b76cd7eda7d0a7e9dd9859 192.168.152.198:6001 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. #根据提示选择要迁移的slot数量 How many slots do you want to move (from 1 to 16384)? 1000 #选择要接受这些slot的node-id What is the receiving node ID? a70d7fff6d6dde511cb7cb632a347be82dd34643 # 选择slot来源: # all表示从所有的master重新分配, # 或者数据要提取slot的master节点id,最后用done结束 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:3bcdfbed858bbdd92dd760632b9cb4c649947fed Source node #2:done # 打印被移动的 slot后,输入yes开始移动slot以及对应的数据. Do you want to proceed with the proposed reshard plan (yes/no)? yes #结束 # 查看确认 [root@redis01 ~]# redis-cli -h 192.168.152.193 -p 6004 -a redispws Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.152.193:6004> cluster nodes
11、删除一个Master节点
删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点(目前只能把被删除master的slot迁移到一个节点上)
[root@redis01 ~]# redis-cli --cluster reshard 192.168.152.193:6001 #根据提示选择要迁移的slot数量(7003上有1000个slot全部转移) How many slots do you want to move (from 1 to 16384)? 1000 #选择要接受这些slot的node-id What is the receiving node ID? 3bcdfbed858bbdd92dd760632b9cb4c649947fed #选择slot来源: #all表示从所有的master重新分配, #或者数据要提取slot的master节点id,最后用done结束 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:a70d7fff6d6dde511cb7cb632a347be82dd34643 Source node #2:done #打印被移动的slot后,输入yes开始移动slot以及对应的数据. #Do you want to proceed with the proposed reshard plan (yes/no)? yes #结束 #删除空master节点 [root@redis01 ~]# redis-cli --cluster del-node 192.168.152.193:6001 'a70d7fff6d6dde511cb7cb632a347be82dd34643'
12、删除一个Slave节点
[root@redis01 ~]# redis-cli --cluster del-node ip:port '<node-id>' #这里移除的是6004 ./redis-cli --cluster del-node 192.168.152.193:6002 74957282ffa94c828925c4f7026baac04a67e291 返回信息: >>> Removing node 74957282ffa94c828925c4f7026baac04a67e291 from cluster 192.168.152.193:6001 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node.
[root@localhost ~]# tar zxvf 2.2.7.tar.gz [root@localhost ~]# cd phpredis-2.2.7 [root@localhost ~]# /application/php/bin/phpize [root@localhost ~]# ./configure --with-php-config=/application/php/bin/php-config [root@localhost ~]# make && make install [root@localhost ~]# echo 'extension="redis.so"' >> /application/php/lib/php.ini [root@localhost ~]# systemctl restart php-fpm [root@localhost ~]# systemctl restart nginx
1、连接测试代码
[root@localhost ~]# cat /application/nginx/html/check.php <?php //连接本地的 Redis 服务 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); echo "Connection to server sucessfully"; //查看服务是否运行 echo "Server is running: " . $redis->ping(); ?>
2、字符串操作
<?php //连接本地的 Redis 服务 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); echo "Connection to server sucessfully"; //设置 redis 字符串数据 $redis->set("tutorial-name", "Redis tutorial"); // 获取存储的数据并输出 echo "Stored string in redis:: " . $redis- >get("tutorial-name"); ?>
1、安装软件包
[root@localhost ~]# yum install python-pip ipython -y [root@localhost ~]# pip install redis
2、连接测试
[root@localhost ~]# ipython In [1]: import redis In [2]: clsn = redis.StrictRedis(host='localhost', port=6379, db=0) In [3]: clsn.set('blog','blog.nmtui.com') Out[3]: True In [4]: clsn.get('blog') Out[4]: 'blog.nmtui.com'
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。