简介
Redis(Remote Dictionary Server、远程字典服务)在2009年发布,开发者 萨尔瓦多·桑菲利波(Salvatore Sanfilippo)是意大利开发者,他本想为自
己的公司开发一个用于替换MySQL的产品Redis,但是没有想到他把Redis开源后大受欢迎,短短几年,Redis就有了很大的用户群体,目前国内外
使用的公司有知乎网、新浪微博、GitHub等
redis是一个开源的、遵循BSD协议的、基于内存的而且目前比较流行的键值数据库(key-value database),是一个非关系型数据库,redis提供将内
存通过网络远程共享的一种服务,提供类似功能的还有memcache,但相比memcache,redis还提供了易扩展、高性能、具备数据持久性等功能。
Redis在高并发、低延迟环境要求比较高的环境使用量非常广泛,目前redis在DB-Engine月排行榜<https://db-engines.com/en/ranking> 中一
直比较靠前,而且一直是键值型存储类的首位Redis 典型应用场景
Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享
消息队列:ELK的日志缓存、部分业务的订阅发布系统
计数器:访问排行榜、商品浏览数等和次数相关的数值统计场景
缓存:数据库查询缓存、电商网站商品信息、新闻内容
微博/微信社交场合:共同好友、点赞评论等https://github.com/redis/redis #github
https://redis.io/docs/about #文档
缓存分类
本地缓存:将数据保存到本地,如浏览器、nginx等服务都有缓存,但无法多节点共享。
远程缓存:使用其它服务器的提供的服务作为缓存,多节点可以共享同一份缓存数据缓存的保存位置
内存 硬盘 数据缓存的特点
1.缓存的目的是为了调节速度不一致的两个或多个不同的服务的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用。
2.缓存不会一直有效,有过期时间(设置过期时间、删除缓存、或强制更新(如CDN强制更新缓存))。
3.缓存命中率:命中率越高,表明缓存的使用率越高,计算方式为 返回数据成功次数/请求次数,如总请求100次,返回成功85次,则850/1000=85%。
4.缓存最大空间:如Redis会设置总内存使用空间,超出将触发强制内存空间回收(删除部分历史数据)。
基于Redis的缓存业务架构

基于Redis的日志收集系统


提示: WARNING Memory overcommit must be enabled!
基于redis.service启动redis
root@ubuntu:/usr/local/src/redis-7.2.0/utils# pwd
/usr/local/src/redis-7.2.0/utils
root@ubuntu:/usr/local/src/redis-7.2.0/utils# cp ./systemd-redis_server.service本地命令行连接
远程命令行连接
图形化工具连接
https://github.com/qishibo/AnotherRedisDesktopManager/blob/master/README.zh-CN.md #下载地址
测试能否正常写入数据


python脚本
压测方式
redis-benchmark: Redis自带的压测工具,会对redis server进行常规的数据读写测试
inline 和 multibulk 是 Reids 定义的数据解析协
redis-benchmark 压测案例
字符串是使用最广泛的数据类型,字符串数据使用二进制保存,比如图片、视频等,默认一个字符串的value最大512M,可在redis.conf修改proto-max-bulk-len

示例
列表是一个双向可读写的管道,其头部是左侧尾部是右侧,一个列表最多可以包含2^32-1个元素即4294967295个元素。

提示:一般我们都是约定从右侧消费,俗称FIFO(先进先出),先进的数据先被右侧消费

示例
Set 是 String 类型的无序集合,集合中的成员是唯一的,这就意味着集合中不能出现重复的数据,可以在两个不同的集合中对数据进行对比并取值

示例
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,redis正是通过该分数来为集合中的成员进行从小到大的排序,有序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1), 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)

示例
hash是一个键值对(key=>value)的集合,一个hash数据里面可以包含多个key-value的数据,Redis中每个 hash 可以存储2^32 - 1 键值对(40多亿)

提示:As per Redis 4.0.0, HMSET is considered deprecated. Please use HSET in new code.
根据Redis 4.0.0,HMSET被视为已弃用。请在新代码中使用HSET。
在这之前HSET只能设置单个键值对,同时设置多个时必须使用HMSET。而现在HSET也允许接受多个键值对作参数了。
示例
生产者消费者模型示例
消息队列主要分为两种,分别是生产者消费者模式和发布者订阅者模式,这两种模式Redis都支持
在生产者消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至 指定的频道(channel)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步的操作就直接返回数据给外部请求, 如果还有下一步的操作就再将任务发布到另外一个频道,由另外一个消费者继续监听和处理。
生产者消费者模式下,多个消费者同时监听一个队里,但是一个消息只能被最先抢到消息的消费者消费,即消息任务是一次性读取和处理,此模式 在分布式业务架构中非常常用,比较常用的软件还有RabbitMQ、Kafka、RocketMQ、ActiveMQ等。

队列介绍
队列当中的 消息由不同的生产者写入也会有不同的消费者取出进行消费处理,但是一个消息一定是只能被取出一次也就是被消费 一次。

