redis基本
redis
缓存机制比较重要
关系型与非关系型数据库的区别:数据的结构不同
主从机制:MHA架构,选择binlog同步数据最多的节点进行提升到主节点
没有说基于ACID的特性
ACID:原子性(要么事务提交成功,要么失败),一定会有结果,一个个事务之间都是隔离的
一致性:提交了一定会保存到表中,不会出现数据丢失,数据守恒
隔离性:事务还没提交前,看不到数据,数据隔离
持久型:事务提交,永久保存
##面试重点
事务的4个特性
A:原子性,整个事务中要么全部执行成功,要么全部失败回滚,唯一性,不可分割的步骤
C:一致性,必须遵循能量守恒定律,比如银行转账1000块,对方银行必定增加1000块,不存在转账后,1000块没了,双方平衡,双方加起来钱还是一致的
I:隔离性,即事务还未提交的时候,(还没显示结果),别人看不到你提交了一半的事务的过程--->dirty data脏数据,没有具体落地的东西
D:持久型,一旦事务提交,修改永久保存在数据库中
应用场景:大型数据存储场景,一般都是非结构化的数据,互联网场景,需要用到redis做大量的数据缓存--->高并发的场景下比较合适
基于keyvalue的数据类型
分布式系统的特点
常见的nosql类型
nosql类型 | 作用 |
---|---|
MongoDB | 文档型,以json格式存储数据的,通常用于日志的存储,日志作为一份文本可以以json格式,文档型document |
key-value(redis、memcached) | 键值对的数据,通过key可以迅速找到他的value值,可能还存了metadata元数据等,缓存数据库 |
elasticsearch(ES) | 数据库,索引代表一个库,可以进行日志转储到ES中,logstash转储,kibana提供图形化界面查看日志,例如查看json文件 |
好的底层系统开发语言:C语言,但是开发难度较高
golang语言:难度偏低,比较友好,能够开发底层的东西,应用,代码,功能,二次开发,基于Prometheus开发等
一般的使用场景:MySQL+redis,sql server+redis等适用场景,弥补MySQL的缺陷,处理大并发消息过来的时候,可以调大最大并发数,且redis的成本较低,小规格就能够承担大负载
redis特点+处理请求的逻辑:单线程
所有数据都在内存里,所以为什么Redis只需要买内存的规格,和多节点抗并发就行了,而不需要买磁盘,所有的数据都写入到redis服务器的内存中,加快请求的处理和响应,加速
处理并发高,基本的数据处理还是基于队列来进行
一般都作为关系型数据库的缓存,MySQL---redis,用户访问先到redis,再到MySQL后端:先缓存,再后端磁盘
redis集群版实现功能,也提供proxy代理节点,用户访问到redis的集群proxy,对外提供域名
redis处理消息的方式:单线程,排到队列处理+内存内处理请求数据,基于key-value键值对,也不存在多人同时访问这个数据需要加写锁等
比如说秒杀场景,可以使用redis单线程队列,取前100个人下单成功的就行,不需要使用MySQL来处理这些并发的事务,效率太低
请求:提交事务,下订单,修改表数据,客户新下一个订单等
多线程:多个用户同时并发处理
redis 6.0以前:单线程处理,现在企业使用比较多也是5.0左右,目前有5、6、7版本
纯处理请求:单线程,队列模式
其他的redis任务:例如落盘、主从复制、集群监控心跳等都需要redis线程来完成,本质上处理请求:单线程,其他任务:开多个线程
数据直接写到内存中,但也支持持久化存储
起多个redis变为4线程了
pstree -p | grep redis-server
[root@rocky ~]#pstree -p | grep redis
|-redis-server(1030)-+-{redis-server}(1065)
| |-{redis-server}(1067)
| |-{redis-server}(1069)
| `-{redis-server}(1071)
|-redis-server(1034)-+-{redis-server}(1064)
| |-{redis-server}(1066)
| |-{redis-server}(1068)
| `-{redis-server}(1070)
|-redis-server(1038)-+-{redis-server}(1060)
| |-{redis-server}(1061)
| |-{redis-server}(1062)
| `-{redis-server}(1063)
redis的常用场景
1.缓存:类似访问图片、CSS、JS等的CDN,访问到数据库后,请求结果缓存到redis中,下次用户在读这个表的数据直接读redis;
2.session:用户个性化信息,多台WEB服务器/API服务器共同放在redis中,用户再次访问的时候直接访问redis,共同读redis,比如说购物车场景,买好了就放好在购物车内
3.和次数有关的场景,放到redis,计数器,比较简单的场景修改数字而已,而不是说要去到表内修改记录,排行榜信息,实时会变化的
4.社交:朋友圈、共同好友,使用好友集合的并集来处理
5.地理位置:非常规数据,地理位置
6.消息队列:ELK等日志系统的缓存,订阅等


MySQL并发控制:锁、写锁
手动添加锁分为
读锁:对表/行加锁,别人能读,但是不能更改
写锁:对表/行加锁,别人不能读/写,加上排他性,自己掌握控制权
lock tables students lock_type(read/write)
lock tables students read
##加锁后的效果
update students set age=50 where stuid=1;
ERROR 1099 (HY000): Table 'students' was locked with a READ lock and can't be updated
##解锁后就可以写了
unlock tables;
update students set age=50 where stuid=1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
写锁:自己独占表/行的控制权,别的用户不能读或者写
lock tables students write;
select / update /delete等更新操作都不行
##查看MySQL的进程正在干嘛
[hellodb]>show processlist;
+----+-----------------+-----------+---------+---------+------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+---------+---------+------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 96 | Waiting on empty queue | NULL |
| 8 | root | localhost | hellodb | Query | 0 | init | show processlist |
+----+-----------------+-----------+---------+---------+------+------------------------+------------------+
kill +id ##杀掉对应的blocking进程
unlock tables;
select * from students where stuid=1;
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 50 | M | 2 | 3 |
+-------+-------------+-----+--------+---------+-----------+
1 row in set (6.30 sec)
redis缓存的实现逻辑
类似CDN,先读CDN缓存,没有缓存则回源拉取CDN的数据;每次回源都要算阿里云CDN的出网费用--->涉及到公网;
但是redis内网对接MySQL,没有出网一说,但是逻辑是类似的
提前先写好redis和MySQL的逻辑关系
1.写操作:包括update、insert、delete等,直接写后端的MySQL;写成功更新到redis,返回写成功;写失败直接返回

2.读操作:先读redis,没有就返回MySQL,MySQL吧对应的数据缓存到Redis中,redis获取数据,返回读成功

redis安装和部署
1.yum安装,Cent OS 8/ubuntu自带5.0的版本

yum -y install redis
rpm -ql redis
systemctl enable --now redis
端口-6379
ss -ntl | grep 6379
[root@rocky ~]#ss -ntlp | grep 6379
LISTEN 0 128 127.0.0.1:6379 0.0.0.0:* users:(("redis-server",pid=2812,fd=6))
redis启动,调用redis-server--->/usr/bin里面的执行程序和redis.conf
user=redis
group=redis
[root@rocky ~]#cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
redis登录,无账号登录,默认本地监听,后续需要修改成远程也能访问,监听0.0.0.0:6379
不像MySQL的各个info需要查看,比如show processlist,show master status/show slave status \G,show variables like '%log_bin%'等,select version();
redis-cli
127.0.0.1:6379> info [section]
##查看redis的线程,只有一个作为接收用户请求的主线程,其他的都是做别的功能的;消息队列,全部访问请求都要排队
pstree -p | grep redis
|-redis-server(2812)-+-{redis-server}(2813)
| |-{redis-server}(2814)
| `-{redis-server}(2815)
##检查redis的健康ping---pong
127.0.0.1:6379> ping
PONG
redis-cli ping
PONG
redis-cli info
redis二进制包安装&启动
编译安装,不想要构建源码
环境:Cent OS 7.6
##获取这个包
https://redis.io/download/
wget https://download.redis.io/releases/redis-6.2.7.tar.gz
[root@rocky redis-6.2.7]#ls
00-RELEASENOTES CONDUCT COPYING INSTALL MANIFESTO redis.conf runtest-cluster runtest-sentinel src TLS.md
BUGS CONTRIBUTING deps Makefile README.md runtest runtest-moduleapi sentinel.conf tests utils
##安装依赖环境,gcc编译程序,因为是基于C写的;安装make
yum -y install gcc make jemalloc-devel
rpm -qa | grep gcc
##需要支持systemd自启动,目的路径为apps,编译+安装install完成,可以写成脚本
make USE-SYSTEMD=yes PREFIX=/apps/redis -j 2 install
LINK redis-server
LINK redis-benchmark
INSTALL redis-check-rdb
INSTALL redis-check-aof
INSTALL redis-sentinel
LINK redis-cli
INSTALL redis-server
INSTALL redis-benchmark
INSTALL redis-cli
Hint: It's a good idea to run 'make test' ;)
make[1]: Leaving directory `/root/redis-6.2.7/src'
##查看redis工作目录
[root@master redis-6.2.7]#tree /apps/redis
/apps/redis
└── bin
├── redis-benchmark
├── redis-check-aof -> redis-server
├── redis-check-rdb -> redis-server
├── redis-cli
├── redis-sentinel -> redis-server
└── redis-server
##需要把执行文件写到profile内,避免每次启动都要写路径,.或者source使得配置文件生效,=写环境变量,里面写好了redis-server的启动
echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh
. /etc/profile.d/redis.sh
cat /etc/profile.d/redis.sh
##redis-server的启动,写配置文件redis.conf
[root@master redis-6.2.7]#cp redis.conf /apps/redis/
##创建/apps/redis下的配置文件
mkdir /apps/redis/{data,etc,log,run}
[root@master redis]#grep -Ev '^#|^$' redis.conf
bind 127.0.0.1 -::1
protected-mode yes
port 6379
tcp-backlog 511
timeout 0

报错:cc error,估计是gcc的问题,rocky 8的错误
https://www.cnbugs.com/post-1833.html
rocky 8安装gcc出现无法安装依赖
软件包 gcc-8.5.0-4.el8_5.x86_64 需要 glibc-devel >= 2.2.90-12,但没有提供者可以被安装
估计是版本不兼容
解决办法:降级处理
yum -y install gcc.x86_64 --allowerasing
redis启动+优化参数
目前还是基于前台运行,需要写systemd的service
##启动redis,新版本内会有两个告警wraning
redis-server /apps/redis/etc/redis.conf
WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
##解决办法:写到/etc/sysctl.conf里面,永久保存
##TCP最大长度+分配内存:如果redis服务器(实例)有32G的内存,则分配给程序32G的内存,不管其他的程序和OS层面
vim /etc/sysctl.conf
net.core.somaxconn=511
vm.overcommit_memory = 1
sysctl -p
##启动连接测试
redis-cli ping
redis-cli info
没有报警了
redis systemd服务实现
创建一个redis的用户用于运行redis-server服务
-s:指定用户路径
-r:创建同名组
useradd -s /sbin/nologin -r redis
##修改redis目录的权限
chown -R redis.redis /apps/redis
[root@master redis-6.2.7]#chown -R redis.redis /apps/redis
[root@master redis-6.2.7]#ll /apps/redis/
total 4
drwxr-xr-x 2 redis redis 134 Oct 5 12:14 bin
drwxr-xr-x 2 redis redis 6 Oct 5 12:31 data
-rw-r--r-- 1 redis redis 92 Oct 5 12:43 dump.rdb
drwxr-xr-x 2 redis redis 24 Oct 5 12:35 etc
drwxr-xr-x 2 redis redis 6 Oct 5 12:31 log
drwxr-xr-x 2 redis redis 6 Oct 5 12:31 run
##配redis.service
vim redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
LimitNOFILE=1000000 ##实现多并发的service,在启动Redis的时候需要
[Install]
WantedBy=multi-user.target
systemctl restart redis
systemctl status redis
redis安装脚本
redis默认是没用用户的,可以设置密码使用
所有的Linux安装二进制包都是先安装好依赖,再编译安装包,包括MySQL,redis,nginx都一样
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-07-22
#FileName: install_redis.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2020 All rights reserved
#********************************************************************
REDIS_VERSION=redis-6.2.7
#REDIS_VERSION=redis-4.0.14
PASSWORD=123456
INSTALL_DIR=/apps/redis
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'` ##取核心数
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
prepare(){
if [ $ID = "centos" -o $ID = "rocky" ];then
yum -y install gcc make jemalloc-devel systemd-devel
else
apt update
apt -y install gcc make libjemalloc-dev libsystemd-dev
fi
if [ $? -eq 0 ];then
color "安装软件包成功" 0
else
color "安装软件包失败,请检查网络配置" 1
exit
fi
}
install() {
if [ ! -f ${REDIS_VERSION}.tar.gz ];then
wget http://download.redis.io/releases/${REDIS_VERSION}.tar.gz || { color "Redis 源码下载失败" 1 ; exit; }
fi
tar xf ${REDIS_VERSION}.tar.gz -C /usr/local/src
cd /usr/local/src/${REDIS_VERSION}
make -j $CUPS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && color "Redis 编译安装完成" 0 || { color "Redis 编译安装失败" 1 ;exit ; }
ln -s ${INSTALL_DIR}/bin/redis-* /usr/bin/
mkdir -p ${INSTALL_DIR}/{etc,log,data,run}
cp redis.conf ${INSTALL_DIR}/etc/
sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf
##sed -e表示修改多个地方
##修改监听bind 0.0.0.0 -::1
##requirepass 123456
##dir /apps/redis/data/:数据目录
##logfile /apps/redis/log/redis-6379.log :日志目录
##运行pid文件:pidfile /apps/redis/run/redis_6379.pid
if id redis &> /dev/null ;then
color "Redis 用户已存在" 1
else
useradd -r -s /sbin/nologin redis
color "Redis 用户创建成功" 0
fi
chown -R redis.redis ${INSTALL_DIR}
cat >> /etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
##两个warning参数
#1.TCP连接最大长度,不要关机掉
#2.申请最大内存,机器所拥有的内存
sysctl -p
##大页内存never不开启
if [ $ID = "centos" -o $ID = "rocky" ];then
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
/etc/rc.d/rc.local
else
echo -e '#!/bin/bash\necho never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local
chmod +x /etc/rc.local
/etc/rc.local
fi
cat > /usr/lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now redis &> /dev/null
if [ $? -eq 0 ];then
color "Redis 服务启动成功,Redis信息如下:" 0
else
color "Redis 启动失败" 1
exit
fi
sleep 2
redis-cli -a $PASSWORD INFO Server 2> /dev/null
}
prepare
install
redis多实例与连接
密码都是123456,配置文件,二进制文件可以共用
##复制配置文件
mv redis.conf redis6379.conf
cp redis6379.conf redis6380.conf
cp redis6379.conf redis6381.conf
sed -i 's/6379/6380/' redis6380.conf
sed -i 's/6379/6381/' redis6381.conf
##修改属主
chown -R redis.redis redis*
##修改service文件
cp redis.service redis6380.service
cp redis.service redis6381.service
mv redis.service redis6379.service
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6379.conf --supervised systemd
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6380.conf --supervised systemd
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6381.conf --supervised systemd
sed -i 's/6379/6380/' redis6380.service
sed -i 's/6379/6381/' redis6381.service
##重新加载文件
systemctl daemon-reload
systemctl enable --now redis6379
systemctl enable --now redis6380
systemctl enable --now redis6381
##查看进程,都是基于redis-server去跑的
ps aux | grep redis
redis 28695 0.0 0.1 301128 6892 ? Ssl 22:00 0:00 /apps/redis/bin/redis-server 0.0.0.0:6379
redis 28856 0.0 0.1 301128 6788 ? Ssl 22:01 0:00 /apps/redis/bin/redis-server 0.0.0.0:6380
redis 28911 0.1 0.1 301128 6756 ? Ssl 22:01 0:00 /apps/redis/bin/redis-server 0.0.0.0:6381
ss -ntlp | grep 63
-p:端口
-h:host主机
-a:密码
##连接
redis-cli -p 6380 -a 123456 ping
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
PONG
##远程连接,需要能够访问6379端口
redis-cli -h 10.0.0.132 -p 6380 -a 123456 ping
python连接redis测试
比如说点赞数:点赞=1000,程序自动+1
排行榜:实时更新+1 -1等场景
##安装python3,自带python3
yum -y install python3
##使用pip3版本
pip3 install redis
pip3安装:类似Linux内的yum安装,主要是用于python环境安装程序
#1.导入redis包,配置r的键,键值为后续的redis配置,包括端口,主机,密码;自定义变量r.set方法,r.get方法,=给变量赋值
>>> import redis
>>> r = redis.Redis(host='10.0.0.132',port=6379,db=0,password='123456')
>>> r.set('t','test')
True
>>> r.get('t')
b'test'
#2.python批量写数据测试脚本,从0写到100000,=for i in {0..100000};do
#!/usr/bin/python3
import redis
pool = redis.ConnectionPool(host="10.0.0.132",port=6379,password="123456",decode_responses=True)
r = redis.Redis(connection_pool=pool)
for i in range(100000):
r.set("k%d" % i,"v%d" % i)
data=r.get("k%d" % i)
print(data)
#3.redis内查看python插入的数据
get key
set key value
127.0.0.1:6379> set name catyer
OK
127.0.0.1:6379> get name
"catyer"
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k999
"v999"
keys * = select *,#遍历所有数据
redis客户端client连接,一共有15个库,其中db0就是刚刚操作插入键值对的库
redis配置文件redis.conf
sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf
sed -e表示修改多个地方
bind 0.0.0.0 ##修改监听,远程连接,/^bind
requirepass 123456 ##启用密码,/^require
dir /apps/redis/data/ ##数据目录
logfile /apps/redis/log/redis-6379.log ##日志目录,记录redis的日志
=pidfile /apps/redis/run/redis_6379.pid ##进程ID号文件
slowlog-log-slower-than 1000 ##默认10ms,还是太长了
slowlog-max-len 128 #记录最近的128条慢日志
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
tcp-backlog 511:全连接队列,这里必须是写的511,所以之前的net.core.somaxconn = 1024,需要根据程序调大一点
dbfilename dump.rdb ##持久化数据文件,默认开启RDB功能
##查看配置文件,默认值,自动触发bgsave的默认配置规则
/^# save
save 3600 1
save 300 100
save 60 10000
##aof配置
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
#单节点客户端最高是10000并发
maxclients 10000
# maxclients 10000
使用config动态修改redis参数
不需要重启服务,最后还是得写到redis.conf中去修改requirepass参数
重启服务生效
SET和GET方法
127.0.0.1:6379> CONFIG SET requirepass 123
OK
redis-cli -a 123
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "123"
127.0.0.1:6379> CONFIG GET port
1) "port"
2) "6379"
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "0.0.0.0 -::1"
#查所有系统参数
127.0.0.1:6379> CONFIG GET *
systemctl restart redis
设置配置最大使用内存maxmemory:推荐为机器内存的一半
单位为B字节,需要转换一下,约为2G,不至于造成OOM的现象
[root@rocky etc]#free
total used free shared buff/cache available
Mem: 3793484 864828 1141028 9584 1787628 2640156
[root@rocky etc]#echo 3793484*1024 |bc
3884527616
[root@rocky etc]#echo 3793484*1024/2 |bc
1942263808
127.0.0.1:6379> CONFIG SET maxmemory 1942263808
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "1942263808"
redis慢查询SLOWLOG LEN
redis执行指令4个阶段:
1.客户端发送指令
2.redis单线程队列排序
3.执行命令--->慢查询可能的原因
4.返回结果
主要是可以根据用户客户端的反馈,从Redis的慢查询记录中找一下,类似MySQL的慢查询日志
MySQL的慢查询日志可以在my.cnf配置文件中配置,也可以基于动态修改
set global slow_query_log=ON;
##查看慢查询日志
[(none)]>show variables like '%slow%';
+-----------------------------+----------------------------+
| Variable_name | Value |
+-----------------------------+----------------------------+
| log_slow_admin_statements | OFF |
| log_slow_extra | OFF |
| log_slow_replica_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /data/mysql/rocky-slow.log |
+-----------------------------+----------------------------+
##MySQL配置的是10ms
[(none)]>show variables like '%long%';
+----------------------------------------------------------+-----------+
| Variable_name | Value |
+----------------------------------------------------------+-----------+
| long_query_time | 10.000000 |
| performance_schema_events_stages_history_long_size | 10000 |
| performance_schema_events_statements_history_long_size | 10000 |
| performance_schema_events_transactions_history_long_size | 10000 |
| performance_schema_events_waits_history_long_size | 10000 |
+----------------------------------------------------------+-----------+
5 rows in set (0.00 sec)
[root@rocky ~]#grep slowlog /apps/redis/etc/redis6379.conf
slowlog-log-slower-than 10000 ##默认10ms,还是太长了
slowlog-max-len 128 #记录最近的128条
127.0.0.1:6379> SLOWLOG len ##现在是0条慢查询记录
(integer) 0
##动态修改slow-log参数的值为1us,生产可以设置成1000us=1ms,差不多
127.0.0.1:6379>
OK
127.0.0.1:6379> CONFIG GET slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "1"
##获取慢查询的记录
127.0.0.1:6379> set test1 catyer
OK
127.0.0.1:6379> get test1
"catyer"
127.0.0.1:6379> SLOWLOG get ##keys *全表遍历,用了20ms
1) 1) (integer) 7
2) (integer) 1665018587
3) (integer) 21209
4) 1) "keys"
2) "*"
5) "127.0.0.1:50962"
6) ""
##清空慢查询日志
127.0.0.1:6379> SLOWLOG reset
OK
##花了14ms
127.0.0.1:6379> SLOWLOG get
1) 1) (integer) 11
2) (integer) 1665018955
3) (integer) 14885
4) 1) "keys"
2) "*"
5) "127.0.0.1:50962"
6) ""
慢查询阿里云redis版本:低于20ms就算慢查询
记录慢查询日志:1024个
redis数据持久化RDB&AOF
一般来说,redis保存在内存中,重启服务数据就会丢失,可以通过写磁盘文件实现数据保存持久化
支持两种类型:
RDB:redis database ---> mysqldump,不管是手动执行还是基于save的自动触发,还是不能做到实时保存数据,这个是RDB的缺点
AOF:appendONLYfile ----> binlog
RDB文件使用方式:会记录当前redis库的数据,服务崩溃/重启后,直接重新加载配置文件到redis中,恢复数据

