企业级WEB缓存中间件之Redis

一、Redis

1.redis的介绍

 

Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。

2.redis的业务场景

 1、[sort set]排行榜应用,取topn操作,例如sina微博热门话题
2、[List]获得最新N个数据 或 某个分类的最新数据
3、[string]计数點应用
4、[Set]/sns(social network site)获得共同好友
5、[set]防攻击系统(ip判断) 黑白名单等等

3.redis支持的数据结构

 支持存储的数据结构有
String(字符串,包含整数)
List(列表)
Hash(关联数组)
Sets(集合)
Sorted Sets(有序集合)

4.redis的性能

 1)、100 万较小的键存储字符串,大概消耗 100M 内存
2)、由于 redis 是单线程,如果服务器主机上有多个 CPU,只有一个能够使用,但并不意味着 CPU 会成为瓶颈,因为 redis 是一个比较简单的 K-V 数据存储,CPU 通常不会成为瓶颈的
3)、在常见的 linux 服务器上,500K(50 万)的并发,只需要一秒钟处理,如果主机硬件较好的情况下,每秒钟可以达到上百万的并发 

 5.redis优势

1)速度快:10W QPS,基于内存,C语言实现
2)单线程:Redis工作线程只有一个线程
3)支持数据的持久化:可以将内存中的数据保持在磁盘中,重启redis服务或者服务器之后可以从备份文件中恢复数据到内存继续使用 
4)支持更多的数据类型:支持string(字符串)、hash(哈希数据)、list(列表)、set(集合)、zset(有序集 合) 
5)支持数据的备份:可以实现类似于数据的master-slave模式的数据备份,另外也支持使用快照 +AOF 支持更大的value数据:memcache单个key value最大只支持1MB,而redis最大支持512MB(生产 不建议超过2M,性能受影响) 
6)在Redis6版本前,Redis 是单线程,而memcached是多线程,所以单机情况下没有memcached 并 发高,性能更好,但redis 支持分布式集群以实现更高的并发,单Redis实例可以实现数万并发 
7)支持多种编程语言
8)功能丰富:支持Lua脚本,发布订阅,事务,pipeline等功能
9)简单:代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单
10)主从复制
11)支持高可用和分布式
12)支持集群横向扩展:基于redis cluster的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性

 6.redis和memcached比较

1、Redis不仅仅支持简单的kN类型的数据,同时还提供list, set, zset, hash等数据结构的存储。
2、Redis支持master-slave(主一从模式应用)
3、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
4、Redis单个value存储string的最大限制是512MB, memcached只能保存1MB的数据
5、redis是单核,memcached是多核

二、部署redis

 redis分为Linux版本和Windows版本,Windows 安装包是某位民间“大神”根据 Redis 源码改造的,并非 Redis 官方网站提供。

1.安装windoes版本

github下载地址:https:#github.com/tporadowski/redis/releases

在 Windows 系统下安装 Redis 要比 Linux 系统安装稍微复杂一些,本节详细介绍如何在 Windows 系统上如何安装 Redis。

打开上述的下载链接,Redis 支持 32 位和 64 位的 Window 系统,大家根据个人情况自行下载,如图 1 所示:

图1:Redis 安装

下载完成后,打开相应的文件夹,您会看到如下图所示的文件目录:

图2:Window 安装 Redis

2.1.1 创建Redis临时服务
2.1.1.1 启动服务端程序

如上图所示,双击 Redis 服务端启动程序 redis-server.exe,您会看到以下界面:

图3:启动 Redis 服务端程序

上图中显示一些 Redis 的相关信息,比如 Redis 的版本号以及默认端口号(6379)。注意,为了实现后续操作,请您保持服务端开启状态,否则客户端无法正常工作。

2.1.1.2 启动客户端程序

启动服务端后,双击客户端启动程序 redis-cli.exe,得到如下界面:

图4:Redis客户端启动

得到如上界面,说明 Redis 本地客户端与服务端连接成功。

2.1.2 命令创建Redis服务

上述方式虽然简单快捷,但是显然不是程序员的操作,下面介绍,通过命令启动 Redis 服务端,并将 Redis 服务添加到 Windows 资源管理器,实现开机后自动启动。

2.1.2.1 注册Redis服务

通过 CMD 命令行工具进入 Redis 安装目录,将 Redis 服务注册到 Windows 服务中,执行以下命令:

redis-server.exe --service-install redis.windows.conf --loglevel verbose

执行完后,得到以下输出,说明注册成功。

[3568] 31 May 16:25:12.908 # Granting read/write access to 'NT AUTHORITY\NetworkService' on: "E:\Redis-x64-5.0.14.1" "E:\Redis-x64-5.0.14.1\"
[3568] 31 May 16:25:12.908 # Redis successfully installed as a service.
2.1.2.2 启动Redis服务

执行以下命令启动 Redis 服务,命令如下:

redis-server --service-start

如下图所示:

图5:命令启动 Redis 服务

注意:此时 Redis 已经被添加到 Windows 服务中,因此不会再显示 Redis 服务端的相应的信息,如下图所示:

图6:Windows 服务管理界面

2.1.3 启动Redis客户端

在 CMD 命令行输出 redis-cli 命令启动客户端,如下所示:

图7:启动 Redis 客户端

2.1.4 检查是否连接成功

