热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis五大数据类型及常用命令使用超级详解

一、redis性能测试redis-benchmark是一个压力测试工具,是官方自带的性能测试工具。redis-benchmark命令参数redis性能测试工具可选

一、redis性能测试

redis-benchmark 是一个压力测试工具,是官方自带的性能测试工具。

redis-benchmark 命令参数

redis 性能测试工具可选参数如下所示:


序号选项描述默认值
1-h指定服务器主机名127.0.0.1
2-p指定服务器端口6379
3-s指定服务器 socket
4-c指定并发连接数50
5-n指定请求数10000
6-d以字节的形式指定 SET/GET 值的数据大小2
7-k1=keep alive 0=reconnect1
8-rSET/GET/INCR 使用随机 key, SADD 使用随机值
9-P通过管道传输 请求1
10-q强制退出 redis。仅显示 query/sec 值
11--csv以 CSV 格式输出
12-l生成循环,永久执行测试
13-t仅运行以逗号分隔的测试命令列表。
14-IIdle 模式。仅打开 N 个 idle 连接并等待。

简单执行一下测试:

测试:100个并发连接,10000个请求

执行命令:redis-benchmark -h localhost -p 6379 -c 100 -n 100000

进入redis默认安装目录 /usr/local/bin 中启动redis 

 