##MySQL的备份方式
mysqldump -A -uroot -p123 -F --source-data=2 --single-transaction > backup.sql
mysqldump -B dbname -uroot -p123 -F --source-data=2 --single-transaction > backup.sql
--binlog:记录MySQL的增删查改,记录实时数据的变化
备份库数据同时需要备份binlog,记录当前的binlog_pos,备份完成后刷新一份binlog日志,更新pos
--RDB的实现方式:类似快照,备份速度快,恢复简单
--AOF:记录redis的写操作过程
##需要开启数据持久化,类似MySQL内的设置变量,开启log_bin等,是一个redis的RDB文件
[root@rocky data]#tree
.
└── dump.rdb
ll -h dump.rdb
-rw-r--r--. 1 redis redis 1.5M 10月 6 09:49 dump.rdb
##查看配置文件,RDB功能默认开启,由这两个路径组成;修改的话,同时需要修改两个地方;
##同时,如果是多个实例的话,可以在各自不同的.conf内修改路径和文件名,同时需要复制多份data到不同的名字
grep dump.rdb redis6379.conf
dbfilename dump.rdb
grep '^dir' ../etc/redis6379.conf
dir /apps/redis/data/
cp data.rdb data_6379.rdb
cp data_6379.rdb data_6380.rdb
cp data_6381.rdb data_6381.rdb
不用修改.conf,如果需要改变路径,则需要修改/^dir/
在.conf中,写哪个路径下的rdb,就读哪个路径下的.conf
RDB文件的保存bgsave
快照的形式,并不是实时保存的,因为终究还是写道内存中,不做快照保存到RDB的话还是非持久化的数据
过程:
1.调用redis-server执行快照
2.生成一个子进程专门用于保存快照
3.dump备份到一个临时的rdb文件,temp.rdb,全量dump,类似mysqldump -A
4.dump完成后,覆盖最终的rdb
bgsave:background save,后台执行保存,生成子进程,不影响主进程的redis-server执行--->主要使用
save:阻塞型的保存快照指令,执行快照的过程中,查询无法执行查看结果;因为save调用主进程,所以会使得其他的查询指令(调用redis-server)无法执行
##从内存写入磁盘的过程,保存
##复制过来rdb文件
cp dump_6.2.4.rdb data/dump.rdb
cp:是否覆盖'data/dump.rdb'? y
##重启服务,新的数据写入到内存中,成为redis的数据,1kw条记录
127.0.0.1:6379> dbsize
(integer) 10100001
[root@rocky data]#ll -h
总用量 182M
-rw-r--r--. 1 redis redis 182M 10月 6 11:25 dump.rdb
bgsave方式:redis-cli save&
##将内存中的数据写入到RDB文件内
redis-cli -a 123456 save& \
pstree -p | grep redis;ll /apps/redis/data
##还是调用的主进程进行保存的,会生成一个临时的.rdb文件,大概3-4s会完成快照的写入和保存
[root@rocky data]#redis-cli -a 123456 save& \
> pstree -p | grep redis;ll /apps/redis/data
[1] 4016
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
|-redis-server(3726)-+-{redis-server}(3733)
| |-{redis-server}(3734)
| |-{redis-server}(3735)
| `-{redis-server}(3736)
| | `-redis-cli(4016)
| `-sshd(2105)---sshd(2109)---bash(2110)---redis-cli(2153)
总用量 185856
-rw-r--r--. 1 redis redis 189855682 10月 6 11:35 dump.rdb
-rw-r--r--. 1 redis redis 360448 10月 6 11:36 temp-3726.rdb
[root@rocky data]#OK
[1]+ 已完成 redis-cli -a 123456 save
##重启服务后,直接调用/data/.rdb写入到redis中,date键值还在1006
先新加一条记录
127.0.0.1:6379> SET date 1006
OK
127.0.0.1:6379> get date
"1006"
127.0.0.1:6379> dbsize
(integer) 10100002
[root@rocky data]#redis-cli -a 123456 save&
[1] 4168
systemctl restart redis6379
127.0.0.1:6379> dbsize
(integer) 10100002
127.0.0.1:6379> get date
"1006"
##bgsave类似,可以并行执行,速度和save类似
redis-cli bgsave ; pstree -p | grep redis;ll /apps/redis/data
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Background saving started
|-redis-server(4243)-+-redis-server(4443) --->开启子进程,命令与temp.rdb一样
| |-{redis-server}(4250)
| |-{redis-server}(4251)
| |-{redis-server}(4252)
| `-{redis-server}(4253)
| `-sshd(2105)---sshd(2109)---bash(2110)---redis-cli(2153)
总用量 185600
-rw-r--r--. 1 redis redis 189855691 10月 6 11:49 dump.rdb
-rw-r--r--. 1 redis redis 122880 10月 6 12:04 temp-4443.rdb
[root@rocky data]#ll /apps/redis/data
总用量 185408
-rw-r--r--. 1 redis redis 189855691 10月 6 12:04 dump.rdb
systemctl restart redis6379
127.0.0.1:6379> get date
"1007"
基于bgsave实现定时备份rdb文件到远程主机脚本
缺点:需要人为手工去配置执行,或者是写定时任务触发这个备份任务,也可以从远端机器redis-cli -h 10.0.0.132来远端备份RDB文件到备份机器上面
##判断bgsave是否完成的参数
redis-cli -a 123456 --no-auth-warning info | grep rdb_bgsave_in_progress
[root@rocky script]#redis-cli -a 123456 --no-auth-warning info | grep rdb_bgsave_in_progress
rdb_bgsave_in_progress:0
[root@rocky script]#redis-cli -a 123456 --no-auth-warning info | grep rdb_bgsave_in_progress | awk -F: '{print $2}'
0
result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| \
sed -rn 's/.*:([0-9]+).*/\1/p'`
sed -n:打印
sed -r:扩展正则
##s/.*(:前面的任意字符)+([0-9]+)(整数)(整数后的的任意字符)/\1/p:替换打印出来为1
##!/bin/bash
BACKUP=/backup/redis-rdb
DIR=/data/redis
FILE=dump_6379.rdb
PASS=123456
#HOST=这里可以指定复制到哪个主机,或者其他机器定时redie-cli -h 10.0.0.132定时备份这台机器上面的rdb
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
redis-cli -h 127.0.0.1 -a $PASS --no-auth-warning bgsave
result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'`
##s/.*(:前面的任意字符)+([0-9]+)(整数)(整数后的的任意字符)/\1/p:替换打印出来为整数
until [ $result -eq 0 ] ;do
sleep 1
result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'`
done
DATE=`date +%F_%H-%M-%S`
[ -e $BACKUP ] || { mkdir -p $BACKUP ; chown -R redis.redis $BACKUP; }
cp $DIR/$FILE $BACKUP/dump_6379-${DATE}.rdb
color "Backup redis RDB" 0
尝试恢复数据,先更新一条记录
127.0.0.1:6379> set backup 1006
OK
127.0.0.1:6379> get backup
"1006"
备份
systemctl stop redis6379
rm -rf data/dump.rdb
cp backup/dump-2022-10-06_12\:47\:11.rdb data/dump.rdb,复制回来
重启服务
systemctl restart redis6379
测试完成
127.0.0.1:6379> set backup 1006
OK
127.0.0.1:6379> get backup
"1006"
save的配置参数自动触发bgsave保存快照--->覆盖本地.rdb
可自定义save的配置,定义时间+多少个key值发生变化,进行备份,类似MySQL的触发器trigger,不需要手动触发bgsave,需要备份到远程的话可以定时scp到远程主机
触发bgsave:自动做快照,生成临时.rdb文件,覆盖现有的dump.rdb
配置save,配置三个键值对
这种能够在config内看到的一般都是在.conf内有的
##默认规则,需要同时满足两个规则,满足以下任意的一条就可以,不需要三条都满足,即会触发redis的bgsave自动触发保存
127.0.0.1:6379> CONFIG GET save
1) "save"
2) "3600 1 300 100 60 10000"
--> 1小时 1次key变化
--> 300s(5min) 100次key变化
--> 60s 10000次key的变化
##查看配置文件,默认值,默认开启这些功能
/^# save
#save 3600 1
#save 300 100
#save 60 10000
##测试到底是bgsave还是save前台
##生成7746的子进程,证明是bgsave,自动触发,保存
[root@rocky ~]#pstree -p | grep redis ; ll /apps/redis/data/
|-redis-server(5673)-+-redis-server(7746)
| |-{redis-server}(5675)
| |-{redis-server}(5676)
| |-{redis-server}(5677)
| `-{redis-server}(5678)
|-sshd(1037)-+-sshd(1899)---sshd(1917)---bash(1918)---redis_test.py(7741)
| |-sshd(2105)---sshd(2109)---bash(2110)---redis-cli(7559)
总用量 447488
-rw-r--r--. 1 redis redis 189855702 10月 6 15:48 dump.rdb
-rw-r--r--. 1 redis redis 145403909 10月 6 15:50 temp-7746.rdb
redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress
rdb_bgsave_in_progress=1
##可以自定义save的配置参数,10s内有1个key发生变化
save 10 1
systemctl restart redis6379
##测试
redis-cli -a 123456 set date1 100444; pstree -p | grep redis;ll data/
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
OK
|-redis-server(8195)-+-redis-server(8390)
| |-{redis-server}(8199)
| |-{redis-server}(8200)
| |-{redis-server}(8201)
| `-{redis-server}(8202)
| |-sshd(2105)---sshd(2109)---bash(2110)---redis-cli(7559)
总用量 447488
-rw-r--r--. 1 redis redis 189855722 10月 6 16:12 dump.rdb
-rw-r--r--. 1 redis redis 144654341 10月 6 16:12 temp-8390.rdb
##取消save参数,置空;不禁用的话,就是使用默认的规则;自己写的话,就按照自己的规则10s 1次保存快照
vim etc/redis6379.conf
save ""
systemctl restart redis6379.service
127.0.0.1:6379> CONFIG GET save
1) "save"
2) ""
127.0.0.1:6379> CONFIG GET save
1) "save"
2) "10 1"
AOF:全备+增量备份
采用COW机制:copy on write,只要有数据更新,就会实时写入到.aof文件,无论是增加(set value)、删除(del value)、修改(set value)都一样
AOF的优先级高于RDB,如果两项都开启的话,默认redis读.aof
关于mysqldump的备份方式+恢复:mysqldump -A -F... > backup_full.sql
mysqlbinlog --start-position=157 /data/mysql/binlog/rocky-bin.000014 > /data/backup/binlog.sql
恢复次序:
1.还原完备:source backup_full.sql
2.还原时间点的binlog:source binlog.sql
##开启AOF,默认和rdb放在同一个文件
vim etc/redis6379.conf
appendonly no---yes
systemctl restart redis6379.service
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
[root@rocky redis]#ll data
总用量 185408
-rw-r--r--. 1 redis redis 0 10月 6 16:55 appendonly.aof
-rw-r--r--. 1 redis redis 189855724 10月 6 16:12 dump.rdb
##测试写一点数据进去,执行python脚本
直接覆盖了.rdb文件了
-rw-r--r--. 1 redis redis 3.5M 10月 6 16:58 appendonly.aof
-rw-r--r--. 1 redis redis 711K 10月 6 16:58 dump.rdb
appendonlyfine(.aof)功能的开启顺序&恢复数据
记录操作过程,跟binlog类似,binlog的格式跟这个不一样,这个比较简单明了,还能直接作为备份,也可以定点备份,恢复的时候确认需要开启appendonly no的配置
.aof就是一个文本文件
##先在redis-cli中开启appendonlyfile功能
##对于先修改.aof文件导致rdb文件数据丢失
先修改回no先
appendonly no
#复制回原来的备份
cp backup/dump-2022-10-06_12\:52\:49.rdb data/dump.rdb
cp:是否覆盖'data/dump.rdb'? y
#重启服务,数据还在
systemctl restart redis6379
127.0.0.1:6379> dbsize
(integer) 10100003
##记得要先修改redis appendonly,先修改redis.conf文件
#redis-cli config修改
127.0.0.1:6379> CONFIG SET appendonly yes
OK
127.0.0.1:6379> CONFIG GET appendonly
1) "appendonly"
2) "yes"
#查看data下,有一个.aof文件了
[root@rocky redis]#ll data/
总用量 370816
-rw-r--r--. 1 redis redis 189855702 10月 6 23:42 appendonly.aof
-rw-r--r--. 1 redis redis 189855702 10月 6 23:38 dump.rdb
#这时候再修改.conf文件,生效就行,下次再重启服务
appendonly yes
##测试更新数据.aof文件的变化,有实时更新的
127.0.0.1:6379> get city
"sz"
127.0.0.1:6379> set city sz
OK
-rw-r--r--. 1 redis redis 189855756 10月 7 10:18 appendonly.aof
关闭掉save的规则
#save 10 1
#查看.aof的文件格式,有一定的记录,set city sz
tail -f data/appendonly.aof
*3
$3
set
$4
city
$2
sz
.aof文件误操作恢复数据
类似binlog的恢复
1.先恢复全备
2.在全备到现在的binlog中,找到例如truncate这条语句,删除他
3.恢复binlog.sql
保存机制:类似bgsave,额外开一个redis-server来恢复创建快照,无论是全备还是增量都是这样
第一次启动:yes,做全备,后续都是增量备份,生成临时文件 temp.aof
127.0.0.1:6379> get city
"sz"
#误操作删除了city
127.0.0.1:6379> del city
(integer) 1
127.0.0.1:6379> get city
(nil)
#进入到.aof内删除del操作,删除5行,从*3开始,重启服务
vim data/appendonly.aof
systemctl restart redis6379
127.0.0.1:6379> get city
"sz"
##.aof的数据写入磁盘规则,每秒钟写一次磁盘,无论在1s(everysec)内有多少数据更新都是整合成一次IO进行写入
##always规则:已有更新就写入,适用于金融型的场景的交易数据,需要写成always
--appendfsync always
--appendfsync everysec
# appendfsync no
.aof文件重写(rewrite回收空间)
.aof带来的问题,如果将一个key重复修改很多次,那么.aof就会记录这么多次的修改操作,导致.aof文件的大小增长迅速,比.rdb的文件大太多了,目标其实就是想保留最后一次key更新的值,之前的其实都不关心
解决方案:re-write
##流程
1.执行bgrewriteaof
2.生成子进程1,继续接受用户的写入,同时回收磁盘空间
3.生成子进程2,生成一个临时的temp.aof新文件
4.新的aof文件覆盖老的aof文件,数据大小更新