测试客户端和服务端是否成功连接。输出PING命令,若返回PONG则证明成功连接。如下所示:

图8:测试客户端是否连接

通过上面的操作,我们完成了 Redis 的安装。当然,您也可以将 Redis 加入到环境变量中,如下所示:

图9:环境变量配置

注意:根据自己的安装路径添加环境变量。

总结

下面对安装过程中涉及到的命令进行总结,主要包括以下命令:

安装服务:redis-server --service-install
卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop
服务端启动时重命名:redis-server --service-start --service-name Redis1
2.2 安装Linux版本
2.2.1 yum 安装 Redis

CentOS系统yum仓库自带redis 版本

  • CentOS7:redis 3.2.12 (epel)

  • CentOS8:redis 5.0.3 (base)

2.2.2 源码包安装
2.2.2.1 解压redis压缩包
[root@localhost redis-6.0.16]# yum -y install gcc
[root@redis ~]# tar zxvf redis-6.0.16.tar.gz -C /usr/local/src/
[root@redis redis-6.0.16]# make PREFIX=/usr/local/redis install

安装过程中如果存在如下的报错,则是因为默认的gcc的版本太低导致的,可以使用如下的办法解决

[root@redis redis-6.0.16]#yum -y install centos-release-scl
[root@redis redis-6.0.16]#yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
[root@redis redis-6.0.16]#scl enable devtoolset-9 bash

2.2.2.2 查看安装的执行文件
[root@redis bin]# cd /usr/local/redis/bin/
[root@redis bin]# ls
redis-benchmark  redis-check-aof  redis-check-rdb  redis-cli  redis-sentinel  redis-server
2.2.2.3 配置服务启动文件
vim /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/usr/local/redis/bin/redis-server /usr/local/src/redis-6.0.16/redis.conf
ExecStop=/usr/libexec/redis-shutdown
Type=notifyUser=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[root@redis bin]# useradd -r redis -s /sbin/nologin
[root@redis bin]# systemctl daemon-reload
2.2.2.4 启动redis

前台启动redis

[root@redis bin]# cd /usr/local/redis/bin/
[root@redis bin]# ./redis-server     ##前台启动命令
13703:C 29 Oct 2022 13:57:18.508 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
13703:C 29 Oct 2022 13:57:18.508 # Redis version=6.0.16, bits=64, commit=00000000, modified=0, pid=13703, just started
13703:C 29 Oct 2022 13:57:18.508 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf
13703:M 29 Oct 2022 13:57:18.509 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 6.0.16 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 13703
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http:#redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

13703:M 29 Oct 2022 13:57:18.509 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
13703:M 29 Oct 2022 13:57:18.509 # Server initialized
13703:M 29 Oct 2022 13:57:18.509 # 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.
13703:M 29 Oct 2022 13:57:18.509 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redismust be restarted after THP is disabled (set to 'madvise' or 'never').
13703:M 29 Oct 2022 13:57:18.509 * Ready to accept connections

后台启动redis

[root@redis bin]# systemctl start redis
[root@redis bin]# ps -ef |grep redis
root      13684      1  0 13:52 ?        00:00:00 /usr/local/redis/bin/redis-server 127.0.0.1:6379
root      13689  13124  0 13:52 pts/1    00:00:00 grep --color=auto redis
2.2.3 redis的基本操作
2.2.3.1 redis的配置文件
[root@redis bin]# vim /usr/local/src/redis-6.0.16/redis.conf

daemonize no #表示 redis 并不会运行成为一个守护进程,如果需要运行成为一个守护进程,则把 no,改为 yes 即可,如果使用服务脚本启动,即使 daemonize 为 no,也会运行为一个守护进程
port 6379   #监听端口:6379/tcp
tcp-backlog 511   #指定 tcp-backlog 的长度
说明:任何的 tcp 服务都有可能使用到 tcp-backlog 功能,backlog 是一个等待队列,比如:redis 的并发很高时,redis 运行不过来时,就连接本地缓存等队列都满了以后,就会使用额外的存储地方,把新来的请求暂存下来,而这个位置则称为 backlog
bind 127.0.0.1   #监听的地址,默认监听在 127.0.0.1 地址上,可以指定为 0.0.0.0 地址,或某个特定的地址,或可以指定多个,使用空格分隔即可#
protected-mode yes   # redis3.2 之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问
 
unixsocket /tmp/redis.sock #指定使用 sock 文件通信及 sock 文件位置,如果服务端和客户都在同一台主机上,建议打开此项,基于 sock 方式通信可以直接在内存中交换,数据不用再经过 TCP/TP协议栈进行封装、拆封
unixsocketperm 700 #定义 sock 文件的访问权限
timeout 0         #表示当客户端连接成功后,空闲(非活跃、或没有任何数据交互)多长时间则连接超时,0 表示不启用此功能
tcp-keepalive 0     #定义是否启用 tcp-keepalive 功能
loglevel notice     #定义日志级别
logfile /var/log/redis/redis.log #定义日志文件
databases 16                 #定义 redis 默认有多少个 databases,但是在分布式中,只能使用一个,默认是0号数据库
#### SNAPSHOTTING #### #定义 RDB 的持久化相关
save <seconds> <changes> #使用 save 指令,并指定每隔多少秒,如果发生多大变化,进
行存储
示例:
save 900 1 #表示在 900 秒(15 分钟内),如果至少有 1 个键发生改变,则做一次快照(持
久化)
save 300 10 #表示在 300 秒(5 分钟内),如果至少有 10 个键发生改变,则做一次快照(持
久化)
save 60 10000 #表示在 60 秒(1 分钟内),如果至少有 10000 个键发生改变,则做一次快照
(持久化)
save ""   #如果 redis 中的数据不需做持久化,只是作为缓存,则可以使用此方式关闭持久化
功能
stop-writes-on-bgsave-error yes  #后台存储错误停止写
rdbcompression yes    #存储至本地数据库是(持久化到rdb)中是否压缩数据,默认是yes
dbfilename dump.rdb  #本地化持久数据库文件名,默认是dump.rdb