[root@localhost bin]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
&#61;&#61;&#61;&#61;&#61;&#61; PING_INLINE &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.14 seconds100 parallel clients3 bytes payloadkeep alive: 181.94% <&#61; 1 milliseconds
99.50% <&#61; 2 milliseconds
99.99% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
87719.30 requests per second&#61;&#61;&#61;&#61;&#61;&#61; PING_BULK &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.18 seconds100 parallel clients3 bytes payloadkeep alive: 177.48% <&#61; 1 milliseconds
99.53% <&#61; 2 milliseconds
99.89% <&#61; 3 milliseconds
99.97% <&#61; 4 milliseconds
100.00% <&#61; 4 milliseconds
84961.77 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 179.92% <&#61; 1 milliseconds
99.44% <&#61; 2 milliseconds
99.90% <&#61; 3 milliseconds
99.90% <&#61; 12 milliseconds
100.00% <&#61; 13 milliseconds
100.00% <&#61; 13 milliseconds
86058.52 requests per second&#61;&#61;&#61;&#61;&#61;&#61; GET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.12 seconds100 parallel clients3 bytes payloadkeep alive: 183.42% <&#61; 1 milliseconds
99.84% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
89605.73 requests per second&#61;&#61;&#61;&#61;&#61;&#61; INCR &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.13 seconds100 parallel clients3 bytes payloadkeep alive: 182.80% <&#61; 1 milliseconds
99.65% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
88731.15 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPUSH &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 178.40% <&#61; 1 milliseconds
99.63% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
86355.79 requests per second&#61;&#61;&#61;&#61;&#61;&#61; RPUSH &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 179.61% <&#61; 1 milliseconds
99.50% <&#61; 2 milliseconds
99.92% <&#61; 15 milliseconds
99.99% <&#61; 16 milliseconds
100.00% <&#61; 16 milliseconds
85910.65 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 178.22% <&#61; 1 milliseconds
99.67% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
86430.43 requests per second&#61;&#61;&#61;&#61;&#61;&#61; RPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.14 seconds100 parallel clients3 bytes payloadkeep alive: 180.66% <&#61; 1 milliseconds
99.53% <&#61; 2 milliseconds
99.93% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
87336.24 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SADD &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.10 seconds100 parallel clients3 bytes payloadkeep alive: 185.11% <&#61; 1 milliseconds
99.82% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
90661.83 requests per second&#61;&#61;&#61;&#61;&#61;&#61; HSET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.17 seconds100 parallel clients3 bytes payloadkeep alive: 177.08% <&#61; 1 milliseconds
99.59% <&#61; 2 milliseconds
100.00% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
85397.09 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.17 seconds100 parallel clients3 bytes payloadkeep alive: 179.06% <&#61; 1 milliseconds
99.20% <&#61; 2 milliseconds
99.93% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
85616.44 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPUSH (needed to benchmark LRANGE) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.20 seconds100 parallel clients3 bytes payloadkeep alive: 174.79% <&#61; 1 milliseconds
99.38% <&#61; 2 milliseconds
99.89% <&#61; 3 milliseconds
99.96% <&#61; 4 milliseconds
100.00% <&#61; 4 milliseconds
83472.46 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LRANGE_100 (first 100 elements) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 3.36 seconds100 parallel clients3 bytes payloadkeep alive: 10.00% <&#61; 1 milliseconds
24.02% <&#61; 2 milliseconds
80.28% <&#61; 3 milliseconds
95.57% <&#61; 4 milliseconds
99.37% <&#61; 5 milliseconds
99.86% <&#61; 6 milliseconds
99.96% <&#61; 7 milliseconds
99.99% <&#61; 8 milliseconds
100.00% <&#61; 8 milliseconds
29788.50 requests per second^CANGE_300 (first 300 elements): 12106.58
[root&#64;localhost bin]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
&#61;&#61;&#61;&#61;&#61;&#61; PING_INLINE &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.13 seconds100 parallel clients3 bytes payloadkeep alive: 182.57% <&#61; 1 milliseconds
99.87% <&#61; 2 milliseconds
100.00% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
88731.15 requests per second&#61;&#61;&#61;&#61;&#61;&#61; PING_BULK &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.11 seconds100 parallel clients3 bytes payloadkeep alive: 184.39% <&#61; 1 milliseconds
99.72% <&#61; 2 milliseconds
99.97% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
89928.05 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 179.64% <&#61; 1 milliseconds
99.63% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
86430.43 requests per second&#61;&#61;&#61;&#61;&#61;&#61; GET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.12 seconds100 parallel clients3 bytes payloadkeep alive: 184.03% <&#61; 1 milliseconds
99.63% <&#61; 2 milliseconds
99.89% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
89285.71 requests per second&#61;&#61;&#61;&#61;&#61;&#61; INCR &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.14 seconds100 parallel clients3 bytes payloadkeep alive: 181.28% <&#61; 1 milliseconds
99.74% <&#61; 2 milliseconds
100.00% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
87719.30 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPUSH &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.26 seconds100 parallel clients3 bytes payloadkeep alive: 170.63% <&#61; 1 milliseconds
98.37% <&#61; 2 milliseconds
99.41% <&#61; 3 milliseconds
99.68% <&#61; 4 milliseconds
99.70% <&#61; 5 milliseconds
99.72% <&#61; 6 milliseconds
99.76% <&#61; 7 milliseconds
99.80% <&#61; 10 milliseconds
99.84% <&#61; 11 milliseconds
100.00% <&#61; 11 milliseconds
79239.30 requests per second&#61;&#61;&#61;&#61;&#61;&#61; RPUSH &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.17 seconds100 parallel clients3 bytes payloadkeep alive: 177.07% <&#61; 1 milliseconds
99.80% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
85543.20 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.20 seconds100 parallel clients3 bytes payloadkeep alive: 173.55% <&#61; 1 milliseconds
99.66% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
83542.19 requests per second&#61;&#61;&#61;&#61;&#61;&#61; RPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.16 seconds100 parallel clients3 bytes payloadkeep alive: 178.35% <&#61; 1 milliseconds
99.76% <&#61; 2 milliseconds
99.97% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
86281.27 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SADD &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.13 seconds100 parallel clients3 bytes payloadkeep alive: 181.52% <&#61; 1 milliseconds
99.89% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
88105.73 requests per second&#61;&#61;&#61;&#61;&#61;&#61; HSET &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.15 seconds100 parallel clients3 bytes payloadkeep alive: 178.64% <&#61; 1 milliseconds
99.87% <&#61; 2 milliseconds
100.00% <&#61; 2 milliseconds
86805.56 requests per second&#61;&#61;&#61;&#61;&#61;&#61; SPOP &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.14 seconds100 parallel clients3 bytes payloadkeep alive: 181.76% <&#61; 1 milliseconds
99.61% <&#61; 2 milliseconds
99.90% <&#61; 10 milliseconds
99.99% <&#61; 11 milliseconds
100.00% <&#61; 11 milliseconds
87412.59 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LPUSH (needed to benchmark LRANGE) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.18 seconds100 parallel clients3 bytes payloadkeep alive: 176.46% <&#61; 1 milliseconds
99.43% <&#61; 2 milliseconds
99.91% <&#61; 3 milliseconds
100.00% <&#61; 4 milliseconds
100.00% <&#61; 4 milliseconds
84817.64 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LRANGE_100 (first 100 elements) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 3.38 seconds100 parallel clients3 bytes payloadkeep alive: 10.00% <&#61; 1 milliseconds
23.43% <&#61; 2 milliseconds
80.89% <&#61; 3 milliseconds
96.01% <&#61; 4 milliseconds
99.55% <&#61; 5 milliseconds
99.77% <&#61; 6 milliseconds
99.80% <&#61; 7 milliseconds
99.81% <&#61; 10 milliseconds
99.85% <&#61; 11 milliseconds
99.91% <&#61; 12 milliseconds
99.96% <&#61; 19 milliseconds
100.00% <&#61; 20 milliseconds
100.00% <&#61; 20 milliseconds
29629.63 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LRANGE_300 (first 300 elements) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 8.34 seconds100 parallel clients3 bytes payloadkeep alive: 10.00% <&#61; 2 milliseconds
0.02% <&#61; 3 milliseconds
6.31% <&#61; 4 milliseconds
25.89% <&#61; 5 milliseconds
48.11% <&#61; 6 milliseconds
71.67% <&#61; 7 milliseconds
88.69% <&#61; 8 milliseconds
94.52% <&#61; 9 milliseconds
97.91% <&#61; 10 milliseconds
99.65% <&#61; 11 milliseconds
99.99% <&#61; 12 milliseconds
100.00% <&#61; 12 milliseconds
11988.97 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LRANGE_500 (first 450 elements) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 11.96 seconds100 parallel clients3 bytes payloadkeep alive: 10.00% <&#61; 4 milliseconds
0.23% <&#61; 5 milliseconds
9.05% <&#61; 6 milliseconds
22.72% <&#61; 7 milliseconds
37.67% <&#61; 8 milliseconds
53.92% <&#61; 9 milliseconds
70.55% <&#61; 10 milliseconds
84.58% <&#61; 11 milliseconds
90.99% <&#61; 12 milliseconds
94.95% <&#61; 13 milliseconds
97.38% <&#61; 14 milliseconds
98.85% <&#61; 15 milliseconds
99.58% <&#61; 16 milliseconds
99.76% <&#61; 17 milliseconds
99.87% <&#61; 18 milliseconds
99.93% <&#61; 19 milliseconds
99.97% <&#61; 20 milliseconds
100.00% <&#61; 21 milliseconds
100.00% <&#61; 21 milliseconds
8360.50 requests per second&#61;&#61;&#61;&#61;&#61;&#61; LRANGE_600 (first 600 elements) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 15.49 seconds100 parallel clients3 bytes payloadkeep alive: 10.00% <&#61; 3 milliseconds
0.00% <&#61; 4 milliseconds
0.03% <&#61; 5 milliseconds
0.10% <&#61; 6 milliseconds
2.27% <&#61; 7 milliseconds
11.41% <&#61; 8 milliseconds
22.08% <&#61; 9 milliseconds
33.61% <&#61; 10 milliseconds
46.01% <&#61; 11 milliseconds
58.87% <&#61; 12 milliseconds
71.66% <&#61; 13 milliseconds
83.39% <&#61; 14 milliseconds
89.39% <&#61; 15 milliseconds
93.06% <&#61; 16 milliseconds
95.57% <&#61; 17 milliseconds
97.17% <&#61; 18 milliseconds
98.20% <&#61; 19 milliseconds
98.84% <&#61; 20 milliseconds
99.16% <&#61; 21 milliseconds
99.31% <&#61; 22 milliseconds
99.43% <&#61; 23 milliseconds
99.53% <&#61; 24 milliseconds
99.63% <&#61; 25 milliseconds
99.73% <&#61; 26 milliseconds
99.81% <&#61; 27 milliseconds
99.90% <&#61; 28 milliseconds
99.97% <&#61; 29 milliseconds
99.99% <&#61; 30 milliseconds
100.00% <&#61; 30 milliseconds
6457.45 requests per second&#61;&#61;&#61;&#61;&#61;&#61; MSET (10 keys) &#61;&#61;&#61;&#61;&#61;&#61;100000 requests completed in 1.42 seconds100 parallel clients3 bytes payloadkeep alive: 140.75% <&#61; 1 milliseconds
98.82% <&#61; 2 milliseconds
99.95% <&#61; 3 milliseconds
100.00% <&#61; 3 milliseconds
70274.07 requests per second

分析测试结果&#xff1a;


二、基础使用命令详解 

1、redis默认有16个数据库

默认使用的是第0个数据库

2、基础常用命令

切换数据库&#xff0c;命令&#xff1a;select 3

查看数据库大小&#xff0c;命令&#xff1a;dbsize 

127.0.0.1:6379> select 3 # 切换数据库
OK
127.0.0.1:6379[3]> dbsize # 查看数据库大小
(integer) 0
127.0.0.1:6379[3]>

数据库中放值&#xff0c;命令&#xff1a;set name helloworld

数据库中取值&#xff0c;命令&#xff1a;get name

查看数据库中所有的key&#xff0c;命令&#xff1a;keys *

127.0.0.1:6379[3]> set name helloworld # 数据库中放值
OK
127.0.0.1:6379[3]> get name # 数据库中取值
"helloworld"
127.0.0.1:6379[3]> keys * # 查看数据库中所有的key
1) "name"
127.0.0.1:6379[3]>