##模拟回收数据流程
127.0.0.1:6379> dbsize
(integer) 10100004
127.0.0.1:6379> flushall ##清空所有库表数据
OK
(7.35s)
127.0.0.1:6379> dbsize
(integer) 0
##查看.aof文件,还是这么大,证明还没有回收空间,类似MongoDB的collect
[root@rocky redis]#ll data/
总用量 185412
-rw-r--r--. 1 redis redis 189855820 10月 7 11:08 appendonly.aof
-rw-r--r--. 1 redis redis 92 10月 7 11:08 dump.rdb
##手动执行bgrewriteaof,生成3534的子进程以及temp文件
[root@rocky redis]#redis-cli -a 123456 bgrewriteaof;pstree -p | grep redis ;ll data
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Background append only file rewriting started
|-redis-server(3008)-+-redis-server(3534)
| |-{redis-server}(3017)
| |-{redis-server}(3018)
| |-{redis-server}(3019)
| |-{redis-server}(3020)
| `-{redis-server}(3345)
| `-sshd(2230)---sshd(2241)---bash(2251)---redis-cli(2313)
总用量 185416
-rw-r--r--. 1 redis redis 189855820 10月 7 11:08 appendonly.aof
-rw-r--r--. 1 redis redis 92 10月 7 11:09 dump.rdb
-rw-r--r--. 1 redis redis 92 10月 7 11:10 temp-rewriteaof-bg-3534.aof
##覆盖
[root@rocky redis]#ll data
总用量 8
-rw-r--r--. 1 redis redis 92 10月 7 11:10 appendonly.aof
-rw-r--r--. 1 redis redis 92 10月 7 11:09 dump.rdb
##aof文件自动重写规则
no-appendfsync-on-rewrite no ##在回收期间,是否阻塞IO写,默认关闭
auto-aof-rewrite-percentage 100 ##当aof增长到一开始的1倍后,比如开始100MB,到200MB,则会从200MB开始回收数据--->180MB,又会从360MB开始回收
auto-aof-rewrite-min-size 64mb ##指定.aof文件增长到多少MB,就执行rewrite
aof-load-truncated yes ##末尾异常,即IO没写完
有关RDB和AOF模式的简单总结
##共同点
都可以实现redis保存数据的持久化,不必说redis重启或者其他操作导致数据丢失
##执行方式
1.RDB:通过save/bgsave来保存当前状态下的快照,不会实时记录数据变化
2.AOF:实时记录数据变化,实时写入AOF文件
##缺点
1.RDB:不会实时记录数据变化,安全性较低
2.AOF:造成大量数据的写入,占用磁盘空间
##应用场景
1.如果redis只是缓存,则只启动RDB就行,主要的备份还是MySQL那些,因为主要的数据加速读写还是MySQL、sql server作为主库
2.如果数据安全性要求高,建议RDB和AOF同时开启
阿里云redis默认只开启appendonly=yes,实现实时写入保存,增量保存;没有RDB
其余参数都没看有开启
redis常见指令
##所有的指令都可以通过非交互式来完成
redis-cli -a 123456 config get
redis-cli -a 123456 --no-auth-warning bgsave
##连接
redis-cli -a pass -h host
##监测链接、基本信息
127.0.0.1:6379> ping
PONG
##各种参数查看,有分类的,指定分类查看
127.0.0.1:6379> info
# Server
redis_version:6.2.7
redis_git_sha1:00000000
127.0.0.1:6379> info server
# Server
redis_version:6.2.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:ec1dca3538491f5c
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:0
##select切换数据库,类似MySQL的use dbname
##内置了很多歌数据库,默认都放在db0,可以从db0--->db15
切换
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> dbsize --->有标注是1号
(integer) 0
##修改.conf的databases参数,修改个数,重启服务;从0开始计数,如果写select 20的话没有,写select 19才能到20号数据库db
grep databases etc/redis6379.conf
databases 16
databases 20
--->集群只支持一个db0