######## REPLICATION ####### #配置主从相关
# slaveof <masterip> <masterport> #此项不启用时,则为主,如果启动则为从,但是需
要指明主服务器的 IP,端口
# masterauth <master-password> #如果主服务设置了密码认证,那么从的则需要启用此项
并指明主的认证密码
slave-serve-stale-data yes  #配置slave实例是否接受写,写slave对存储短暂数据是有用得,默认是yes.
slave-read-only yes #定义从服务对主服务是否为只读(仅复制)
# repl-ping-slave-period 10   #从库向主库会按照一个将时间发送ping,默认是10S
# repl-timeout 60    #设置主库批量数据传输时间或者Ping恢复间隔时间,默认是60S,注意这个值一定要大于repl-ping-slave-period
repl-disable-tcp-nodelay no  #如果选择“yes”,redis会使用一个较小的的数字TCP数据表和更小的带宽将数据发送到slave,这可能导致数据发送到slave端会有延时,如果选择“no",则发送数据到slave的延时更小。
# repl-backlog-size 1mb  #设置复制的后台日志大小,日志设置的越大,slave断开连接后以及以后可能执行部分复制化的时间就越长
slave-priority 100   #如果master异常,那么会在多个slave中选择优先值最小的一个slave来提升为master,优先值为0,表示不能提升为Master
################################ SECURITY #######################################
# requirepass foobared   #定义连接redis后进行操作,需要使用密码验证
############################## LIMITS ############################# #定义与连接和资源限制相关的配置
# maxclients 10000 #定义最大连接限制(并发数)
# maxmemory <bytes> #定义使用主机上的最大内存,默认此项关闭,表示最大将使用主机上的最大可用内存

当内存达到最大值是,内存中键值的删除策略
# volatile-lru -> 利用LRU算法移除设置过期时间的key
# allkeys-lru -> 利用LRU算法来移除任何key
# volatile-lfu -> 从已设置过期时间的key中挑选最不经常使用的数据淘汰
# allkeys-lfu -> 从所有的Key中来移除使用频率最低的key
# volatile-random -> 移除设置过期时间的随机key
# allkeys-random -> 随机移除任何的key
# volatile-ttl -> 移除即将过期的key
# noeviction -> 如果对于上面的Key没有key可以删除,在写数据的时候返回一个错误。


############################## APPEND ONLY MODE ####### #定义 AOF 的持久化功能相关配置,一旦有某
一个键发生变化,将修改键的命令附加到命令列表的文件中,类似于 MySQL 二进制日志
appendonly no #定义是否开启此功能,no 表示关闭,yes 表示开启
说明:RDB 和 AOF 两种持久功能可以同时启用,两者不影
appendfilename "appendonly.aof"  #AOF持久化的名字
键同步AOF中的策略
# appendfsync always    #每次有键值有变化就进行同步。速度最慢
appendfsync everysec  #每秒钟同步一次 ,速度快
# appendfsync no    #不同步,速度最快,让系统决定同步策略