生产者发布消息
发布者订阅模型示例
在发布者订阅者模式下,发布者将消息发布到指定的channel里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机的广播模 式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。
此模式常用语群聊天、群通知、群公告等场景。
Subscriber:订阅者
Publisher:发布者
Channel:频道

cat /apps/redis/etc/redis.confRedis虽然是一个内存级别的缓存程序,也就是redis是使用内存进行数据的缓存的,但是其可以将内存的数据按照一 定的策略保存到硬盘上,从而实现数据持久保存的目的,目前redis支持三种不同方式的数据持久化保存机制,分别是RDB和AOF,以及(RDB+AOF)混合制持久化
1.RDB(*Redis* DataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点是执行速度比较快,缺点是可能会丢失从 上次快照到当前时间点之间未做快照的数据。
2.RDB实现的具体过程Redis从主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如 dump.rdb.temp,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保证每一次做RDB快照的 时候保存的数据都是完整的,因为直接替换RDB文件的时候可能会出现突然断电等问题而导致RDB文件还没有保存完整就突然关 机停止保存而导致数据丢失的情况,可以手动将每次生成的RDB文件进程备份,这样可以最大化保存历史数据RDB的优缺点
优点
缺点
基于RDB实现redis单机数据迁移
补充:
当AB主机的redis版本不一致,即rdb版本不一致的时候会报错
2754462:M 07 Sep 16:08:00.458 # Can't handle RDB format version 11
2754462:M 07 Sep 16:08:00.458 # Fatal error loading the DB: Invalid argument. Exiting.
AOF模式的简介
1.AOF:按照操作顺序依次将操作添加到指定的日志文件当中,特点是数据安全性相对较高,缺点是即使有些操作是重复的也会全部记录。
2.AOF和RDB一样使用了写时复制机制,AOF默认为每秒钟fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障的话顶多也就丢失1秒钟之内的数据,也可以设置不同的fsync策略,或者设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用户的正常请求而不受到写入AOF文件的IO影响。AOF的优缺点
Redis 4.0支持AOF+RDB混合模式,配置文件开启 aof‐use‐rdb‐preamble yes
混合模式的执行过程
RDB-AOF混合持久化体现在aofrewrite时,先以RDB格式来保存全量数据,即Redis 会先把当前的内存数据以RDB方式写入到 AOF文件,同时把当前的命令记录到重写缓冲区中,最后RDB完成后再把缓冲区中的命令以追加AOF的形式存在AOF文件中。
混合模式的优缺点
使用示例
ACL(Access Control List)即访问控制列表
Redis从6.0版本开始支持的访问权限控制 方式 通过ACL,可以控制客户端对不同redis命令和数据的访问权限
基于ACL的访问控制可以保证redis中的数据更加安全可靠
相比简单的密码认证,它提供了更丰富灵活的权限管理功能

启用和禁用用户
允许或禁止访问某些Key
允许和禁止调用命令
ACL示例
示例一:默认ACL
示例二:通过ACL为user qbn 设置任意权限
示例三:通过ACL为user zhangsan设置指定命令权限
上面通过命令设置的权限,重启redis会失效,所以需要写到配置文件使其永久生效
通过redis.conf定义ACL规则
通过外部文件定义ACL规则
补充:所以这个时候远程是访问不了的,因为触发了redis安全模式,要么关闭安全模式要么设置密码
redis-dump可以实现redis跨版本数据迁移
安装redis-dump
导数据
验证数据
测试基于redis-shake实现redis数据迁移**
https://blog.51cto.com/u_13626676/6041309 #redis-shak使用说明
https://github.com/tair-opensource/RedisShake #redis-shake项目地址
版本要求
go version >=go1.17
ubuntu下载GO
root@ubuntu20:~# wget -c https://go.dev/dl/go1.20.linux-amd64.tar.gz验证go版本
root@ubuntu20:~# go version
go version go1.20 linux/amd64安装redis-shake
编写toml文件
其他高级写法参考:https://tair-opensource.github.io/RedisShake/zh/guide/config.html
root@ubuntu20:~/RedisShake/bin# pwd
/root/RedisShake/bin启动 redis-shake
root@ubuntu20:~/RedisShake/bin# ./redis-shake rdb_20230907.toml
提示:
此时可以看到有数据一直在持续同步,开两个终端测试,可以看到一有数据写入,立马会进行同步。可以用ctrl+c暂停同步。
验证数据
[root@centos7 ~]# vi /etc/yum.repos.d/redis.repo
[Redis]
name=Redis
baseurl=http://packages.redis.io/rpm/rhel7
enabled=1
gpgcheck=1
[root@centos7 ~]# curl -fsSL https://packages.redis.io/gpg > /tmp/redis.key #下载key文件
[root@centos7 ~]# sudo rpm --import /tmp/redis.key #导入key
[root@centos7 ~]# sudo yum install epel-release
[root@centos7 ~]# yum list redis-stack-server --showduplicates | sort -r #Redis Stack 是 Redis 的扩展,它添加了现代数据模型和处理引擎,以提供完整 的开发人员体验
[root@centos7 ~]# yum install redis-stack-server-7.2.0_v0-1.rhel7 -y #安装指定版本,不加的话默认最新版本
[root@centos7 ~]# systemctl restart redis-stack-server.serviceroot@ubuntu22-04-2:~# curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
root@ubuntu22-04-2:~# sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
root@ubuntu22-04-2:~#echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
root@ubuntu22-04-2:~# sudo apt-get update
root@ubuntu22-04-2:~# apt-cache madison redis-server
root@ubuntu22-04-2:~# apt-cache madison redis-stack-server
root@ubuntu22-04-2:~# apt install redis-serverroot@ubuntu:~# apt update
root@ubuntu:~# apt install iproute2 ntpdate tree libssl-dev gcc openssh-server lrzsz \
openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev ntpdate tcpdump telnet \
traceroute iotop unzip zip make libsystemd-dev pkg-config
root@ubuntu:~# cd /usr/local/src/
root@ubuntu:/usr/local/src# wget http://download.redis.io/releases/redis-7.2.0.tar.gz
root@ubuntu:/usr/local/src# tar xvf redis-7.2.0.tar.gz
root@ubuntu:/usr/local/src# cd redis-7.2.0/
make test
root@ubuntu:/usr/local/src/redis-7.2.0# make USE_SYSTEMD=yes PREFIX=/apps/redis install
root@ubuntu:/usr/local/src/redis-7.2.0# ll /apps/redis/bin/
----修改内核参数----
root@ubuntu:/usr/local/src/redis-7.2.0# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
root@ubuntu:/usr/local/src/redis-7.2.0# sysctl -p
vm.overcommit_memory = 1
----重启机器,确保机器重启之后内核参数依旧有效----
root@ubuntu:~# reboot
root@ubuntu:~# redis-server /apps/redis/etc/redis.conf
1094:C 05 Sep 2023 09:34:17.000 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1094:C 05 Sep 2023 09:34:17.000 * Redis version=7.2.0, bits=64, commit=00000000, modified=0, pid=1094, just started
1094:C 05 Sep 2023 09:34:17.000 * Configuration loaded
1094:M 05 Sep 2023 09:34:17.001 * Increased maximum number of open files to 10032 (it was originally set to 1024).
1094:M 05 Sep 2023 09:34:17.001 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 7.2.0 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 1094
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
1094:M 05 Sep 2023 09:34:17.006 * Server initialized
1094:M 05 Sep 2023 09:34:17.007 * Ready to accept connections tcp----编写service文件----
root@ubuntu20:/usr/local/src/redis-7.2.0/utils# vi /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis data structure server
Documentation=https://redis.io/documentation
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd --daemonize no
LimitNOFILE=10032
NoNewPrivileges=yes
Type=notify
TimeoutStartSec=infinity
TimeoutStopSec=infinity
UMask=0077
User=redis #配置了普通用户,所以需要把对应的目录权限改成普通用户权限
Group=redis #配置了普通用户组
WorkingDirectory=/apps/redis
[Install]
WantedBy=multi-user.targetroot@ubuntu:/usr/local/src/redis-7.2.0/utils# groupadd -g 2023 redis && useradd -u 2023 -g 2023 redis -s /sbin/nologin
root@ubuntu:/usr/local/src/redis-7.2.0/utils# chown redis.redis -R /apps/redis/
root@ubuntu:/usr/local/src/redis-7.2.0/utils# systemctl daemon-reload
root@ubuntu:/usr/local/src/redis-7.2.0/utils# systemctl daemon-reload && systemctl enable redis.service && systemctl restart redis.serviceroot@ubuntu:~# redis-cli --help
redis-cli -h HOSTNAME/IP -p PORT -a PASSWORD --user USER
root@ubuntu:~# /apps/redis/bin/redis-cli
127.0.0.1:6379> info
# Server
redis_version:7.2.0
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:af067dcb17a8e211
redis_mode:standalone
os:Linux 5.4.0-159-generic x86_64
....root@ubuntu:~# vi /apps/redis/etc/redis.conf
....
bind 0.0.0.0 #设置监听地址地址,可以用空格隔开设置多个监听IP
....
requirepass 123123 #设置连接的密码
....
root@ubuntu:~# systemctl restart redis
root@ubuntu:~# redis-cli -h 192.168.20.247
192.168.20.247:6379> auth 123123
OK
192.168.20.247:6379>192.168.20.247:6379> select 0
OK
192.168.20.247:6379> keys *
1) "name"
192.168.20.247:6379> get name
"luningbo"
192.168.20.247:6379>
提示:DB在逻辑上隔离不同项目的数据,比如上面的db0的key “name”,只能存在一个,如果在db1则可以重复
cat redis-client.sh
#!/bin/bash
NUM=`seq 1 100000` for i in ${NUM};do
redis-cli -h 127.0.0.1 set key-${i} value-${i}
echo "key-${i} value-${i} 写入完成"
done
echo "十万个key写入到Redis完成
apt install python3-pip
cat redis-client.py
#!/bin/env python
import redis
import time
pool = redis.ConnectionPool(host="127.0.0.1", port=6379,password="")
r = redis.Redis(connection_pool=pool)
for i in range(100):
r.set("key%d" % i,"value%d" % i)
#time.sleep(0.1)
data=r.get("key%d" % i)
data=data.decode("utf-8")
print(data)CONFIG:config 命令用于查看当前redis配置、以及不重启更改redis配置等
127.0.0.1:6379> CONFIG set maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG get maxmemory #查看某个配置项
maxmemory
8589934592
127.0.0.1:6379> CONFIG GET * #获取当前所有配置
repl-diskless-sync-max-replicas
0
127.0.0.1:6379> CONFIG SET requirepass 123456
O
INFO:显示当前节点redis运行状态信息
DEL: 删除指定的key
SELECT:切换数据库,等于MySQL的use DBNAME指令
keys::查看当前库下的所有key:
BGSAVE:手动在后台执行RDB持久化操作
DBSIZE: 返回当前库下的所有key 数量
FLUSHDB:强制清空当前库中的所有key
FLUSHALL:强制清空当前redis服务器所有数据库中的所有key,即删除所有数据redis-benchmark --help
redis-benchmark [option] [option value
-h 指定Redis 地址
-p 指定Redis 端口
-s 使用 socket文件连接
-c 指定并发连接数
-n 指定请求总数
-d 以字节的形式指定 SET/GET 值的数据大小
-k 是否开启会话保持,1 表示 keepalive;0 表示 reconnect,默认为 1。
-r SET/GET/INCR 使用随机 key, SADD使用随机值,ZADD使用随机值和评分
-P 是否使用Pipeline 请求
-q 静默模式,仅显示测试结果的 query/sec 值
--csv 将测试结果转换为 CSV 格式输出
-l(小写L) 生成循环,永久执行测试。
-t 运行以逗号分隔的单次多测试命令列表
-I(大写i) 空闲模式,打开 N 个空闲连接并等待连# redis-benchmark -h 127.0.0.1 -p 6379 -n -a 123123 1000 -c 200 #并发200,累计1000个请求,加-q仅显示测试结果的 query/sec 值
Summary: #测试结果摘要
throughput summary: 90909.09 requests per second #吞吐量统计,每秒完成客户端请求数90909.09
latency summary (msec): #延迟统计(毫秒)
avg min p50 p95 p99 max
1.236 0.376 1.007 2.431 2.591 2.63
# redis-benchmark -t set -n 1000 -c 100 #压测单个命令,累计1000个请求并发100
# redis-benchmark -t ping,set,get -n 100 --csv #压测多个命令,并以csv格式输出
# redis-benchmark -h 127.0.0.1 -p 6379 -n 1000 -c 200 -q #默认压测,并仅显示测试结果的 query/sec 值
# redis-benchmark -h 127.0.0.1 -p 6379 -t set -d 1024 -n 1000 -r 1000 -c 200 #指定每个key的大小为1024字节(1k)
# redis-benchmark -r 100 -n 10000 lpush mylist __rand_int__ #测试向指定列表mylist 写入总数(-n 10000)个随机数据,每个数据随机在(-r
100)以内选择127.0.0.1:6379> set key abc #添加一个key
OK
127.0.0.1:6379> get key #获取key的内容
"abc"
127.0.0.1:6379> type key #查看key的类型
string
127.0.0.1:6379> set name1 lnb ex 100 #设置key自动过期时间
OK
127.0.0.1:6379> get name1
"lnb"
127.0.0.1:6379> ttl name1 #查看key的剩余过期时间
(integer) 77
127.0.0.1:6379> keys * #查看所有key
1) "zhangsan-key"
2) "name1"
3) "key"
4) "xxx"
127.0.0.1:6379> del xxx #删除一个key
(integer) 1
127.0.0.1:6379> mset key-1 111 key-2 222 #批量创建多个key
OK
127.0.0.1:6379> mget key-1 key-2 #批量获取多个key
1) "111"
2) "222"
127.0.0.1:6379> del key-1 key-2 #删除多个key
(integer) 2
127.0.0.1:6379> append key lnb #向key追加数据
(integer) 6
127.0.0.1:6379> get key #查看key内容验证
"lnbqbn"
127.0.0.1:6379> strlen key #返回value的长度
(integer) 6
127.0.0.1:6379> exists key #判断key是否存在
(integer) 1
127.0.0.1:6379> set num 10 #数值递增
OK
127.0.0.1:6379> incr num
(integer) 11
127.0.0.1:6379> incr num
(integer) 12
127.0.0.1:6379> incr num
(integer) 13
127.0.0.1:6379> get num
"13"
127.0.0.1:6379> get num #数值递减
"13"
127.0.0.1:6379> decr num
(integer) 12
127.0.0.1:6379> decr num
(integer) 11
127.0.0.1:6379> get num
"11"
127.0.0.1:6379> persist key #设置key永不过期
(integer) 1
127.0.0.1:6379> TTL key
(integer) -1
ttl #查看key的剩余生存时间
-1 #负一为永不过期,默认创建的key是永不过期,重新对key赋值,也会从有剩余生命周期变成永不过期
-2 #为没有此key
num #key的剩余有效期
127.0.0.1:6379> expire key 5555 #设置key到期时间,不修改值
(integer) 1
127.0.0.1:6379> ttl key
(integer) 5553
127.0.0.1:6379> ttl key
(integer) 5552127.0.0.1:6379> LPUSH list aaa bbb ccc #根据顺序逐个写入list,从左到右写
(integer) 3
127.0.0.1:6379> TYPE list #获取列表类型
list
127.0.0.1:6379> LPUSH list ddd #从列表左侧推入一个值
(integer) 4
127.0.0.1:6379> LLEN list #获取列表长度
(integer) 4
127.0.0.1:6379> RPOP list #右侧消费
"aaa"
127.0.0.1:6379> RPOP list
"bbb"
127.0.0.1:6379> RPOP list
"ccc"
127.0.0.1:6379> RPOP list
"ddd"
127.0.0.1:6379> RPOP list
(nil)
127.0.0.1:6379> LPUSH list aaa bbb ccc
(integer) 3
127.0.0.1:6379> LPOP list #左侧消费
"ccc"
127.0.0.1:6379> LPOP list
"bbb"
127.0.0.1:6379> LPOP list
"aaa"
127.0.0.1:6379> LRANGE list 1 2 #获取指定范围的值
1) "bbb"
2) "aaa"
127.0.0.1:6379> LINDEX list -1 #获取倒第一个数的值
"aaa"
127.0.0.1:6379> LINDEX list -2 #获取倒第二个数的值
"bbb"127.0.0.1:6379> SADD set1 v1 #生成集合key
(integer) 1
127.0.0.1:6379> SADD set2 v2 v4
(integer) 2
127.0.0.1:6379> TYPE set1 #查看类型
set
127.0.0.1:6379> TYPE set2
set
127.0.0.1:6379> SADD set1 v2 v3 v4 #向集合set1添加一个或多个成员
(integer) 3
127.0.0.1:6379> SADD set1 v2 #返回值为0表示0个数据操作成功
(integer) 0
127.0.0.1:6379> SMEMBERS set1 #查看集合所有数据
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> SMEMBERS set2 #查看集合所有数据
1) "v2"
2) "v4"
127.0.0.1:6379> SCARD set1 #获取集合长度
(integer) 4
127.0.0.1:6379> SDIFF set1 set2 #获取set1和set2的差集
1) "v1"
2) "v3"
127.0.0.1:6379> SINTER set1 set2 #获取set1和set2的交集
1) "v2"
2) "v4"
127.0.0.1:6379> SUNION set1 set2 #获取set1和set2的并集
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> SISMEMBER set1 v1 #判断v1是否是集合set1的成员
(integer) 1
127.0.0.1:6379> SISMEMBER set1 v5 #返回0表示不是
(integer) 0127.0.0.1:6379> ZADD zset1 1 v1 #生成有序集合
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> ZADD zset1 3 v3
(integer) 1
127.0.0.1:6379> ZADD zset1 4 v4
(integer) 1
127.0.0.1:6379> TYPE zset1 #获取key类型
zset
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 3 v3 4 v4 5 v5 #一次生成多个数据
(integer) 5
127.0.0.1:6379> TYPE zset2
zset
127.0.0.1:6379> ZCARD zset1 #查看有序集合长度
(integer) 4
127.0.0.1:6379> ZCARD zset2
(integer) 5
127.0.0.1:6379> ZRANGE zset1 1 3 #基于索引返回数值
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> ZRANGE zset1 2 2
1) "v3"
127.0.0.1:6379> ZRANK zset1 v3 #返回某个数值的索引
(integer) 2
127.0.0.1:6379> ZRANK zset1 v1
(integer) 0
----写入不通评分的数据,查看排列----
root@ubuntu20:~# redis-cli --raw #--raw 指定原生数据,不做转义
127.0.0.1:6379> auth 123123
OK
127.0.0.1:6379> ZADD paihangbang 90 nezha 199 zhanlang 60 zhuluoji 30 gangtiexia 99 封神榜
5
127.0.0.1:6379> ZRANGE paihangbang 0 -1 #显示集合内所有的key,升序排序
gangtiexia
zhuluoji
nezha
封神榜
zhanlang
127.0.0.1:6379> ZREVRANGE paihangbang 0 -1 withscores #显示指定集合内所有key和得分情况,并按照降序排序,
zhanlang
199
封神榜
99
nezha
90
zhuluoji
60
gangtiexia
30127.0.0.1:6379> HSET hash1 name tom age 18 #生成hash key
2
127.0.0.1:6379> TYPE hash1
hash
----获取hash key字段值----
127.0.0.1:6379> HGET hash1 name
tom
127.0.0.1:6379> HGET hash1 age
18127.0.0.1:6379> HMSET hash3 name tom age 20
OK
127.0.0.1:6379> HKEYS hash3
name
age
127.0.0.1:6379> HMGET hash3 name age
tom
20
127.0.0.1:6379> HGETALL hash3
name
tom
age
20
127.0.0.1:6379> hkeys hash4 #删除hash4的key字段
1) "name"
2) "age"
127.0.0.1:6379> hdel hash4 name
(integer) 1
127.0.0.1:6379> keys hash*
1) "hash1"
2) "hash3"
3) "hash4"
127.0.0.1:6379> hdel hash4 age #删除hash4的第二个hash key字段
(integer) 1
127.0.0.1:6379> keys hash* #当一个key的所有字段都被删除,key也被删除
1) "hash1"
2) "hash3"#从管道的左侧写入
127.0.0.1:6379> LPUSH channel1 msg1 1
127.0.0.1:6379> LPUSH channel1 msg2
2
127.0.0.1:6379> LPUSH channel1 msg3
3
127.0.0.1:6379> LPUSH channel1 msg4
4
127.0.0.1:6379> LPUSH channel1 msg5
5
查看队列所有消息:
127.0.0.1:6379> LRANGE channel1 0 -1
msg5
msg4
msg3
msg2
msg1
#从管道的右侧消费
127.0.0.1:6379> RPOP channel1
msg1
127.0.0.1:6379> RPOP channel1
msg2
127.0.0.1:6379> RPOP channel1
msg3
127.0.0.1:6379> RPOP channel1
msg4
127.0.0.1:6379> RPOP channel1
msg5
127.0.0.1:6379> RPOP channel1
再次验证队列消息:
127.0.0.1:6379> LRANGE channel1 0 -1 #队列中的消息已经被已全部消费完毕#订阅者订阅指定的频道,频道不存在也可以订阅:
127.0.0.1:6379> SUBSCRIBE channel1
subscribe
channel1
1
发布者在另外一个终端发布消息:
127.0.0.1:6379> PUBLISH channel1 test1
(integer) 1
127.0.0.1:6379> PUBLISH channel1 test2
(integer) 1
各订阅者验证消息:
127.0.0.1:6379> SUBSCRIBE channel1
subscribe
channel1
1
message
channel1
test1
message
channel1
test2
message
同时订阅多个频道:
127.0.0.1:6379> SUBSCRIBE channel1 channel2
subscribe
channel1
1
subscribe
channel2
2
基于正则订阅指定频道:
127.0.0.1:6379> PSUBSCRIBE chann*
psubscribe
chann*
1
订阅匹配的频道:
127.0.0.1:6379> PSUBSCRIBE *
psubscribe
*
1################################## NETWORK #####################################
bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听IP
protected-mode no#redis3.2 之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,远程访问将提示警告信息并拒绝远程访问
port 6379#监听端口
tcp-backlog 511#三次握手的时候,Redis server收到的的客户端请求在未建立好连接之前的未连接队列长度
unixsocket /apps/redis/run/redis.sock
unixsocketperm 700 #redis socket文件路径,需要对目录有写入权限,且保证有这个路径
timeout 0 #客户端和Redis服务端的会话超时时间,即多少秒之后Redis会和客户端断开连接,默认是0,表示永不超时。
tcp-keepalive 300#Redis server定时向client发送tcp_ack包来探测client是否存活,即每间隔多少秒探测客户端是否存活
################################# GENERAL(常规) #####################################
daemonize yes# 以守护进程运行,会生成一个pid文件记录当前进程的pid
supervised auto#可以设置通过upstart和systemd管理Redis守护进程,centos 7以后都使用systemd
pidfile /apps/redis/run/redis_6379.pid#pid文件路径
loglevel notice #日志级别
----A主机先生成数据----
root@ubuntu20:/apps/redis/data# redis-cli
127.0.0.1:6379> auth 123123
OK
127.0.0.1:6379> set zhangsan xxx
OK
127.0.0.1:6379> keys *
1) "zhangsan"
2) "aa"
B主机停止redis服务
root@ubuntu20:~# systemctl stop redis-server.service
复制A主机的rdb文件到B主机
root@ubuntu20:/apps/redis/data# scp ./dump_6379.rdb root@45.15.10.203:/var/lib/redis/dump.rdb
root@ubuntu20:/apps/redis/data# ll
drwx------ 2 redis redis 4096 Sep 7 16:00 appendonlydir/
-rw------- 1 redis redis 100 Sep 7 16:01 dump_6379.rdb
root@ubuntu20:/apps/redis/data# scp ./dump_6379.rdb root@45.15.10.203:/var/lib/redis/dump.rdb
B主机重启redis服务,验证数据
root@ubuntu20:~# systemctl restart redis-server.service
root@ubuntu20:~# redis-cli
127.0.0.1:6379> keys *
1) "aa"
2) "zhangsan"
127.0.0.1:6379> ----开启redis数据持久化混合模式----
root@ubuntu20:~# vim /apps/redis/etc/redis.conf
....
aof-rewrite-incremental-fsync yes
....
systemctl restart redis.service
root@ubuntu20:~# ll /apps/redis/data/appendonlydir/
-rw------- 1 redis redis 88 Sep 6 10:29 appendonly.aof.1.base.rdb
-rw------- 1 redis redis 2369 Sep 7 13:31 appendonly.aof.1.incr.aof
-rw------- 1 redis redis 88 Sep 6 10:29 appendonly.aof.manifest
---AOF文件的保存路径,同RDB的路径一致----
root@ubuntu20:~# vim /apps/redis/etc/redis.conf
....
################################ SNAPSHOTTING################################
dir /apps/redis/data/
....
注意:AOF的优先级比RDB高127.0.0.1:6379> acl help
1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are:
2) LOAD #从ACL文件中重新载入用户信息
3) SAVE #保存当前的用户配置信息到ACL文件
4) LIST #以配置文件格式显示用户详细信息
5) USERS #列出所有已注册的用户名
6) SETUSER <username> [attribs ...] #创建或则修改一个用户
7) GETUSER <username> #得到一个用户的详细信息
8) DELUSER <username> [...] #删除列表中的用户
9) CAT #列出可用的ACL种类,如ACL CAT等内置的方法类
10) CAT <category> #列出指定类别中的命令,如ACL CAT READ
11) GENPASS [<bits>] #自动生成一个安全的用户密码.
12) WHOAMI #返回当前的连接用户名称+<command>:将命令添加到用户可以调用的命令列表中,多个命令用空格隔开
-<command>:将命令从用户可以调用的命令列表中移除
+@<category>:允许用户调用 <category> 类别中的所有命令,有效类别为@admin,@set,@sortedset等(使用命令acl cat查看),可通过调用ACL CAT命令查看完整列表,特殊类别@all表示所有命令,包括当前和未来版本中存在的所有命令
-@<category>:禁止用户调用<category> 类别中的所有命令
+<command>|subcommand:允许使用已禁用命令的特定子命令
+<command>|subcommand:允许使用已禁用命令的特定子命令
allcommands等于+@all:包括当前存在的命令以及将来通过模块加载的所有命令
nocommands等于-@all:禁止调用所有命令127.0.0.1:6379> acl list
1) "user default on nopass sanitize-payload ~* &* +@all"
----默认ACL账户简介----
user default #当前用户名default
on #账户已经启用
nopass #没有设置密码
~ * #能访问所有的key(~ *)
* #能访问所有的发布/订阅(Pub/Sub)频道
+@all #能执行所有的命令127.0.0.1:6379> acl setuser qbn on ~* &* +@all >123123
OK
127.0.0.1:6379> acl list
1) "user default on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
2) "user qbn on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
----远程通过qbn用户登录redis----
[root@host-45-15-10-203 ~]# redis-cli -h 45.15.10.135 --user qbn -a 123123
45.15.10.135:6379>
45.15.10.135:6379> acl whoami
"qbn"
45.15.10.135:6379> set key abc
OK
45.15.10.135:6379> get key
"abc"127.0.0.1:6379> acl setuser zhangsan on ~* &* +get +set >123123
OK
127.0.0.1:6379> acl list
1) "user default on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
2) "user qbn on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
3) "user zhangsan on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* -@all +get +set"
----使用zhangsan用户远程登录redis----
----注意老版本的redis没有--user的参数,所以只能用auth命令登录对应用户----
[root@host-45-15-10-203 ~]# redis-cli -h 45.15.10.135
45.15.10.135:6379> auth zhangsan 123123
OK
45.15.10.135:6379> set zhangsan-key aaa
OK
45.15.10.135:6379> get zhangsan-key
"aaa"
45.15.10.135:6379> del zhangsan-key #验证无删除权限
(error) NOPERM User zhangsan has no permissions to run the 'del' command
45.15.10.135:6379> acl whoami #验证无权限
(error) NOPERM User zhangsan has no permissions to run the 'acl|whoami' commandroot@ubuntu20:~# vi /apps/redis/etc/redis.conf
....
user qbn on ~* &* +@all >123123
user zhangsan on ~* &* +get +set >123123
acllog-max-len 128 #大概放在这行附近就行
....
root@ubuntu20:~# systemctl restart redis.service
----验证重启是否失效----
root@ubuntu20:~# redis-cli
127.0.0.1:6379> auth 123123
OK
127.0.0.1:6379> acl list
1) "user default on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
2) "user qbn on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
3) "user zhangsan on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* -@all +get +set"----创建自定义acl文件----
root@ubuntu20:~# cat /apps/redis/etc/uers.acl
user qbn on ~* &* +@all >123123
user zhangsan on ~* &* +get +set >123123
----编辑redis.conf,设置自定义acl文件指定路径----
root@ubuntu20:~# vi /apps/redis/etc/redis.conf
# aclfile /etc/redis/users.acl
aclfile /apps/redis/etc/user.acl
----本地验证权限----
root@ubuntu20:~# redis-cli #因为用了自定义acl文件,所以默认default用户没有密码
127.0.0.1:6379> acl list
1) "user default on nopass sanitize-payload ~* &* +@all"
2) "user qbn on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* +@all"
3) "user zhangsan on sanitize-payload #96cae35ce8a9b0244178bf28e4966c2ce1b8385723a96a6b838858cdd6ca0a1e ~* &* -@all +get +set"echo "user default on ~* &* +@all >123123" >> /apps/redis/etc/user.acl
----远程登录验证zangsan权限----
[root@host-45-15-10-203 ~]# redis-cli -h 45.15.10.135
45.15.10.135:6379> auth zhangsan 123123
OK
45.15.10.135:6379> get zhangsan-key
"aaa"
45.15.10.135:6379> del zhangsan-key
(error) NOPERM User zhangsan has no permissions to run the 'del' command----查看redis版本----
root@ubuntu20:~# redis-cli
127.0.0.1:6379> info
# Server
redis_version:5.0.7
---安装ruby(任意一台主机装即可)----
root@ubuntu20:~# apt install ruby ruby-dev gcc
----安装redis-dump----
root@ubuntu20:~# gem install redis-dump
root@ubuntu20:~# redis-dump --help ----把数据导出到本地----
root@ubuntu20:~# redis-dump -a 123123 -u 127.0.0.1:6379 > /tmp/redis.json
root@ubuntu20:~# cat /tmp/redis.json
{"db":0,"key":"zhangsan","ttl":-1,"type":"string","value":"xxx","size":3}
{"db":0,"key":"aa","ttl":-1,"type":"string","value":"bb","size":2}
{"db":2,"key":"name","ttl":-1,"type":"string","value":"zhangsan","size":8}
----在本地把数据远程导入到其他机器----
root@ubuntu20:~# cat /tmp/redis.json | redis-load -a 123123 -u 45.15.10.203:6379
提示:也可以把导出的json文件scp到远程机器,再远程本地导入
A主机:scp /tmp/redis.json root@45.15.10.203:/tmp/redis.json
B主机:cat /tmp/redis.json | redis-load -a 123123 -u 127.0.0.1:6379----在被导入机器验证数据----
root@ubuntu20:~# redis-cli
127.0.0.1:6379> auth 123123
OK
127.0.0.1:6379> keys *
1) "aa"
2) "zhangsan"
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> keys *
1) "name"
127.0.0.1:6379[2]> root@ubuntu20:~# git clone https://github.com/alibaba/RedisShake
root@ubuntu20:~# cd RedisShake
root@ubuntu20:~/RedisShake# sh build.sh
root@ubuntu20:~/RedisShake# ll
drwxr-xr-x 4 root root 4096 Feb 6 16:40 bin/ ### build.sh成功生成bin目录
-rwxr-xr-x 1 root root 966 Feb 6 16:32 build.sh*
drwxr-xr-x 3 root root 4096 Feb 6 16:32 cmd/
drwxr-xr-x 2 root root 4096 Feb 6 16:32 filters/
drwxr-xr-x 8 root root 4096 Feb 6 16:34 .git/
drwxr-xr-x 4 root root 4096 Feb 6 16:32 .github/
-rw-r--r-- 1 root root 55 Feb 6 16:32 .gitignore
-rw-r--r-- 1 root root 424 Feb 6 16:32 go.mod
-rw-r--r-- 1 root root 3232 Feb 6 16:32 go.sum
drwxr-xr-x 13 root root 4096 Feb 6 16:32 internal/
-rw-r--r-- 1 root root 1078 Feb 6 16:32 license.txt
-rw-r--r-- 1 root root 3499 Feb 6 16:32 README.md
-rw-r--r-- 1 root root 1924 Feb 6 16:32 restore.toml
-rw-r--r-- 1 root root 1918 Feb 6 16:32 scan.toml
drwxr-xr-x 4 root root 4096 Feb 6 16:32 scripts/
drwxr-xr-x 5 root root 4096 Feb 6 16:32 test/
root@ubuntu20-171:RedisShake# cd bin/
root@ubuntu20-171:bin# ll
root@ubuntu20:~/RedisShake/bin# ll
-rwxr-xr-x 1 root root 11437724 Sep 7 19:38 redis-shake* #可执行文件
-rw-r--r-- 1 root root 2671 Sep 7 19:38 shake.toml # 参数模板----到目的主机验证----
root@ubuntu20:~# redis-cli
127.0.0.1:6379> auth 123123
OK
127.0.0.1:6379> keys *
1) "bbb"
2) "ccc"
3) "ddd"
4) "aa"
5) "qbn"
6) "zhangsan"
7) "aaa"
127.0.0.1:6379>