##配置keys变量
keys:列出所有变量,一般不用,造成CPU飙高,间接导致redis无法返回读写请求,导致所有的并发请求到MySQL上,导致业务崩溃,宕机等;导致redis写锁
set key value:设置
get key:查看
del value:删除变量
mset:设置多个key
127.0.0.1:6379[19]> mset c1 w c2 e c3 r c4 t
OK
127.0.0.1:6379[19]> get c1
"w"
##keys模糊查询值,配置了多少个c的key
127.0.0.1:6379[19]> keys c*
1) "c2"
2) "c1"
3) "c4"
4) "c3"
##配置参数,动态修改,可以在.conf修改后重启服务
config set value 值:设置变量
config get value:查看
##记录数量
dbsize:看多少行
##慢日志,单位为us,可以设置例如set 1000=1ms
CONFIG GET slowlog-log-slower-than
CONFIG SET slowlog-log-slower-than 1000
SLOWLOG LEN:查看目前系统中的慢日志
##备份快照
redis-cli save&:前台保存
redis-cli bgsave:后台保存
save:保存快照
##对DB的危险操作
flushall:删除所有数据,库表
flushdb:清楚当前的数据库,比如在db1,则清除db1的数据
##使用rename-command将命令禁用,对flushdb置空
vim etc/redis.conf
rename-command flushdb ""
rename-command flushall ""
systemctl restart redis6379
127.0.0.1:6379[19]> keys c*
1) "c1"
2) "c3"
3) "c2"
4) "c4"
127.0.0.1:6379[19]> flushdb
(error) ERR unknown command `flushdb`, with args beginning with:
##shutdown关闭自己的客户端连接,服务停止,关闭服务
127.0.0.1:6379[19]> shutdown
not connected>
ss -ntlp | grep 6379
redis常见数据类型
key:string类型,指定键值对
##key的
set key value
get key
mset key1 value1 key2 value2...
mget key1 key2...
##key大小写敏感,不一样的大小写的key不一样
##可选选项
127.0.0.1:6379> set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
##设置这个变量10s后过期,比如红包100块,10s后过期
set hongbao 100 EX 10
127.0.0.1:6379> get hongbao
(nil)
##type:查看key类型
127.0.0.1:6379> set c1 1
OK
127.0.0.1:6379> set c2 2
OK
127.0.0.1:6379> type c1
string
##ttl:查看key的有效期
127.0.0.1:6379> set hongbao 100 ex 100
OK
127.0.0.1:6379> ttl hongbao
(integer) 97
##递增INCR=INCREMENT,类似MySQL的主键递增,id auto_increment
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
list:类似数组,称为列表
定义一个数组
array=(0,1,2,3)
下标:array[0],[1]以此类推
LPUSH:从左边开始编号,索引为0,1,2,3...
RPUSH:从右边开始编号,索引为-1.-2,-3...
lindex:从左边开始查看
rindex:从右边
##顺序:a b c,先推c,再ba
127.0.0.1:6379> lpush list1 c b a
(integer) 3
127.0.0.1:6379> lindex list1 0 --->最左边为a
"a"
127.0.0.1:6379> lindex list1 -1 --->最右边为c
"c"
type list1
127.0.0.1:6379> type list1
list
sets:集合,取交集/并集/差集,共同认识的好友
集合:无序的字符串放在里面,同一个集合内的元素不能重复,唯一的;不同的集合之间可以取并集,实现统计,例如共同好友等
里面可以是各种字符串
集合之间的操作