建议如果不知道设置成哪种,可以选择“everysec”,在数据安全性和同步速度是最平衡的。
no-appendfsync-on-rewrite no  #后台执行(RDB的save | aof重写)时appendfsync设为no。
(当AOF 的appendfsync配置为 everysec 或 always ,并且后台运行着RDB的save或者AOF重写时,(由于save和rewrite会)消耗大量的磁盘性能。在某些Linux配置下,aof同步到磁盘执行 fsync() 将被阻塞很长时间。
注意:这个问题目前还没有解决办法。因为即使在不同的线程中执行fsync,也会阻塞同步 write() 调用。
  为了减轻这个问题,可以使用 no-appendfsync-on-rewrite 选项防止执行BGSAVE或BGREWRITEAOF时,在主进程中调用fsync()。这意味着当有另一个子进程执行BGSAVE或BGREWRITEAOF 时,磁盘同步策略相当于 appendfsync no。在最坏的情况下(使用默认的Linux设置)可能会丢失最多30秒的日志。
  如果你有延迟问题可以将该项设置为“yes”。否则,从数据完整性的角度看,使用“no”更安全
auto-aof-rewrite-percentage 100   #如果是0代表,这个值是用于防止文件即使很小但是增长幅度很大也进行重写
auto-aof-rewrite-min-size 64mb   #指定AOF文件大小
aof-load-truncated yes   #指定当发生AOF文件末尾截断时,加载文件还是报错退出
aof-use-rdb-preamble  no   #开启混合持久化,更快的AOF重写和启动时数据恢复,如果是No,则不开启
2.2.3.2 连接redis

Redis属于轻量级NoSQL数据库,没有用户账号和用户权限控制,直接通过密码登录Redis数据拥有最高操作权限,默认安装Redis是无密码直接连接

安全检查命令:

命令说明
AUTH password验证密码是否正确
ECHO message打印字符串
PING查看服务是否运行正常
QUIT关闭当前连接
SELECT index切换到指定的数据库

方法1:使用telnet连接

[root@redis bin]# telnet 127.0.0.1 6379
info     ##表示获取redis的服务器的信息
set  a  100 ##表示设置一个k-v的值,键是a,值是100
get a   ##获取键a的值

方法2:使用redis自带客户端连接

[root@redis bin]# redis-cli -h
选项:-h <hostname> 指定主机 IP
-p <port> 指定端口 socket 文件进行通信
-s <socket> 指定 socket 文件,如果客户端口和服务端都在同一台主机,可以指定 socket 文
件进行通信
-a <password> 指定认证密码
-r <repeat> 连接成功后指定运行的命令 N 次
-i <interval> 连接成功后每个命令执行完成等待时间,使用-i 选项指定
-n <db>
[root@redis bin]# redis-cli -h localhost   ##默认登录不需要密码
localhost:6379> set b 200
OK
localhost:6379> get b
"200"
localhost:6379> info
# Server
redis_version:6.0.16
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:b63746939d966c35
redis_mode:standalone
os:Linux 3.10.0-1160.76.1.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.3.1
process_id:13714
run_id:63702cfd6128b73f1471214cb31aa3e24b9c2822
tcp_port:6379
uptime_in_seconds:758
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:6079571
executable:/usr/local/redis/bin/redis-server
config_file:/usr/local/src/redis-6.0.16/redis.conf
io_threads_active:0

.......
localhost:6379> select 1  ##表示切换到 1 号库中,默认为 0 号库,共 16 个,0-15
OK
localhost:6379[1]>
localhost:6379[1]> exit               ##exit,退出登录

客户端常用命令:

命令说明
CLIENT LIST以列表的形式返回所有连接到 Redis 服务器的客户端。
CLIENT SETNAME设置当前连接的名称。
CLIENT GETNAME获取通过 CLIENT SETNAME 命令设置的服务名称。
CLIENT PAUSE挂起客户端连接,将所有客户端挂起指定的时间(以毫秒为计算)。
CLIENT KILL关闭客户端连接。
CLIENT ID返回当前客户端 ID。
CLIENT REPLY控制发送到当前连接的回复,可选值包括 on|off|skip。

方法3: python 连接Redis

python 多种开发库可以支持连接redis,官方推荐使用redis-py 连接 redis

redis-py模块的GitHub地址:https:#github.com/andymccurdy/redis-py

#安装python3和redis-py模块
yum -y install python3 python3-redis

#python连接redis脚本,(注意文件名不要为redis,会和redis模块名称冲突)
[root@centos7 ~ ]# vim py-redis.py
#!/bin/env python3
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(1,101):
        r.set("k%d" % i,"v%d" % i)
        # time.sleep(1)
        data=r.get("k%d" % i)
        print(data)

[root@centos7 ~ ]# python3 py-redis.py
b'v1'
b'v2'
......
b'v99'
b'v100'

#查看redis的键值情况
[root@centos7 ~ ]# redis-cli -p 6379
127.0.0.1:6379> info
......
# Keyspace
db0:keys=201,expires=0,avg_ttl=0

方法4: 图形工具连接

 

2.2.4 key的遵循规则
1)可以使用 ASCII 字符
2)键的长度不要过长,键的长度越长则消耗的空间越多,也不要太短,不好理解其含义
3)在同一个库中(名称空间),键的名称不得重复,如果复制键的名称,实际上是修改键中的值
4)在不同的库中(名称空间),键的名称可以重复
5)键可以实现自动过期
2.2.4.1 Redis键(key)命令
1)keys * #查看当前库所有key (匹配:keys *1)
2)exists key #判断某个key是否存在
3)type key #查看你的key是什么类型
4)del key #删除指定的key数据
5)unlink key #根据value选择非阻塞删除,仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。
6)expire key 10 #10秒钟:为给定的key设置过期时间
7)ttl key #查看还有多少秒过期,-1表示永不过期,-2表示已过期
8)select #切换数据库
9)dbsize #查看当前数据库的key的数量
10)flushdb #清空当前库
11)flushall #清空全部库
12)shutdown  #关闭redis

默认16个数据库,类似数组下标从0开始,初始默认使用0号库
 2.2.4.2 演示案例
localhost:6379> keys *    ##查看所有的key
1) "a"
localhost:6379>

localhost:6379> exists a    ##检查是否存在a这个key
(integer) 1
localhost:6379> exists a b   ##同时检查多个key
(integer) 2

localhost:6379> type a   ##查看key的类型
string
localhost:6379> del b    ##删除key   
(integer) 1
localhost:6379> unlink a  ##根据value选择非阻塞删除,仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作
(integer) 1
localhost:6379> get a
(nil)
localhost:6379> set a 100   
OK
localhost:6379> expire a 1    ##设置a键的过期时间,默认是s
(integer) 1
localhost:6379> ttl a     ##查看键的过期时间,-2代表已经过期,-1表示永不过期
(integer) -2