清空当前数据库&#xff0c;命令&#xff1a;flushdb

127.0.0.1:6379[3]> flushdb # 清空当前数据库
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]>

 清空所有数据库&#xff0c;命令&#xff1a;flushall

127.0.0.1:6379[3]> select 3
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> set name helloworld
OK
127.0.0.1:6379[3]> keys *
1) "name"
127.0.0.1:6379[3]> select 4
OK
127.0.0.1:6379[4]> keys *
(empty list or set)
127.0.0.1:6379[4]> set name love
OK
127.0.0.1:6379[4]> keys *
1) "name"
127.0.0.1:6379[4]> flushall # 清空所有数据库
OK
127.0.0.1:6379[4]> keys *
(empty list or set)
127.0.0.1:6379[4]> select 3
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]>

3、redis的端口号

6379  &#xff08;为什么redis的端口号是6379  Redis端口为什么是6379?_corleone_4ever的博客-CSDN博客_redis端口&#xff09;

4、redis是单线程的

 redis很快&#xff0c;官方表示&#xff0c;redis是基于内存操作的&#xff0c;CPU不是redis的性能瓶颈&#xff0c;redis的性能瓶颈是根据机器的内存和网络带宽来决定的。

redis为什么单线程还这么快&#xff1f;

误区1&#xff1a;高性能的服务器一定是多线程的吗&#xff1f;答案是不一定