##定义两个无序集合
sadd my mary tom bob
sadd your mary tony jerry
##里面有3个元素
127.0.0.1:6379> sadd my mary tom bob
(integer) 3
127.0.0.1:6379> sadd your mary tony jerry
(integer) 3
##集合之间的操作,sinter:共同的元素,交集
##smembers:查看集合的元素
127.0.0.1:6379> smembers my
1) "tom"
2) "bob"
3) "mary"
127.0.0.1:6379> smembers your
1) "tony"
2) "jerry"
3) "mary"
127.0.0.1:6379> sinter my your
1) "mary"
##sunion:并集,所有合起来,不包括重复的,因为集合内的元素都是唯一的
127.0.0.1:6379> sunion my your
1) "mary"
2) "bob"
3) "tom"
4) "tony"
5) "jerry"
##sdiff:差集,set1有set2没有,或者是set2有set1没有,比如一群朋友就是一个集合等;社交场景可能认识的人
127.0.0.1:6379> sdiff my your
1) "tom"
2) "bob"
sorted sets:有序集合,常用于排行榜(名字-分数对)
按照一定的次序进行集合内的排序,比如排行榜,百度搜索的集合;或者是基于ES推荐的

每个元素都是由score和value组成的,可以根据分数来对人(value)进行排名,或者是别的值,比如说商品根据购买量、好评数等参数来进行排序,就可以使用有序集合sorted