localhost:6379> rename a aaa   ##将键重新重命名
OK
localhost:6379>


localhost:6379> select 1    ##选择数据库,默认是0
OK
localhost:6379[1]> dbsize     ##查看当前库的键数量
(integer) 0 
localhost:6379[1]> set name zhangsan   
OK
localhost:6379[1]> dbsize
(integer) 1
localhost:6379[1]> flushdb     ## 清空数据库
OK
 
localhost:6379> flushall    ##清空所有数据库
·
OK
2.2.5 Redis数据类型
2.2.5.1 Strings

string是redis的基本类型,它可以存储任何类型的数据,单个key的最大空间是512M

 

127.0.0.1:6379> help set
SET key value [EX seconds] [PX milliseconds] [NX|XX] #命令 键 值 [EX 过期时间,单位
秒]
summary: Set the string value of a key
since: 1.0.0
group: string
NX:如果一个键不存在,才创建并设定值,否则不允许设定
XX:如果一个键存在则设置建的值,如果不存在则不创建并不设置其值

案例演示:
localhost:6379> set hubei wuhan   ##设置一个键为湖北,值为武汉
OK
localhost:6379> get hubei    ##获取hubei这个键的值
"wuhan"
localhost:6379> set wuhan 123 NX  ##设置一个键为wuhan,值为123,不存在时可以创建的
OK
localhost:6379> set wuhan 123 NX  ##设置一个键为wuhan,值为123,键存在时不可以创建,返回一个nil空
(nil)
localhost:6379> set wuhan 123 XX    ##设置一个键为user,值是123,如果键键存在则设置建的值
OK
localhost:6379> set user 123 XX   ##设置一个键为user,值是123,如果不存在则不创建并不设置其值
(nil)
localhost:6379> set abc 123 EX 60   ##设置一个键为abc,值为123,过期时间为60s
OK
localhost:6379> get abc    ##获取abc的值,已经超时被清除
(nil)
localhost:6379[1]> mset name zhangsan age 20   ##同时设置多个k-v
OK
localhost:6379[1]> mget name age    ##同时获取多个
1) "zhangsan"
2) "20"
localhost:6379[1]> INCR age    ##增加1
(integer) 21
localhost:6379[1]> DECR age    ##减少1
(integer) 20
localhost:6379[1]> INCRBY age 10   ##增加10
(integer) 30
localhost:6379[1]> DECRBY age 15   ##减少15
(integer) 15
localhost:6379> append hubei xianning  ##添加键中的值(在原有键中附加值的内容):
(integer) 13
localhost:6379> get hubei
"wuhanxianning"
localhost:6379> substr hubei 5 12   ##截取字符串,从下标0开始
"xianning"
localhost:6379>
localhost:6379> substr hubei 0 -1  ##截取所有的字符串
"wuhanxianning"
localhost:6379>
localhost:6379> strlen hubei    ##查看字符串长度
(integer) 13


注:incr 命令只能对整数使用

127.0.0.1:6379> del fda  删除键:
(integer) 1
2.2.5.2 list

Redis中的List其实就是双端链表,我们可以使用RPUSH和LPUSH从链头和链尾添加和删除元素

list既可以做队列,也可以做栈

同一端进出,先进后出,叫栈(羽毛球)

一端进,另一端出,先进先出,叫队列(排队打饭)

 

键指向一个列表,而列表可以理解为是一个字符串的容器,列表是有众多元素组成的集合,可以在键所指向的列表中附加一个值
Lists 的常用命令:
LPUSH #在键所指向的列表前面插入一个值(左边加入)
RPUSH #在键所指向的列表后面附加一个值(右边加入)
LPOP #在键所指向的列表前面弹出一个值(左边弹出)
RPOP #在键所指向的列表后面弹出一个值(右边弹出)
LINDEX #根据索引获取值,指明索引位置进行获取对应的值
LSET #用于修改指定索引的值为指定的值
案例:老师想登记班里谁先到班,谁最后到班?

localhost:6379> lpush name zhangsan    ##往列表中推入学生名字
(integer) 1
localhost:6379> lpush name lisi      ##往列表中推入学生名字
(integer) 2 
localhost:6379> lpush name wangwu    ##往列表中推入学生名字
(integer) 3
localhost:6379> LPOP name          ##栈操作   
"wangwu"
localhost:6379> rpop name          ##队列操作
"zhangsan"
localhost:6379> llen name         ##查看队列的长度,wangwu和zhangsan已经被推出去了
(integer) 1
localhost:6379>

localhost:6379> rpush name wangwu    ##重新在列表尾部推送2个名字
(integer) 2
localhost:6379> rpush name zhangsan
(integer) 3
localhost:6379> LRANGE name 0 -1       ##查看列表的内容 
1) "lisi"
2) "wangwu"
3) "zhangsan"
localhost:6379>
localhost:6379> LRANGE name -1 -1     ##取出最后进班的人
1) "zhangsan"
localhost:6379>
localhost:6379> lindex name 1         ##根据下标来取值
"wangwu"
localhost:6379>
localhost:6379> type name       ##查看key的类型
list
2.2.5.3 set

Redis 的 Set 是 String 类型的无序集合,集合成员是不可重复的

set的最大可以有2的32次方-1个元素