误区2&#xff1a;多线程&#xff08;多线程使用CPU调度会频繁的进行上下文切换&#xff0c;消耗资源&#xff09;一定比单线程效率高吗&#xff1f;答案是不一定

核心&#xff1a;redis是将所有的数据全部放在内存中的&#xff0c;所有说使用单线程去操作时效率就是最高的&#xff0c;多线程&#xff08;CPU上下文会切换&#xff0c;耗时的操作&#xff09;&#xff0c;对于内存系统来说&#xff0c;如果没有上下文切换效率就是最高的&#xff0c;多次读写都是在一个CPU上的时候&#xff0c;在内存操作情况下&#xff0c;效率就是最快的。


三、redis基本数据类型

redis英文官方网站&#xff1a;https://redis.io/

redis中文官方网站&#xff1a; Redis中文网

摘自官网说明&#xff1a;

Redis-Key

#########################################################################################
127.0.0.1:6379> keys * # 查看当前数据库中所有的key
(empty list or set)
127.0.0.1:6379> set name hao # 放置一个key值
OK
127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> exists name # 判断当前key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> get name # 获取一个key值
"hao"
127.0.0.1:6379> get age
"30"
127.0.0.1:6379> move age 1 # 移除当前的key
(integer) 0
127.0.0.1:6379> move age 2
(integer) 1
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> expire name 10 # 设置key的过期时间&#xff0c;单位是秒
(integer) 1
127.0.0.1:6379> ttl name # 查看当前key的过期剩余时间还有多少秒
(integer) 7
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> set name hao
127.0.0.1:6379> type name # 查看当前key的数据类型
string
127.0.0.1:6379> type age
string
127.0.0.1:6379>

1、String字符串类型

