redis基本

redis

缓存机制比较重要

关系型与非关系型数据库的区别:数据的结构不同

主从机制:MHA架构,选择binlog同步数据最多的节点进行提升到主节点

没有说基于ACID的特性

ACID:原子性(要么事务提交成功,要么失败),一定会有结果,一个个事务之间都是隔离的

一致性:提交了一定会保存到表中,不会出现数据丢失,数据守恒

隔离性:事务还没提交前,看不到数据,数据隔离

持久型:事务提交,永久保存

##面试重点
事务的4个特性
A:原子性,整个事务中要么全部执行成功,要么全部失败回滚,唯一性,不可分割的步骤
C:一致性,必须遵循能量守恒定律,比如银行转账1000块,对方银行必定增加1000块,不存在转账后,1000块没了,双方平衡,双方加起来钱还是一致的
I:隔离性,即事务还未提交的时候,(还没显示结果),别人看不到你提交了一半的事务的过程--->dirty data脏数据,没有具体落地的东西
D:持久型,一旦事务提交,修改永久保存在数据库中

应用场景:大型数据存储场景,一般都是非结构化的数据,互联网场景,需要用到redis做大量的数据缓存--->高并发的场景下比较合适

基于keyvalue的数据类型

分布式系统的特点

image-20221004215942770

常见的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来处理这些并发的事务,效率太低

请求:提交事务,下订单,修改表数据,客户新下一个订单等

多线程:多个用户同时并发处理

image-20221004231504970

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等日志系统的缓存,订阅等

image-20221005103518876 image-20221005103820669

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,返回写成功;写失败直接返回

image-20221005105006094

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

image-20221005105011132

redis安装和部署

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

image-20221005111724712
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

image-20221005121238955

报错: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

image-20221005120023074

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


image-20221005123938637

没有报警了

image-20221005124326483

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就是刚刚操作插入键值对的库

image-20221005234941091

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)

image-20221006085721925

[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个

image-20221007135750048

redis数据持久化RDB&AOF

一般来说,redis保存在内存中,重启服务数据就会丢失,可以通过写磁盘文件实现数据保存持久化

支持两种类型:

RDB:redis database ---> mysqldump,不管是手动执行还是基于save的自动触发,还是不能做到实时保存数据,这个是RDB的缺点

AOF:appendONLYfile ----> binlog

RDB文件使用方式:会记录当前redis库的数据,服务崩溃/重启后,直接重新加载配置文件到redis中,恢复数据

image-20221006105251591
##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 106 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

image-20221006112012278

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 106 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 106 11:35 dump.rdb
-rw-r--r--. 1 redis redis    360448 106 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 106 11:49 dump.rdb
-rw-r--r--. 1 redis redis    122880 106 12:04 temp-4443.rdb

[root@rocky data]#ll /apps/redis/data
总用量 185408
-rw-r--r--. 1 redis redis 189855691 106 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 106 15:48 dump.rdb
-rw-r--r--. 1 redis redis 145403909 106 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 106 16:12 dump.rdb
-rw-r--r--. 1 redis redis 144654341 106 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 106 16:55 appendonly.aof
-rw-r--r--. 1 redis redis 189855724 106 16:12 dump.rdb

##测试写一点数据进去,执行python脚本
直接覆盖了.rdb文件了
-rw-r--r--. 1 redis redis 3.5M 106 16:58 appendonly.aof
-rw-r--r--. 1 redis redis 711K 106 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 106 23:42 appendonly.aof
-rw-r--r--. 1 redis redis 189855702 106 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 107 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文件,数据大小更新
image-20221007110520268
##模拟回收数据流程
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 107 11:08 appendonly.aof
-rw-r--r--. 1 redis redis        92 107 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 107 11:08 appendonly.aof
-rw-r--r--. 1 redis redis        92 107 11:09 dump.rdb
-rw-r--r--. 1 redis redis        92 107 11:10 temp-rewriteaof-bg-3534.aof


##覆盖
[root@rocky redis]#ll data
总用量 8
-rw-r--r--. 1 redis redis 92 107 11:10 appendonly.aof
-rw-r--r--. 1 redis redis 92 107 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没写完

image-20221007112628132

image-20221007112639380

有关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

其余参数都没看有开启

image-20221007113745336

redis常见指令

官方:http://redisdoc.com/

##所有的指令都可以通过非交互式来完成
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
image-20221007141951177
##配置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:类似数组,称为列表

image-20221007202727386

定义一个数组

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:集合,取交集/并集/差集,共同认识的好友

集合:无序的字符串放在里面,同一个集合内的元素不能重复,唯一的;不同的集合之间可以取并集,实现统计,例如共同好友等

里面可以是各种字符串

集合之间的操作

image-20221007213911423
##定义两个无序集合
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推荐的

image-20221007214756536

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

image-20221007215225662
##添加一个集合,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轮流取数完成注册,返回成功,响应成功

image-20221008233115131

作用:解耦前端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 中国大陆许可协议进行许可。

posted @   Catyer  阅读(25)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起