关于set集合类型除了基本的添加删除操作,其他常用的操作还包含集合的取 并集(union), 交集(intersection). 差集(difference)。通过这些操作可以很容易的实现sns中的好友推荐功能。

命令使用:
命令   	简述	                    使用
SADD	向集合添加一个或多个成员	 SADD key value
SCARD	获取集合的成员数	        SCARD key
SMEMBER	返回集合中的所有成员	       SMEMBER key member
SISMEMBER	判断 member 元素是否是集合 key 的成员	SISMEMBER key member
# ===================================================
# sadd 将一个或多个成员元素加入到集合中,不能重复
# smembers 返回集合中的所有的成员。
# sismember 命令判断成员元素是否是集合的成员。
# ===================================================
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "kuangshen"
2) "hello"
127.0.0.1:6379> SISMEMBER myset "hello"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "world"
(integer) 0
# ===================================================
# scard,获取集合里面的元素个数
# ===================================================
127.0.0.1:6379> scard myset
(integer) 2
# ===================================================
# srem key value 用于移除集合中的一个或多个成员元素
# ===================================================
127.0.0.1:6379> srem myset "kuangshen"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
# ===================================================
# srandmember key 命令用于返回集合中的一个随机元素。
# ===================================================
127.0.0.1:6379> SMEMBERS myset
1) "kuangshen"
2) "world"
3) "hello"
127.0.0.1:6379> SRANDMEMBER myset
"hello"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "world"
2) "kuangshen"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "kuangshen"
2) "hello"
# ===================================================
# spop key 用于移除集合中的指定 key 的一个或多个随机元素
# ===================================================
127.0.0.1:6379> SMEMBERS myset
1) "kuangshen"
2) "world"
3) "hello"
127.0.0.1:6379> spop myset
"world"
127.0.0.1:6379> spop myset
"kuangshen"
127.0.0.1:6379> spop myset
"hello"
# ===================================================
# smove SOURCE DESTINATION MEMBER
# 将指定成员 member 元素从 source 集合移动到 destination 集合。
# ===================================================
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "kuangshen"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset myset2 "kuangshen"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "world"
2) "hello"
127.0.0.1:6379> SMEMBERS myset2
1) "kuangshen"
2) "set2"
# ===================================================
- 数字集合类
- 差集: sdiff
- 交集: sinter
- 并集: sunion
# ===================================================
localhost:6379> sadd key1 zhangsan lisi wangwu zhaoliu xiaohua
(integer) 5
localhost:6379> sadd key2 zhangsan maqi zhaoliu liusan qiansi
(integer) 5
localhost:6379> SDIFF key1 key2     ##差集
1) "wangwu"
2) "xiaohua"
3) "lisi"
localhost:6379> SINTER key1 key2     ##交集
1) "zhangsan"
2) "zhaoliu"
localhost:6379> SUNION key1 key2    ##并集
1) "qiansi"
2) "maqi"
3) "wangwu"
4) "zhangsan"
5) "zhaoliu"
6) "liusan"
7) "lisi"
8) "xiaohua"
localhost:6379>
2.2.5.4 zset

Redis 有序集合和集合一样基本一致元素不能重复

使用场景:
排行榜:有序集合经典使用场景。例如应用市场上的收集APP的排名。
成绩排行:比如一个存储全班同学成绩的sorted set,其集合value可以是同学的学号,而score就可以是其考试得分, 形成了按成绩排序。
权重分配:可以用sorted set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

 需求:统计一下应用市场上APP的排名

localhost:6379> zadd appTop 2 wechat 1 QQ 4 toutiao 7 taobao 6 jd 8 kugou
localhost:6379> ZRANGE appTop 0 -1   ##排序,从小到大
1) "QQ"
2) "wechat"
3) "toutiao"
4) "jd"
5) "taobao"
6) "kugou"
localhost:6379>

localhost:6379> ZREVRANGE appTop 0 -1   ##排序,从大到小
1) "kugou"
2) "taobao"
3) "jd"
4) "toutiao"
5) "wechat"
6) "QQ"
localhost:6379>

localhost:6379> zscore appTop kugou    ##获取kugou和wechat的score
"8"
localhost:6379> zscore appTop wechat
"2"
localhost:6379> ZINCRBY appTop -2 wechat  ##修改wechat的权重,-2代表权重减少2
"0"
localhost:6379> ZRANGE appTop 0 -1   ##再次查看wechat变成了排名第一
1) "wechat"
2) "QQ"
3) "toutiao"
4) "jd"
5) "taobao"
6) "kugou"
localhost:6379>
2.2.5.5 hash

Redis hash 是一个 string 类型的 field(字段) 和 value(属性) 的映射表,hash 特别适合用于存储对象。

一个hash可以存多个key-value,类似一个对象的多个字段和属性

使用场景: 

缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。

命令使用

命令	   简述	         使用
HSET	添加键值对	HSET hash-key sub-key1 value1
HGET	获取指定散列键的值	HGET hash-key key1
HGETALL	获取散列中包含的所有键值对	HGETALL hash-key
HDEL	如果给定键存在于散列中,那么就移除这个键	HDEL hash-key sub-key1

 