#########################################################################################
127.0.0.1:6379> keys * # 查看当前数据库所有的key值
(empty list or set)
127.0.0.1:6379> set name hao # 放值
OK
127.0.0.1:6379> get name # 获取值
"hao"
127.0.0.1:6379> exists name # 判断key是否存在
(integer) 1
127.0.0.1:6379> append name "hello" # 追加字符串&#xff0c;如果当前key不存在&#xff0c;就相当于set key
(integer) 8
127.0.0.1:6379> get name
"haohello"
127.0.0.1:6379> strlen name # 获取字符串的长度
(integer) 8
#########################################################################################
/**
* 字符串中i&#43;&#43;或者i--操作
*/
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views # 自减1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incrby views 10 # 设置步长&#xff0c;指定增量
(integer) 10
127.0.0.1:6379> incrby views 10
(integer) 20
127.0.0.1:6379> get views
"20"
127.0.0.1:6379> decrby views 5 # 设置步长&#xff0c;指定减量
(integer) 15
127.0.0.1:6379> decrby views 5
(integer) 10
127.0.0.1:6379> get views
"10"
#########################################################################################
/**
* 字符串范围range
*/
127.0.0.1:6379> set name "hello,i love china" # 设置name的值
OK
127.0.0.1:6379> get name
"hello,i love china"
127.0.0.1:6379> getrange name 0 3 # 获取字符串[0,3]
"hell"
127.0.0.1:6379> getrange name 0 -1 # 获取全部的字符串&#xff0c;和get key是一样的
"hello,i love china"
#########################################################################################
/**
* 替换字符串
*/
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> setrange key2 1 xx # 替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
#########################################################################################
/**
* setex (set with expire) # 设置过期时间
* setnx (set if not expire) # 如果不存在设置过期时间&#xff0c;一般在分布式锁中会常用
*/
127.0.0.1:6379> setex key1 30 "hello" # 设置key1的值为hello&#xff0c;30秒后过期
OK
127.0.0.1:6379> ttl key1
(integer) 23
127.0.0.1:6379> get key1
"hello"
127.0.0.1:6379> ttl key1
(integer) 10
127.0.0.1:6379> setnx mykey "redis" # 如果mykey不存在&#xff0c;则创建mykey并设置值为redis
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
127.0.0.1:6379> setnx mykey "MongoDB" # 如果mykey存在&#xff0c;则会创建失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"
#########################################################################################
/**
* mset 批量设置多个值
* mget 批量获取多个值
*/
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v2 k4 v4 # msetnx是一个原子性的操作&#xff08;要么全部成功&#xff0c;要么全部失败&#xff09;
(integer) 0
127.0.0.1:6379> get k4
(nil)/**
* 设置对象 set user:1{name:zhangsan,age:20} 设置一个user:1对象值为json字符串来保存一个对象
* key的设计规则&#xff1a;user:{id}:{field}
*/
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 20
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "20"
#########################################################################################
/**
* getset 先get在set
*/
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> getset db redis # 如果不存在值&#xff0c;则返回nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb # 如果存在值&#xff0c;则获取原来的值&#xff0c;并设置新的值
"redis"
127.0.0.1:6379> get db
"mongodb"

2、List数据类型

在redis里面&#xff0c;我们可以把list看成是堆、栈、阻塞队列

所有的list命令都是用 l 开头的

#########################################################################################
/**
* lpush key value 将一个值或者多个值&#xff0c;插入到列表的头部&#xff08;左&#xff09;
* lrange key start stop 通过区间获取值
* rpush key value 将一个值或者多个值&#xff0c;插入到列表的尾部&#xff08;右&#xff09;
*/
127.0.0.1:6379> lpush list one # 将一个值或者多个值&#xff0c;插入到列表的头部&#xff08;左&#xff09;
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 # 获取list中所有的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 # 通过区间获取值
1) "three"
2) "two"
127.0.0.1:6379> rpush list rightone # 将一个值或者多个值&#xff0c;插入到列表的尾部&#xff08;右&#xff09;
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "rightone"
#########################################################################################
/**
* lpop key 移除list中的第一个元素
* rpop key 移除list中的最后一个元素
*/
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "rightone"
127.0.0.1:6379> lpop list # 移除list中的第一个元素
"three"
127.0.0.1:6379> rpop list # 移除list中的最后一个元素
"rightone"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
#########################################################################################
/**
* lindex key index 通过下标获取list中的某一个值
*/
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1 # 通过下标获取list中的某一个值
"one"
127.0.0.1:6379> lindex list 0
"two"
#########################################################################################
/**
* llen key 获取list列表的长度
*/
127.0.0.1:6379> lpush list one
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> llen list # 获取列表的长度
(integer) 3
#########################################################################################
/**
* lrem key count value 移除list中值
*/
127.0.0.1:6379> lpush list three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 1 three # 移除list集合中指定个数的value&#xff0c;精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
#########################################################################################
/**
* ltrim key start stop 通过下标截取list指定的长度&#xff0c;这个list已经被改变了&#xff0c;只剩下截取的元素
*/
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpush mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 # 通过下标截取list指定的长度&#xff0c;这个list已经被改变了&#xff0c;只剩下截取的元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
#########################################################################################
/**
* rpoplpush 移除列表中的最后一个元素&#xff0c;将它移动到新的列表中
*/
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> rpoplpush mylist myotherlist # 移除mylist列表中的最后一个元素&#xff0c;将它移动到新的列表myotherlist中
"hello2"
127.0.0.1:6379> lrange mylist 0 -1 # 查看原来的mylist列表
1) "hello"
2) "hello1"
127.0.0.1:6379> lrange myotherlist 0 -1 # 查看目标列表myotherlist中&#xff0c;确实存在移动过去的值
1) "hello2"
#########################################################################################
/**
* lset
*/
127.0.0.1:6379> exists list # 判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item # 如果不存在这个列表&#xff0c;我们去更新就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在这个列表&#xff0c;那么就会更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other # 如果不存在&#xff0c;则会报错
(error) ERR index out of range
#########################################################################################
/**
* linsert 将某个具体的value值插入到列表中某个元素的前面或者后面
*/
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "world"
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> linsert mylist before "world" "other" # 将other元素插入到mylist列表中world元素的前面(before)
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> linsert mylist after "world" "laugh" # 将laugh元素插入到mylist列表中world元素的后面(after)
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
4) "laugh"

 redis中list数据类型总结&#xff1a;


  • 它实际上是一个链表&#xff0c;before node after,left,right都可以插入值。
  • 如果key不存在&#xff0c;就会创建新的链表。
  • 如果key存在&#xff0c;就会新增内容。
  • 如果移除了所以值&#xff0c;就是空链表&#xff0c;也就代表不存在了。
  • 在两边插入或者改动值&#xff0c;效率最高&#xff0c;如果在中间元素插入或者改动值的话&#xff0c;相对来说效率会低一点。