##添加一个集合,music歌手的排行榜
##有序集合内有多个键值对
127.0.0.1:6379> ZADD music 99 jay 90 eason 85 feiniao 70 joey
(integer) 4
##正序排序,由小到大,=order by ,最左边是最后插入的,索引为0;最右边为最先插入的,索引为1,这条是遍历所有的值
127.0.0.1:6379> ZREVRANGE music 0 -1
1) "jay"
2) "eason"
3) "feiniao"
4) "joey"
##倒序排序
127.0.0.1:6379> ZRANGE music 0 -1
1) "joey"
2) "feiniao"
3) "eason"
4) "jay"
hash:哈希值
hash map操作
消息队列
把需要传输的数据放在消息队列中,实现应用之间的数据交换,将数据写入到消息队列中
场景:需要通过web服务器注册个人信息,然后让程序写入到数据库中
1.将web服务器的需要提交的信息写入到消息队列中
2.程序API服务器C、D轮流从队列中取数
3.C、D轮流取数完成注册,返回成功,响应成功
作用:解耦前端WEB和后端JAVA处理程序的关系,提高高可用性--->异步处理前端发来的消息,请求
可能就类似单线程的处理,类似redis单线程处理用户请求;读/写请求是分开的;放在MQ、kafka里面也可以让高并发的请求处理的没那么及时,不至于说搞到系统崩溃
模拟消费消息队列
生产者和消费者模式,抢占式的消费队列,消息出来后,消费者抢着消费
#从左边往右边推
127.0.0.1:6379> lpush channel1 message1
(integer) 1
127.0.0.1:6379> lpush channel1 message2
(integer) 2
127.0.0.1:6379> lpush channel1 message3
(integer) 3
127.0.0.1:6379> lpush channel1 message4
(integer) 4
#从最左边到右边,按照推送的顺序为1,2,3,4,那么从左道右就是4,3,2,1
127.0.0.1:6379> LRANGE channel1 0 -1
1) "message4"
2) "message3"
3) "message2"
4) "message1"
#lpop和rpop:消费队列
rpop:从最右边开始消费,消费了message1,就类似API程序消费WEB的注册信息一样
127.0.0.1:6379> rpop channel1
"message1"
127.0.0.1:6379> LRANGE channel1 0 -1
1) "message4"
2) "message3"
3) "message2"
订阅者和发布者:订阅发布者的频道,发布消息后,所有的订阅者都能收到消息
本文作者:Catyer
本文链接:https://www.cnblogs.com/catyer/p/16819518.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步