文章目录
Redis集群
https://www.cnblogs.com/ruiyeclub/p/12355073.html
一、Redis相关
1、Redis简介
Redis(Remote Dictionary Server ),即远程字典服务,是一种支持主从同步的ey-value存储系统存储系统。是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis是一个key-value存储系统存储系统。它支持存储的value类型:string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型数据类型)都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
2、Redis特点
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
3、Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
二、集群搭建
1、docker-compose文件编写
version: '2'
services:
master:
image: redis
container_name: redis-master
command: redis-server --requirepass 123456
ports:
- "6379:6379"
networks:
sentinel-master:
ipv4_address: 192.169.0.2
slave1:
image: redis
container_name: redis-slave-1
ports:
- "6380:6379"
command: redis-server --slaveof redis-master 6379 --requirepass 123456 --masterauth 123456
depends_on:
- master
networks:
sentinel-master:
ipv4_address: 192.169.0.3
slave2:
image: redis
container_name: redis-slave-2
ports:
- "6381:6379"
command: redis-server --slaveof redis-master 6379 --requirepass 123456 --masterauth 123456
depends_on:
- master
networks:
sentinel-master:
ipv4_address: 192.169.0.4
networks:
sentinel-master:
driver: bridge
ipam:
config:
- subnet: 192.169.0.0/16
2、运行集群
[root@iZp06cqz6zbn9jZ redis_clusters]# docker-compose up -d
Creating network "redis_clusters_sentinel-master" with driver "bridge"
Creating redis-master ... done
Creating redis-slave-1 ... done
Creating redis-slave-2 ... done
[root@iZp06cqz6zbn9jZ redis_clusters]# docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------
redis-master docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
redis-slave-1 docker-entrypoint.sh redis ... Up 0.0.0.0:6380->6379/tcp
redis-slave-2 docker-entrypoint.sh redis ... Up 0.0.0.0:6381->6379/tcp
[root@iZp06cqz6zbn9jZ redis_clusters]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
acdfccf7f0b4 redis "docker-entrypoint.s…" 16 seconds ago Up 14 seconds 0.0.0.0:6381->6379/tcp redis-slave-2
76b74b0a640f redis "docker-entrypoint.s…" 16 seconds ago Up 14 seconds 0.0.0.0:6380->6379/tcp redis-slave-1
f0ec343bc3b4 redis "docker-entrypoint.s…" 16 seconds ago Up 15 seconds 0.0.0.0:6379->6379/tcp redis-master
3、进入集群
# 进入master节点
[root@iZp06cqz6zbn9jZ redis_clusters]# docker exec -it f0ec343bc3b4 bash
root@f0ec343bc3b4:/data# redis-cli
127.0.0.1:6379> keys *
(error) NOAUTH Authentication required.
127.0.0.1:6379> ahth 123456
(error) ERR unknown command `ahth`, with args beginning with: `123456`,
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> keys *
(empty array)
# 进入master节点 > 设置key/value
127.0.0.1:6379> set name dyl
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"dyl"
127.0.0.1:6379> exit
root@f0ec343bc3b4:/data# exit
# 进入slave1节点
[root@iZp06cqz6zbn9jZ redis_clusters]# docker exec -it 76b74b0a640f bash
root@76b74b0a640f:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> keys *
1) "name"
# 进入slave2节点 > 查看key/value
[root@iZp06cqz6zbn9jZ redis_clusters]# docker exec -it acdfccf7f0b4 bash
root@acdfccf7f0b4:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"dyl"
127.0.0.1:6379>
三、Redis中的六大数据结构
https://www.cnblogs.com/xrq730/p/8944539.html
https://www.cnblogs.com/ysocean/p/9080940.html
1、string数据类型
string 是Redis的最基本的数据类型,可以理解为与 Memcached 一模一样的类型,一个key 对应一个 value。string 类型是二进制安全的,意思是 Redis 的 string 可以包含任何数据,比如图片或者序列化的对象,一个 redis 中字符串 value 最多可以是 512M。
命令 | 描述 | 用法 |
---|---|---|
SET | (1)将字符串值Value关联到Key (2)Key已关联则覆盖,无视类型 (3)原本Key带有生存时间TTL,那么TTL被清除 | SET key value [EX seconds] [PX milliseconds] [NX|XX] |
GET | (1)返回key关联的字符串值(2)Key不存在返回nil (3)Key存储的不是字符串,返回错误,因为GET只用于处理字符串 | GET key |
MSET | (1)同时设置一个或多个Key-Value键值对 (2)某个给定Key已经存在,那么MSET新值会覆盖旧值 (3)如果上面的覆盖不是希望的,那么使用MSETNX命令,所有Key都不存在才会进行覆盖 (4)MSET是一个原子性操作,所有Key都会在同一时间被设置,不会存在有些更新有些没更新的情况 | MSET key value [key value …] |
MGET | (1)返回一个或多个给定Key对应的Value(2)某个Key不存在那么这个Key返回nil | MGET key [key …] |
SETEX | (1)将Value关联到Key(2)设置Key生存时间为seconds,单位为秒 (3)如果Key对应的Value已经存在,则覆盖旧值 (4)SET也可以设置失效时间,但是不同在于SETNX是一个原子操作,即关联值与设置生存时间同一时间完成 | SETEX key seconds value |
SETNX | (1)将Key的值设置为Value,当且仅当Key不存在(2)若给定的Key已经存在,SEXNX不做任何动作 | SETNX key value |
APPEND | 字符串追加 | APPEND key value |
DEL | 删除key | DEL key [key …] |
INCR | 将 key 中储存的数字值增一 | INCR key |
DECR | 将 key 中储存的数字值减一 | DECR key |
[root@iZp06cqz6zbn9jZ redis_clusters]# docker exec -it 5a1cc01437ff bash
root@5a1cc01437ff:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> kyes *
(error) ERR unknown command `kyes`, with args beginning with: `*`,
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set string1 dyl1
OK
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "string1"
127.0.0.1:6379> get string1
"dyl1"
127.0.0.1:6379> mset string2 dyl2 string3 dyl3
OK
127.0.0.1:6379> keys *
1) "string2"
2) "string1"
3) "string3"
127.0.0.1:6379> mget string1 string2
1) "dyl1"
2) "dyl2"
127.0.0.1:6379> setex strtime 10 time1
OK
127.0.0.1:6379> keys *
1) "string2"
2) "string1"
3) "strtime"
4) "string3"
十秒钟之后再次输入
127.0.0.1:6379> keys *
1) "string2"
2) "string1"
3) "string3"
127.0.0.1:6379> append string1 123
(integer) 7
127.0.0.1:6379> get string1
"dyl1123"
127.0.0.1:6379> del string3
(integer) 1
127.0.0.1:6379> keys *
1) "string2"
2) "string1"
# 可以作为页面被访问次数的计数器
127.0.0.1:6379> set one 1
OK
127.0.0.1:6379> keys *
1) "one"
127.0.0.1:6379> incr one
(integer) 2
127.0.0.1:6379> get one
"2"
127.0.0.1:6379> decr one
(integer) 1
127.0.0.1:6379> get one
"1"
2、hash数据类型
3、list数据类型
ist 列表,它是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际上是个链表。
命令 | 描述 | 用法 |
---|---|---|
LPUSH | (1)将一个或多个值value插入到列表key的表头 (2)如果有多个value值,那么各个value值按从左到右的顺序依次插入表头 (3)key不存在,一个空列表会被创建并执行LPUSH操作 (4)key存在但不是列表类型,返回错误 | LPUSH key value [value …] |
LPUSHX | (1)将值value插入到列表key的表头,当且晋档key存在且为一个列表 (2)key不存在时,LPUSHX命令什么都不做 | LPUSHX key value |
LPOP | (1)移除并返回列表key的头元素 | LPOP key |
LRANGE | (1)返回列表key中指定区间内的元素,区间以偏移量start和stop指定 (2)start和stop都以0位底 (3)可使用负数下标,-1表示列表最后一个元素,-2表示列表倒数第二个元素,以此类推 (4)start大于列表最大下标,返回空列表 (5)stop大于列表最大下标,stop=列表最大下标 | LRANGE key start stop |
LREM | (1)根据count的值,移除列表中与value相等的元素 (2)count>0表示从头到尾搜索,移除与value相等的元素,数量为count (3)count<0表示从从尾到头搜索,移除与value相等的元素,数量为count (4)count=0表示移除表中所有与value相等的元素 | LREM key count value |
LSET | (1)将列表key下标为index的元素值设为value (2)index参数超出范围,或对一个空列表进行LSET时,返回错误 | LSET key index value |
LINDEX | (1)返回列表key中,下标为index的元素 | LINDEX key index |
LINSERT | (1)将值value插入列表key中,位于pivot前面或者后面 (2)pivot不存在于列表key时,不执行任何操作(3)key不存在,不执行任何操作 | LINSERT key BEFORE|AFTER pivot value |
LLEN | (1)返回列表key的长度(2)key不存在,返回0 | LLEN key |
LTRIM | (1)对一个列表进行修剪,让列表只返回指定区间内的元素,不存在指定区间内的都将被移除 | LTRIM key start stop |
RPOP | (1)移除并返回列表key的尾元素 | RPOP key |
RPOPLPUSH | 在一个原子时间内,执行两个动作:(1)将列表source中最后一个元素弹出并返回给客户端 (2)将source弹出的元素插入到列表desination,作为destination列表的头元素 | RPOPLPUSH source destination |
RPUSH | (1)将一个或多个值value插入到列表key的表尾 | RPUSH key value [value …] |
RPUSHX | (1)将value插入到列表key的表尾,当且仅当key存在并且是一个列表 (2)key不存在,RPUSHX什么都不做 | RPUSHX key value |
- 栈 通过命令 lpush+lpop
- 队列 命令 lpush+rpop
- 有限集合 命令 lpush+ltrim
- 消息队列 命令 lpush+rpop
root@5a1cc01437ff:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> keys *
1) "int1"
2) "string2"
3) "string1"
127.0.0.1:6379> del int1 string1 string2
(integer) 3
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush list1 1
(integer) 1
127.0.0.1:6379> lpush list1 2
(integer) 2
127.0.0.1:6379> keys *
1) "list1"
127.0.0.1:6379> llen list1
(integer) 2
127.0.0.1:6379> lindex list1 0
"2"
127.0.0.1:6379> lindex list1 1
"1"
127.0.0.1:6379> lpop list1
"2"
127.0.0.1:6379> lindex list1 0
"1"
127.0.0.1:6379> llen list1
(integer) 1
127.0.0.1:6379> lpush list1 2
(integer) 2
127.0.0.1:6379> rpop list1
"1"
4、set数据类型
Redis 的 set 是 string 类型的无序、不可重复
集合。
使用场景:利用集合的交并
集特性,比如在社交领域,我们可以很方便的求出多个用户的共同好友,共同感兴趣的领域等。
命令 | 描述 | 用法 |
---|---|---|
SADD | 添加:sadd set1 1 2 3 | SADD key number [member …] |
SCARD | 集合元素数量 | SCARD key |
SDIFF | 差集: sdiff set1 set2 集合set1与 set2的差集 | SDIFF key [key …] |
SDIFFSTORE | (1)和SDIFF类似,但结果保存到destination集合而不是简单返回结果集 (2) destination如果已存在,则覆盖 | SDIFFSTORE destionation key [key …] |
SINTER | 交集: sinter set1 set2 | SINTER key [key …] |
SINTERSTORE | (1)和SINTER类似,但结果保存早destination集合而不是简单返回结果集 (2)如果destination已存在,则覆盖 (3)destination可以是key本身 | SINTERSTORE destination key [key …] |
SISMEMBER | (1)判断member元素是否key的成员,0表示不是,1表示是 | SISMEMBER key member |
SMEMBERS | (1)返回集合key中的所有成员 (2)不存在的key被视为空集 | SMEMBERS key |
SMOVE | (1)原子性地将member元素从source集合移动到destination集合 (2)source集合中不包含member元素,SMOVE命令不执行任何操作,仅返回0 (3)destination中已包含member元素,SMOVE命令只是简单做source集合的member元素移除 | SMOVE source desination member |
SPOP | (1)移除并返回集合中的一个随机元素,如果count不指定那么随机返回一个随机元素 (2)count为正数且小于集合元素数量,那么返回一个count个元素的数组且数组中的元素各不相同 (3)count为正数且大于等于集合元素数量,那么返回整个集合 (4)count为负数那么命令返回一个数组,数组中的元素可能重复多次,数量为count的绝对值 | SPOP key [count] |
SRANDMEMBER | (1)如果count不指定,那么返回集合中的一个随机元素(2)count同上 | SRANDMEMBER key [count] |
SREM | 删除:移除集合中的一个或多个member元素,不存在的member将被忽略 | SREM key member [member …] |
SUNION | 并集:sunion set1 set2 | SUNION key [key …] |
SUNIONSTORE | (1)类似SUNION,但结果保存到destination集合而不是简单返回结果集 (2)destination已存在,覆盖旧值 (3)destination可以是key本身 | SUNION destination key [key …] |
127.0.0.1:6379> sadd set1 1 2 3
127.0.0.1:6379> sadd set 2 3 4 5
127.0.0.1:6379> sdiff set1 set
1) "1"
127.0.0.1:6379> sunion set1 set
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> sinter set set1
1) "2"
2) "3"
127.0.0.1:6379> srem set 4
(integer) 1
127.0.0.1:6379> smembers set
1) "2"
2) "3"
3) "5"
5、zset数据类型
命令 | 描述 | 用法 |
---|---|---|
ZADD | (1)将一个或多个member元素及其score值加入有序集key中 (2)如果member已经是有序集的成员,那么更新member对应的score并重新插入member保证member在正确的位置上 (3)score可以是整数值或双精度浮点数 | ZADD key score member [[score member] [score member] …] |
ZCARD | (1)返回有序集key的元素个数 | ZCARD key |
ZCOUNT | (1) 返回有序集key中,score值>=min且<=max的成员的数量 | ZCOUNT key min max |
ZRANGE | (1)返回有序集key中指定区间内的成员,成员位置按score从小到大排序 (2)具有相同score值的成员按字典序排列 (3)需要成员按score从大到小排列,使用ZREVRANGE命令( (4)下标参数start和stop都以0为底,也可以用负数,-1表示最后一个成员,-2表示倒数第二个成员 (5)可通过WITHSCORES选项让成员和它的score值一并返回 | ZRANGE key start stop [WITHSCORES] |
ZRANK | (1)返回有序集key中成员member的排名,有序集成员按score值从小到大排列 (2)排名以0为底,即score最小的成员排名为0 (3)ZREVRANK命令可将成员按score值从大到小排名 | ZRANK key number |
ZREM | (1)移除有序集key中的一个或多个成员,不存在的成员将被忽略 (2)当key存在但不是有序集时,返回错误 | ZREM key member [member …] |
ZREMRANGEBYRANK | (1)移除有序集key中指定排名区间内的所有成员 | ZREMRANGEBYRANK key start stop |
ZREMRANGEBYSCORE | (1)移除有序集key中,所有score值>=min且<=max之间的成员 | ZREMRANGEBYSCORE key min max |
127.0.0.1:6379> zadd sort1 1 a 3 b 2 c 4 d
(integer) 4
127.0.0.1:6379> zrange sort1 0 -1
1) "a"
2) "c"
3) "b"
4) "d"
127.0.0.1:6379> zcard sort1
(integer) 4
127.0.0.1:6379> zrem sort1 d
(integer) 1
127.0.0.1:6379> zrange sort1 0 -1
1) "a"
2) "c"
3) "b"
127.0.0.1:6379> zcount sort1 2 3
(integer) 2
127.0.0.1:6379>
6、stream数据类型
基于Redis的Stream类型的完美消息队列解决方案 https://zhuanlan.zhihu.com/p/60501638
Redis和专业的消息队列如何选择? https://zhuanlan.zhihu.com/p/367452637
Redis 当作队列来使用时,始终面临的 2 个问题:
Redis 本身可能会丢数据
面对消息积压,Redis 内存资源紧张,Kafka、RabbitMQ 这类消息队列就不一样了,它们的数据都会存储在磁盘上
如果你的业务场景足够简单,对于数据丢失不敏感,而且消息积压概率比较小的情况下,把 Redis 当作队列是完全可以的,Redis 相比于 Kafka、RabbitMQ,部署和运维也更加轻量。
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
- 简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
- 而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
关于redis讲的很好:https://www.jianshu.com/p/efae507f03cf
127.0.0.1:6379> xadd codehole * name laoqian age 30
"1624075334164-0"
127.0.0.1:6379> xadd codehole * name xiaoyu age 29
"1624075342341-0"
127.0.0.1:6379> xadd codehole * name xiaoqian age 1
"1624075348213-0"
127.0.0.1:6379> xlen codehole
(integer) 3
127.0.0.1:6379> xrange codehole - +
1) 1) "1624075334164-0"
2) 1) "name"
2) "laoqian"
3) "age"
4) "30"
2) 1) "1624075342341-0"
2) 1) "name"
2) "xiaoyu"
3) "age"
4) "29"
3) 1) "1624075348213-0"
2) 1) "name"
2) "xiaoqian"
3) "age"
4) "1"
127.0.0.1:6379> xrange codehole 1624075342341-0 +
1) 1) "1624075342341-0"
2) 1) "name"
2) "xiaoyu"
3) "age"
4) "29"
2) 1) "1624075348213-0"
2) 1) "name"
2) "xiaoqian"
3) "age"
4) "1"
127.0.0.1:6379> xrange codehole 1624075348213-0 +
1) 1) "1624075348213-0"
2) 1) "name"
2) "xiaoqian"
3) "age"
4) "1"
127.0.0.1:6379> xdel codehole 1624075348213-0
(integer) 1
127.0.0.1:6379> xrange codehole - +
1) 1) "1624075334164-0"
2) 1) "name"
2) "laoqian"
3) "age"
4) "30"
2) 1) "1624075342341-0"
2) 1) "name"
2) "xiaoyu"
3) "age"
4) "29"
127.0.0.1:6379> del codehole
(integer) 1