3、Set&#xff08;集合&#xff09;数据类型 

set集合中的元素是不能重复的。

 所有的set命令都是用 s 开头的。

#########################################################################################
/**
* sadd set集合中添加一个元素
* smembers set 查看指定set集合中所有的元素
* sismember set 判断某一个值是否在set集合中
*/
127.0.0.1:6379> sadd myset "hello" # set集合中添加一个元素
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set集合中所有的元素
1) "hello"
2) "world"
127.0.0.1:6379> sismember myset "hello" # 判断某一个值是否在set集合中
(integer) 1
127.0.0.1:6379> sismember myset "china"
(integer) 0
#########################################################################################
/**
* scard 获取set集合中的内容元素个数
*/
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> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> scard myset # 获取set集合中的内容元素个数
(integer) 2
#########################################################################################
/**
* srem 移除set集合中的指定元素
*/
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 "china"
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "china"
3) "world"
127.0.0.1:6379> srem myset "hello" # 移除set集合中的指定元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "china"
2) "world"
#########################################################################################
/**
* set集合是无序不重复&#xff0c;抽随机
* srandmember myset 随机抽取set集合中的一个元素
* srandmember myset count 随机抽取set集合中指定个数的元素
*/
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 "appel"
(integer) 1
127.0.0.1:6379> sadd myset "china"
(integer) 1
127.0.0.1:6379> sadd myset "banana"
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "appel"
3) "china"
4) "world"
5) "banana"
127.0.0.1:6379> srandmember myset # 随机抽取set集合中的一个元素
"world"
127.0.0.1:6379> srandmember myset
"appel"
127.0.0.1:6379> srandmember myset
"banana"
127.0.0.1:6379> srandmember myset 2 # 随机抽取set集合中指定个数的元素
1) "world"
2) "banana"
127.0.0.1:6379> srandmember myset 1
1) "world"
#########################################################################################
/**
* spop myset 随机删除set集合中的一个元素
* spop myset 1 随机删除set集合中指定个数的元素
*
*/
127.0.0.1:6379> sadd myset "a"
(integer) 1
127.0.0.1:6379> sadd myset "b"
(integer) 1
127.0.0.1:6379> sadd myset "c"
(integer) 1
127.0.0.1:6379> smembers myset
1) "a"
2) "c"
3) "b"
127.0.0.1:6379> spop myset # 随机删除set集合中的一个元素
"a"
127.0.0.1:6379> spop myset 1 # 随机删除set集合中指定个数的元素
1) "c"
127.0.0.1:6379> smembers myset
1) "b"
#########################################################################################
/**
* smove 将set集合中的指定的一个值&#xff0c;移动到另外一个set集合中
*
*
*/
127.0.0.1:6379> sadd myset "a"
(integer) 1
127.0.0.1:6379> sadd myset "b"
(integer) 1
127.0.0.1:6379> sadd myset "c"
(integer) 1
127.0.0.1:6379> sadd myset1 "a1"
(integer) 1
127.0.0.1:6379> sadd myset1 "b1"
(integer) 1
127.0.0.1:6379> smembers myset
1) "a"
2) "c"
3) "b"
127.0.0.1:6379> smembers myset1
1) "a1"
2) "b1"
127.0.0.1:6379> smove myset myset1 "a" # 将set集合中的指定的一个值&#xff0c;移动到另外一个set集合中
(integer) 1
127.0.0.1:6379> smembers myset
1) "c"
2) "b"
127.0.0.1:6379> smembers myset1
1) "a"
2) "a1"
3) "b1"
#########################################################################################
/**
* 数字集合类型
* sdiff 差集
* sinter 交集
* sunion 并集
*/
127.0.0.1:6379> sadd myset1 "a"
(integer) 1
127.0.0.1:6379> sadd myset1 "b"
(integer) 1
127.0.0.1:6379> sadd myset1 "c"
(integer) 1
127.0.0.1:6379> sadd myset2 "c"
(integer) 1
127.0.0.1:6379> sadd myset2 "d"
(integer) 1
127.0.0.1:6379> sadd myset2 "e"
(integer) 1
127.0.0.1:6379> smembers myset1
1) "a"
2) "c"
3) "b"
127.0.0.1:6379> smembers myset2
1) "d"
2) "e"
3) "c"
127.0.0.1:6379> sdiff myset1 myset2 # 获取两个set集合的差集
1) "a"
2) "b"
127.0.0.1:6379> sinter myset1 myset2 # 获取两个set集合的交集
1) "c"
127.0.0.1:6379> sunion myset1 myset2 # 获取两个set集合的并集
1) "d"
2) "b"
3) "c"
4) "e"
5) "a"