# ===================================================
# hset、hget 命令用于为哈希表中的字段赋值 。
# hmset、hmget 同时将多个field-value对设置到哈希表中。会覆盖哈希表中已存在的字段。
# hgetall 用于返回哈希表中,所有的字段和值。
# hdel 用于删除哈希表 key 中的一个或多个指定字段
# ===================================================
127.0.0.1:6379> hset myhash field1 "huangkaiyu"
(integer) 1
127.0.0.1:6379> hget myhash field1
"huangkaiyu"
127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK


127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379> HGET myhash field2
"World"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
127.0.0.1:6379> HDEL myhash field1
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "World"
# ===================================================
# hlen 获取哈希表中字段的数量。
# ===================================================
127.0.0.1:6379> hlen myhash
(integer) 1
127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> hlen myhash
(integer) 2
# ===================================================
# hexists 查看哈希表的指定字段是否存在。
# ===================================================
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
# ===================================================
# hkeys 获取哈希表中的所有域(field)。
# hvals 返回哈希表所有域(field)的值。
# ===================================================
127.0.0.1:6379> HKEYS myhash
1) "field2"
2) "field1"
127.0.0.1:6379> HVALS myhash
1) "World"
2) "Hello"
# ===================================================
# hincrby 为哈希表中的字段值加上指定增量值。
# ===================================================
127.0.0.1:6379> hset myhash field 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field 1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field -1
(integer) 5
127.0.0.1:6379> HINCRBY myhash field -10
(integer) -5
# ===================================================
# hsetnx 为哈希表中不存在的的字段赋值 。
# ===================================================
127.0.0.1:6379> HSETNX myhash field1 "hello"
(integer) 1 # 设置成功,返回 1 。
127.0.0.1:6379> HSETNX myhash field1 "world"
(integer) 0 # 如果给定字段已经存在,返回 0 。
127.0.0.1:6379> HGET myhash field1
"hello"
2.2.5.6 HyperLoglog

HyperLoglog 是 Redis 重要的数据类型之一,它非常适用于海量数据的计算、统计,其特点是占用空间小,计算速度快。

HyperLoglog 采用了一种基数估计算法,因此,最终得到的结果会存在一定范围的误差(标准误差为 0.81%)。每个 HyperLogLog key 只占用 12 KB 内存,所以理论上可以存储大约2^64个值,而 set(集合)则是元素越多占用的内存就越多,两者形成了鲜明的对比

基数定义

基数定义:一个集合中不重复的元素个数就表示该集合的基数,比如集合 {1,2,3,1,2} ,它的基数集合为 {1,2,3} ,所以基数为 3。HyperLogLog 正是通过基数估计算法来统计输入元素的基数。

HyperLoglog 不会储存元素值本身,因此,它不能像 set 那样,可以返回具体的元素值。HyperLoglog 只记录元素的数量,并使用基数估计算法,快速地计算出集合的基数是多少。

场景应用

HyperLogLog 也有一些特定的使用场景,它最典型的应用场景就是统计网站用户月活量,或者网站页面的 UV(网站独立访客)数据等。

UV 与 PV(页面浏览量) 不同,UV 需要去重,同一个用户一天之内的多次访问只能计数一次。这就要求用户的每一次访问都要带上自身的用户 ID,无论是登陆用户还是未登陆用户都需要一个唯一 ID 来标识。

当一个网站拥有巨大的用户访问量时,我们可以使用 Redis 的 HyperLogLog 来统计网站的 UV (网站独立访客)数据,它提供的去重计数方案,虽说不精确,但 0.81% 的误差足以满足 UV 统计的需求。

常用命令

命令说明
PFADD key element [element ...]添加指定元素到 HyperLogLog key 中。
PFCOUNT key [key ...]返回指定 HyperLogLog key 的基数估算值。
PFMERGE destkey sourcekey [sourcekey ...]将多个 HyperLogLog key 合并为一个 key。

基本命令

HyperLogLog 提供了三个常用命令,分别是PFADDPFCOUNTPFMERGE

下面看一组实例演示:假设有 6 个用户(user01-user06),他们分别在上午 8 与 9 点访问了www.baidu.com

#向指定的key中添加用户
127.0.0.1:6379> PFADD user:uv:2021011308 user01 user02 user03
(integer) 1
#向指定的key中添加用户
127.0.0.1:6379> PFADD user:uv:2021011309 user04 user05
(integer) 1
#统计基数值
127.0.0.1:6379> PFCOUNT user:uv:2021011308
(integer) 3
#重复元素不能添加成功,其基数仍然为3
127.0.0.1:6379> PFADD user:uv:2021011308 user01 user02
(integer) 0
127.0.0.1:6379> PFCOUNT user:uv:2021011308
(integer) 3
#添加新元素值
127.0.0.1:6379> PFADD user:uv:2021011308 user06
(integer) 1
#基数值变为4
127.0.0.1:6379> PFCOUNT user:uv:2021011308
(integer) 4
#统计两个key的基数值
127.0.0.1:6379> PFCOUNT user:uv:2021011308 user:uv:2021011309
(integer) 6
#将两个key值合并为一个
127.0.0.1:6379> PFMERGE user:uv:2021011308-09 user:uv:2021011308 user:uv:2021011309
OK
#使用合并后key统计基数值
127.0.0.1:6379> PFCOUNT user:uv:2021011308-09
(integer) 6
2.2.7 性能测试
2.2.7.1 测试命令格式