4、Hash&#xff08;哈希&#xff09;数据类型 

Map集合&#xff0c;key-map的时候这个值是一个map集合。

 所有的hash命令都是用 h 开头的。

#########################################################################################
/**
* hset set一个具体的key-value值
* hget 获取hash中的指定字段的值
* hmset set多个key-value值
* hmget 获取hash中多个字段值
* hgetall 获取hash中全部的数据&#xff0c;是以key-value形式展示
* hdel 删除hash指定key字段的值&#xff0c;删除之后对应的value值也就没有了
*/
127.0.0.1:6379> hset myhash field "a" # set一个具体的key-value值
(integer) 1
127.0.0.1:6379> hget myhash field # 获取hash中的指定字段的值
"a"
127.0.0.1:6379> hmset myhash field1 "hello" field2 "world" # set多个key-value值
OK
127.0.0.1:6379> hmget myhash field field1 field2 # 获取hash中多个字段值
1) "a"
2) "hello"
3) "world"
127.0.0.1:6379> hgetall myhash # 获取hash中全部的数据&#xff0c;是以key-value形式展示
1) "field"
2) "a"
3) "field1"
4) "hello"
5) "field2"
6) "world"
127.0.0.1:6379> hdel myhash field # 删除hash指定key字段的值&#xff0c;删除之后对应的value值也就没有了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
#########################################################################################
/**
* hlen 获取hash表中的字段数量
*
*/
127.0.0.1:6379> hmset myhash field1 "hello" field2 "world"
OK
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hlen myhash # 获取hash表中的字段数量
(integer) 2
#########################################################################################
/**
* hexists 判断hash中指定字段是否存在
*/
127.0.0.1:6379> hset myhash field1 "hello" field2 "world"
(integer) 2
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hexists myhash field1 # 判断hash中指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
#########################################################################################
/**
* hkeys 只获取hash中所有的key
* hvals 只获取hash中所有的value
*/
127.0.0.1:6379> hset myhash field1 "hello" field2 "world"
(integer) 2
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hkeys myhash # 只获取hash中所有的key
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash # 只获取hash中所有的value
1) "hello"
2) "world"
#########################################################################################
/**
* hincrby 指定增量
*
*/
127.0.0.1:6379> hset myhash field1 5
(integer) 1
127.0.0.1:6379> hincrby myhash field1 1 # 指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field1 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field2 "hello" # 如果不存在&#xff0c;则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field2 "world" # 如果存在&#xff0c;则不可以设置
(integer) 0

5、Zset&#xff08;有序集合&#xff09;数据类型

 在set基础上&#xff0c;增加了一个值 set k1 v1   zset k1 score1 v1

#########################################################################################
/**
* zadd 添加一个值或多个值
* zrange 查看所有的值
*/
127.0.0.1:6379> zadd myset 1 one # 添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three # 添加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 # 查看所有的值
1) "one"
2) "two"
3) "three"
#########################################################################################
/**
* 排序如何实现
* zrangebyscore
*/
127.0.0.1:6379> zadd salary 2500 zhangsan # 添加三个用户及对应的薪水
(integer) 1
127.0.0.1:6379> zadd salary 5000 lisi
(integer) 1
127.0.0.1:6379> zadd salary 500 zhaohao
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf &#43;inf # 显示全部用户的用户&#xff0c;从小到大升序排列
1) "zhaohao"
2) "zhangsan"
3) "lisi"
127.0.0.1:6379> zrangebyscore salary -inf &#43;inf withscores # 显示全部用户的用户并附带显示成绩&#xff0c;从小到大升序排列
1) "zhaohao"
2) "500"
3) "zhangsan"
4) "2500"
5) "lisi"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores # 显示工资小于2500的用户并附带显示成绩&#xff0c;从小到大升序排列
1) "zhaohao"
2) "500"
3) "zhangsan"
4) "2500"
#########################################################################################
/**
* zrem 移除set集合中指定的元素
* zcard 获取有序集合中的个数
*/
127.0.0.1:6379> zadd salary 2500 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 5000 lisi
(integer) 1
127.0.0.1:6379> zadd salary 500 zhaohao
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf &#43;inf
1) "zhaohao"
2) "zhangsan"
3) "lisi"
127.0.0.1:6379> zrem salary lisi # 移除set集合中指定的元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zhaohao"
2) "zhangsan"
127.0.0.1:6379> zcard salary # 获取有序集合中的个数
(integer) 2


推荐阅读
  • 本文探讨了Java中有效停止线程的多种方法,包括使用标志位、中断机制及处理阻塞I/O操作等,旨在帮助开发者避免使用已废弃的危险方法,确保线程安全和程序稳定性。 ... [详细]
  • 本文详细介绍了如何在本地环境中安装配置Frida及其服务器组件,以及如何通过Frida进行基本的应用程序动态分析,包括获取应用版本和加载的类信息。 ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
  • 深入解析 RuntimeClass 及多容器运行时应用
    本文旨在探讨RuntimeClass的起源、功能及其在多容器运行时环境中的实际应用。通过详细的案例分析,帮助读者理解如何在Kubernetes集群中高效管理不同类型的容器运行时。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • This article explores the process of integrating Promises into Ext Ajax calls for a more functional programming approach, along with detailed steps on testing these asynchronous operations. ... [详细]
  • 优雅地记录API调用时长
    本文旨在探讨如何高效且优雅地记录API接口的调用时长,通过实际案例和代码示例,帮助开发者理解并实施这一技术,提高系统的可观测性和调试效率。 ... [详细]
  • 构建Python自助式数据查询系统
    在现代数据密集型环境中,业务团队频繁需要从数据库中提取特定信息。为了提高效率并减少IT部门的工作负担,本文探讨了一种利用Python语言实现的自助数据查询工具的设计与实现。 ... [详细]
  • 本文详细解析 Skynet 的启动流程,包括配置文件的读取、环境变量的设置、主要线程的启动(如 timer、socket、monitor 和 worker 线程),以及消息队列的实现机制。 ... [详细]
  • 本文详细介绍了如何使用 Python 编程语言中的 Scapy 库执行 DNS 欺骗攻击,包括必要的软件安装、攻击流程及代码示例。 ... [详细]
  • 深入解析C++ Atomic编程中的内存顺序
    在多线程环境中,为了防止多个线程同时修改同一数据导致的竞争条件,通常会使用内核级同步对象,如事件、互斥锁和信号量等。然而,这些方法往往伴随着高昂的上下文切换成本。本文将探讨如何利用C++11中的原子操作和内存顺序来优化多线程编程,减少不必要的开销。 ... [详细]
  • 本文介绍了一个基本的同步Socket程序,演示了如何实现客户端与服务器之间的简单消息传递。此外,文章还概述了Socket的基本工作流程,并计划在未来探讨同步与异步Socket的区别。 ... [详细]
  • 利用Cookie实现用户登录状态的持久化
    本文探讨了如何使用Cookie技术在Web应用中实现用户登录状态的持久化,包括Cookie的基本概念、优势及主要操作方法,并通过一个简单的Java Web项目示例展示了具体实现过程。 ... [详细]
  • 本文总结了在多人协作开发环境中使用 Git 时常见的问题及其解决方案,包括错误合并分支的处理、使用 SourceTree 查找问题提交、Git 自动生成的提交信息解释、删除远程仓库文件夹而不删除本地文件的方法、合并冲突时的注意事项以及如何将多个提交合并为一个。 ... [详细]
author-avatar
周铭
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有