执行测试命令,要在 Redis 的安装目录下执行,命令如下所示:

redis-benchmark [option] [option value]

 

其中 option 为可选参数, option value 为具体的参数值。 redis-benchmark 命令的可选参数如下所示:

参数选项说明
-h指定服务器主机名。
-p指定服务器端口。
-s指定服务器 socket。
-c指定并发连接数。
-n指定请求的具体数量。
-d以字节的形式指定 SET/GET 值的数据大小。
-k1 表示 keep alive;0 表示 reconnect,默认为 1。
-rSET/GET/INCR 使用随机 key, SADD 使用随机值。
-PPipeline 请求
-q强制退出 Redis,仅显示 query/sec 值。
--csv以 CSV 格式输出。
-l生成循环,永久执行测试。
-t仅运行以逗号分隔的测试命令列表。
-I(大写i)空闲模式,打开 N 个空闲连接并等待连接。

在 Windows 系统下,其目录文件如图所示:

2.2.8 CONFIG 动态修改配置

config 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等

注意:config不是所有配置都可以动态修改,且此方式无法持久保存的,比如:客户端连接情况,redis服务端系统状态

config 查询redis服务配置项

 

#CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),在Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所有配置参数都已经可以用 CONFIG GET 访问了
config get connected_clients	 #redis客户端连接数
config get maxmemory			#redis工作线程最大内存空间大小

#CONFIG GET命令支持模糊搜索配置项
127.0.0.1:6379> config get *		#列表redis所有配置参数项
  1) "dbfilename"		#奇数行为key
  2) "dump_6379.rdb"	#偶数行为value
  3) "requirepass"
  4) ""

127.0.0.1:6379>  CONFIG GET bind
1) "bind"
2) "0.0.0.0"

127.0.0.1:6379>  CONFIG GET *pass*
1) "requirepass"
2) ""

config set 临时性状态修改redis配置项立即生效

config set <parameter> <value>

 范例:config 设置连接密码

#config get requirepass 设置redis连接密码
127.0.0.1:6379> config set requirepass 123456
OK

#设置密码显示ok立即生效,此时不能查看redis信息,需要密码验证
127.0.0.1:6379> config get requirepass
(error) NOAUTH Authentication required.

#auth <password> 输入连接密码进行验证
127.0.0.1:6379> AUTH 123456
OK

#auth密码验证后再次查询配置项
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"

 范例:更改最大内存

127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"

127.0.0.1:6379> config set maxmemory 209715200
OK
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "209715200"
2.2.9 服务器命令行中常用命令

下表介绍了 Redis 服务器的常用命令:

命令说明
BGREWRITEAOF在后台以异步的方式执行一个 AOF 文件的重写操作,对源文件进行压缩,使其体积变小。 AOF 是实现数据持久化存储的方式之一。
BGSAVE在后台执行初始化操作,并以异步的方式将当前数据库的数据保存到磁盘中。
CLIENT KILL [ip:port] [ID client-id]关闭客户端连接。
CLIENT LIST获取连接到服务器的客户端连接列表。
CLIENT GETNAME获取当前连接客户端的名称。
CLIENT PAUSE timeout使服务器在指定的时间停止执行来自客户端的命令。
CLIENT SETNAME connection-name设置当前连接客户端的名称。
COMMAND返回所有 Redis 命令的详细描述信息。
COMMAND COUNT此命令用于获取 Redis 命令的总数。
COMMAND GETKEYS获取指定命令的所有键。
INFO [section]获取 Redis 服务器的各种信息和统计数值。
COMMAND INFO command-name [command-name ...]用于获取指定 Redis 命令的描述信息。
CONFIG GET parameter获取指定配置参数的值。
CONFIG REWRITE修改启动 Redis 服务器时所指定的 redis.conf 配置文件。
CONFIG SET parameter value修改 Redis 配置参数,无需重启。
CONFIG RESETSTAT重置 INFO 命令中的某些统计数据。
DBSIZE返回当前数据库中 key 的数量。
DEBUG OBJECT key获取 key 的调试信息。当 key 存在时,返回有关信息;当 key 不存在时,返回一个错误。
DEBUG SEGFAULT使用此命令可以让服务器崩溃。
FLUSHALL清空数据库中的所有键。
FLUSHDB清空当前数据库的所有 key。
LASTSAVE返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 格式表示。
MONITOR实时打印出 Redis 服务器接收到的命令。
ROLE查看主从实例所属的角色,角色包括三种,分别是 master、slave、sentinel。
SAVE执行数据同步操作,将 Redis 数据库中的所有数据以 RDB 文件的形式保存到磁盘中。 RDB 是 Redis 中的一种数据持久化方式。
SHUTDOWN [NOSAVE] [SAVE]将数据同步到磁盘后,然后关闭服务器。
SLAVEOF host port此命令用于设置主从服务器,使当前服务器转变成为指定服务器的从属服务器, 或者将其提升为主服务器(执行 SLAVEOF NO ONE 命令)。
SLOWLOG subcommand [argument]用来记录查询执行时间的日志系统。
SYNC用于同步主从服务器。
SWAPDB index index用于交换同一 Redis 服务器上的两个数据库,可以实现访问其中一个数据库的客户端连接,也可以立即访问另外一个数据库的数据。
TIME此命令用于返回当前服务器时间。

 

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值