• Redis 数据库配置与应用


    Redis 是一个由Salvatore Sanfilippo写的key-value存储系统。Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。


    ♥ 文章声明 ♥
    该系列文章部分文字描述,整理于以下文献,化繁为简.
    《鸟哥的Linux私房菜 (基础学习篇 第三版)》 - 作者:鸟哥
    《Linux就该这么学》 - 作者:刘遄
    《linux运维之道》- 作者:丁明一


    编译安装Redis

    1.编译安装依赖.

    [root@localhost ~]# wget https://jaist.dl.sourceforge.net/project/tcl/Tcl/8.5.18/tcl8.5.18-src.tar.gz
    [root@localhost ~]# tar -xzvf tcl8.5.18-src.tar.gz
    [root@localhost ~]# cd tcl8.5.18/unix/
    [root@localhost ~]# ./configure
    [root@localhost ~]# make && make install
    

    2.编译安装Redis.

    [root@localhost ~]# wget http://download.redis.io/releases/redis-4.0.9.tar.gz
    [root@localhost ~]# tar -xzvf redis-4.0.9.tar.gz
    [root@localhost ~]# cd redis-4.0.9/
    [root@localhost ~]# make && make test
    [root@localhost ~]# make PREFIX=/usr/local/redis install
    [root@localhost ~]# cp -a redis.conf /usr/local/redis/				#复制配置文件到Redis目录
    

    3.修改主配置文件.

    [root@localhost ~]# vim /usr/local/redis/redis.conf
    定位特征:# By default Redis does not run as a daemon. Use 'yes' if you ne
    
    daemonize yes								#以守护进程运行
    

    4.启动数据库.

    [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf #启动数据库
    [root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379                        #链接数据库
    

    数据库操作的基本语句

    ◆字符串类型的操作:String◆ <一个字符串,对应一个数据>

    keys  *								#查看所有键值
    get		名称						#查看键值
    
    set		名称	键值					#创建键值
    sexnx	名称	键值						#创建键值(有则不创建,无则创建)
    setex	名称	消失时间	键值				#创建键值(给键值赋予有效期,到期消失)
    ttl		名称						#查看键的生命周期( -1永久/-2不存在)
    
    mset		名称1	键值1	名称2	键值2			#创建多个键值
    mget	名称1	键值1	名称2	键值2				#查看多个键值
    msetnx	名称1	键值1	名称2	键值2				#创建多个键值(无责创建,有责停止)
    
    setrange	名称	修改位置	欲修改值		#修改替换键值
    getset	名称	欲修改值					#先查看键值,在修改成新值
    getrange	名称	起始位置	终止位置		#查看一个键值的部分,从起始到结束
    
    incr		名称						#给键值每次+1
    incrby	名称	增长值						#给键值指定增长值,进行增长
    decr		名称						#给键值每次-1
    
    decrby	名称	减少值						#给键值指定减少值,进行减少
    strlen	名称							#统计键值长度
    
    append	名称	增长的字符					#在指定键值后面追加字符
    del		名称						#删除一个键
    

    ◆哈希类型:Hash◆ <一个字符有多个字段,每个字段拥有独立的键值>

    hset		名称	字段名	键值				#创建指定字段的值
    hget		名称	字段名					#查看指定字段
    hsetnx	名称	字段名	键值					#创建指定字段(无责创建,有责停止)
    
    hmget	名称	字段1 字段2 字段3				#一次性查看键中多个字段的值
    hmset	名称	字段名1	值1	 字段名2 值2			#一次性创建多个字段与值
    
    hlen		名称						#查一个键中有几个字段
    hvals	名称							#查一个键中所有字段的值
    hgetall	名称							#查指定键中的所有字段和值
    
    hdel		名称	字段	键值				#删除指定键中的指定字段
    hkey		名称						#查看键中所有字段
    
    hincrby	名称	字段	键值					#增加自定字段的值
    linsert 	名称 before/after 数值 新值 			#在数值下标的之前/之后 插入新值
    

    ◆集合:Set◆ <交集,并集,补集>

    sadd	 名称 值 						#添加集合
    smembers名称 							#查看集合中所有元素
    
    srandmember 名称 						#随机调取一个数据
    spop 名称 							#随机删除一个数据
    
    srem 名称 值 							#删除指定集合中指定序号的值
    scard 名称 									#查看集合中有几个元素
    sismember 名称 数值 						#查看数值是否在这个集合之中
    
    sdiff 集合1 集合2 						#查两个集合的差集只看集合1的差集
    sdiffstore 集合3 集合1 集合2 					#将两个集合的差集保存到集合3之中
    sinter 集合1 集合2 						#查看两个集合的交集
    
    sinterstore 集合3 集合1 集合2 					#将两个集合的交集并保存到集合3
    sunion 集合1 集合2 						#查看两个集合的并集
    
    sunionstore 集合3 集合1 集合2 					#将两个集合的并集保存到集合3
    smove 集合1 集合2 值 1 						#将集合1中的值移动到集合2
    

    ◆双向队列:List◆ <将多个字符排列起来>

    注意:右序号顺序以数字1、2、3、4..... 从右到左序号顺序以数字-1、-2、-3......
    
    
    lpush 名称1 数值1						#创建队列并写入数值1,默认从左往右插入	
    rpush 名称2 数值1 数值2 数值3					#创建队列并写入多个数值,默认从左往右插入
    
    lrange 名称 数值的下标1 数值的下标2				#查看键,下标1到下标2的值
    linsert 名称 before/after 数值的下标 新值			#在数值下标的 之前/之后 插入新值
    
    lset 名称 数值的下标 新值					#将键的固定数值下标之后的原有值改为新值
    lrem 名称 -+/123[删除的个数] 已有数值				#删除键中多个重复的元素
    ltrim 名称 0 1							#删除表中除了第一个和第二个所有的元素(保留)
    
    lpop 名称							#删除左边第一个值
    rpop 名称							#删除右边第一个值
    
    rpoplpush 名称1 名称2						#将指定队列1中的最后一个元素,移动到新队列2中
    llen 名称							#查看队列长度
    lindex 名称 队列序号						#查看指定序号的内容注意:右序号顺序以数字1、2、3、4..... 从右到左序号顺序以数字-1、-2、-3......
    
    
    lpush 名称1 数值1						#创建队列并写入数值1,默认从左往右插入	
    rpush 名称2 数值1 数值2 数值3					#创建队列并写入多个数值,默认从左往右插入
    
    lrange 名称 数值的下标1 数值的下标2				#查看键,下标1到下标2的值
    linsert 名称 before/after 数值的下标 新值			#在数值下标的 之前/之后 插入新值
    
    lset 名称 数值的下标 新值					#将键的固定数值下标之后的原有值改为新值
    lrem 名称 -+/123[删除的个数] 已有数值				#删除键中多个重复的元素
    ltrim 名称 0 1							#删除表中除了第一个和第二个所有的元素(保留)
    
    lpop 名称							#删除左边第一个值
    rpop 名称							#删除右边第一个值
    
    rpoplpush 名称1 名称2						#将指定队列1中的最后一个元素,移动到新队列2中
    llen 名称							#查看队列长度
    lindex 名称 队列序号						#查看指定序号的内容
    

    ◆有序集合:Zset◆ <相当于集合每个元素之后增加一个数字(必须为数字)相当于分数>

    zadd 名称 数值 (必须是数字) 元素1 ........			#创建有序集合
    zrange 名称 下标1 下标2						#查看集合下标1到下标2的元素 zrange 名称 0 -1 相当于查看所有
    zrange 名称 下标1 下标2						# withscores 查看集合下标1到下标2的元素。以及分值,从小到大排列
    zrevrange 名称 下标1 下标2					# withscores 查看集合下标1到下标2的元素。以及分值,从大到小排列
    zrangebyscore 名称 数字1 数字2					#withscores 查看从数字1到数字2范围的值
    
    zrem 名称 元素							#删除有序集合指定的值
    zincrby 名称 数字 元素						#每次以数字增加大小,如果没有这个集合,则创建
    zrank 名称 元素							#按照元素的数值从小到大的顺序排列取值的下标
    zrevrank 名称 元素						#按照元素的数值从大到小的顺序排列取值得下标
    
    zcard 名称							#统计集合的元素个数
    zcount 名称 数字1 数字2						#统计数字1到数字2之间的元素个数,两数之间的个数
    
    zremrangebyrank 名称 下标1 下标2				#删除从下标1到下标2的元素
    zremrangbyscore 名称 数字1 数字2				#删除从数字1到数字2之间的元素
    
    
    zinterstore 名称3 集合数 名称1 名称2				#取名称1和名称2的交集保存在名称3之中,取出集合之后分数叠加
    zunionstore 名称3 集合数 名称1 名称2				#取名称1和名称2的并集保存在名称3之中,取出集合之后分数叠加
    
    

    ◆全局命令◆ <常用参数>

    dbsize								#统计键的数量
    exists 键名称							#查看键是否存在
    
    expire 键名称 时效时间 						#将键变为定时失效
    rename 键名称 键新名称 						#将键改名
    
    type 键名称 							#查看键是什么类型的键
    info 								#查看数据库的版本信息
    select 数字							#切换数据库(0-15)
    move 键名称1 数据库号						#将当前键移动到别的数据库
    
    flushdb 							#清空当前数据库
    flushall 							#清空所有数据库
    
    

    给Redis设置初始密码

    1.首先打开redis主配置文件,修改requirepass添加密码.

    [root@localhost ~]# vim /usr/local/redis/redis.conf
    
    定位特征:# masterauth <master-password>
    
    requirepass 123									#设置密码为123
    
    

    2.重启redis,并登陆测试密码可用性.

    [root@localhost ~]# pkill redis                                                     #关闭redis
    [root@localhost ~]# /usr/local/redis/bin/redis-server  /usr/local/redis/redis.conf  #启动数据库
    [root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379 -a 123                   #登陆数据库
    
    

    数据库的备份

    首先默认情况下,Redis会将备份文件存储在默认登陆目录下,文件名为dump.rdb,如果要将文件转移到其他位置应该修改其配置文件

    1.修改备份文件保存位置,写入以下内容.

    [root@localhost ~]# vim /usr/local/redis/redis.conf
    
    定位特征:# Note that you must specify a directory here
    
    dir /usr/local/redis								#指定数据库保存位置
    
    

    2.登陆数据库保存重启数据库即可.

    [root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379 -a 123456               #登陆数据库
    [root@localhost ~]# save                                                           #保存数据
    [root@localhost ~]# pkill redis                                                    #关闭redis
    [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf  #启动数据库
    
    

    Redis实现主从同步

    首先需要两台Redis服务器,分别配置主从同步即可

    1.配置主Redis数据库,设置相应密码并启动.

    [root@localhost ~]# vim /usr/local/redis/redis.conf
    
    daemonize  yes									#设置以守护进程运行
    requirepass 123456								#设置主服务器密码
    
    [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf   #启动数据库
    [root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379 -a 123456                #登陆数据库
    
    

    2.配置从Redis数据库,只需要制定主Redis数据库的地址端口和密码即可.

    [root@localhost ~]# vim /usr/local/redis/redis.conf
    
    slaveof 127.0.0.1 6379                      #指定主服务器(主服务器IP +端口号)
    masterauth   123456                         #指定密码(主服务器的密码)
    
    

    Redis +MySQL

    1.配置好LNMP环境

    配置过程请参考,Linux快速安装LNMP环境,此处不再重复.

    2.编译安装Redis,并启动服务,无需设置密码.

    #安装依赖
    [root@localhost ~]# wget https://jaist.dl.sourceforge.net/project/tcl/Tcl/8.5.18/tcl8.5.18-src.tar.gz
    [root@localhost ~]# tar -xzvf tcl8.5.18-src.tar.gz
    [root@localhost ~]# cd tcl8.5.18/unix/
    [root@localhost ~]# ./configure
    [root@localhost ~]# make && make install
    
    #安装Redis
    [root@localhost ~]# wget http://download.redis.io/releases/redis-4.0.9.tar.gz
    [root@localhost ~]# tar -xzvf redis-4.0.9.tar.gz
    [root@localhost ~]# cd redis-4.0.9/
    [root@localhost ~]# make && make test
    [root@localhost ~]# make PREFIX=/usr/local/redis install
    [root@localhost ~]# cp -a redis.conf /usr/local/redis/
    
    #启动Redis
    [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf   #启动数据库
    [root@localhost ~]# /usr/local/redis/bin/redis-cli -p 6379                          #链接数据库
    
    

    3.安装PHP扩展模块,并配置php.ini文件.

    #安装扩展模块
    
    [root@localhost ~]# tar -xzvf phpredis-master.tar.gz
    [root@localhost ~]# cd phpredis-master/
    [root@localhost ~]# phpize         #检测php模块
    
    [root@localhost ~]# ./configure --with-php-config=/usr/bin/php-config
    [root@localhost ~]# make && make install
    
    #写入并重启php-fpm
    [root@localhost ~]# vim /etc/php.ini
    
    extension=redis.so
    
    [root@localhost ~]# systemctl restart php-fpm
    
    

    4.配置MySQL测试字段.

    MariaDB [(none)]> create database mytest;
    Query OK, 1 row affected (0.01 sec)
    
    MariaDB [(none)]> use mytest;
    Database changed
    
    MariaDB [mytest]> create table test(id int,name char(8),primary key(id));
    Query OK, 0 rows affected (0.01 sec)
    
    MariaDB [mytest]> insert into test values(1,'a1'),(2,'a2'),(3,'a3'),(4,'a4'),(5,'a5');
    Query OK, 5 rows affected (0.00 sec)
    Records: 5  Duplicates: 0  Warnings: 0
    
    MariaDB [mytest]> select * from mytest.test;
    
    

    5.创建PHP测试文件.

    [root@localhost ~]# vim /usr/share/nginx/html/test.php
    
    <?php
    $redis = new Redis();
    $redis->connect('127.0.0.1',6379) or die ("could net connect redis server");
    $query = "select * from test limit 4";
    for ($key = 1; $key < 4; $key++)
    {
    	if (!$redis->get($key))
    	{
    		$connect = mysql_connect('127.0.0.1','root','123');
    		mysql_select_db(mytest);
    		$result = mysql_query($query);
    		
    		while ($row = mysql_fetch_assoc($result))
    		{
    			$redis->set($row['id'],$row['name']);
    		} 
    		$myserver = 'mysql';
    		break;
    		} 
    	else
    		{
    			$myserver = "redis";
    			$data[$key] = $redis->get($key);
    		}
    	} 
    	
    	echo $myserver;
    	echo "<br>";
    	
    	for ($key = 1; $key < 4; $key++)
    	{
    		echo "number is <b><font color=#FF0000>$key</font></b>";
    		echo "<br>";
    		echo "name is <b><font color=#FF0000>$data[$key]</font></b>";
    		echo "<br>";
    	}
    ?>
    

    Redis 基本使用

    安装redis 编译文件会复制到/usr/local/bin目录下,直接执行以下代码,立即编译安装.

    yum -y install centos-release-scl
    yum -y install gcc devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
    
    scl enable devtoolset-9 bash
    
    wget http://download.redis.io/releases/redis-6.0.5.tar.gz
    tar xzvf redis-6.0.5.tar.gz
    cd redis-6.0.5
    make && make install
    
    cp -a redis.conf /etc/
    sed -i 's/daemonize no/daemonize yes/g' /etc/redis.conf
    
    redis-server /etc/redis.conf
    redis-cli -p 6379
    

    字符串操作: String 一个字符串,对应一个数据

    keys  *							# 查看所有键值
    get		名称						# 查看键值
    set		名称	键值					# 创建键值
    sexnx	名称	键值					# 创建键值(有则不创建,无则创建)
    setex	名称	消失时间	键值			# 创建键值(给键值赋予有效期,到期消失)
    ttl		名称						# 查看键的生命周期( -1永久/-2不存在)
    
    mset	名称1	键值1	名称2	键值2	# 创建多个键值
    mget	名称1	键值1	名称2	键值2	# 查看多个键值
    msetnx	名称1	键值1	名称2	键值2	# 创建多个键值(无责创建,有责停止)
    
    setrange	名称	修改位置	欲修改值		# 修改替换键值
    getset		名称	欲修改值				# 先查看键值,在修改成新值
    getrange	名称	起始位置	终止位置		# 查看一个键值的部分,从起始到结束
    
    incr		名称						# 给键值每次+1
    incrby	名称	增长值					# 给键值指定增长值,进行增长
    decr		名称						# 给键值每次-1
    
    decrby	名称	减少值					# 给键值指定减少值,进行减少
    strlen	名称							# 统计键值长度
    
    append	名称	增长的字符				# 在指定键值后面追加字符
    del		名称							# 删除一个键
    

    哈希操作: Hash 一个字符有多个字段,每个字段拥有独立的键值

    hset	名称	字段名	键值				# 创建指定字段的值
    hget	名称	字段名					# 查看指定字段
    hsetnx	名称	字段名	键值				# 创建指定字段(无责创建,有责停止)
    
    hmget	名称	字段1 字段2 字段3			# 一次性查看键中多个字段的值
    hmset	名称	字段名1	值1	 字段名2 值2	# 一次性创建多个字段与值
    
    hlen	名称							# 查一个键中有几个字段
    hvals	名称							# 查一个键中所有字段的值
    hgetall	名称							# 查指定键中的所有字段和值
    
    hdel	名称	字段	键值					# 删除指定键中的指定字段
    hkey	名称							# 查看键中所有字段
    
    hincrby	名称	字段	键值					# 增加自定字段的值
    linsert 名称 before/after 数值 新值 	# 在数值下标的之前/之后 插入新值
    

    集合操作: Set 常用的集合有交集,并集,补集

    sadd	 名称 值 						# 添加集合
    smembers 名称 							# 查看集合中所有元素
    
    srandmember 名称 						# 随机调取一个数据
    spop 名称 								# 随机删除一个数据
    
    srem 名称 值 							# 删除指定集合中指定序号的值
    scard 名称 								# 查看集合中有几个元素
    sismember 名称 数值 						# 查看数值是否在这个集合之中
    
    sdiff 集合1 集合2 						# 查两个集合的差集只看集合1的差集
    sdiffstore 集合3 集合1 集合2 				# 将两个集合的差集保存到集合3之中
    sinter 集合1 集合2 						# 查看两个集合的交集
    
    sinterstore 集合3 集合1 集合2 			# 将两个集合的交集并保存到集合3
    sunion 集合1 集合2 						# 查看两个集合的并集
    
    sunionstore 集合3 集合1 集合2 			# 将两个集合的并集保存到集合3
    smove 集合1 集合2 值 1 					# 将集合1中的值移动到集合2
    

    双向队列: List 队列将多个字符排列起来 注意:右序号顺序以数字1、2、3、4..... 从右到左序号顺序以数字-1、-2、-3......

    lpush 名称1 数值1							# 创建队列并写入数值1,默认从左往右插入	
    rpush 名称2 数值1 数值2 数值3					# 创建队列并写入多个数值,默认从左往右插入
    
    lpush 名称1 数值1							# 创建队列并写入数值1,默认从左往右插入	
    rpush 名称2 数值1 数值2 数值3					# 创建队列并写入多个数值,默认从左往右插入
    
    lpop 名称									# 删除左边第一个值
    rpop 名称									# 删除右边第一个值
    
    lrange 名称 数值的下标1 数值的下标2			# 查看键,下标1到下标2的值
    linsert 名称 before/after 数值的下标 新值		# 在数值下标的 之前/之后 插入新值
    
    lset 名称 数值的下标 新值						# 将键的固定数值下标之后的原有值改为新值
    lrem 名称 -+/123[删除的个数] 已有数值			# 删除键中多个重复的元素
    ltrim 名称 0 1								# 删除表中除了第一个和第二个所有的元素(保留)
    rpoplpush 名称1 名称2						# 将指定队列1中的最后一个元素,移动到新队列2中
    llen 名称									# 查看队列长度
    lindex 名称 队列序号							# 查看指定序号的内容
    

    有序集合: Zset 相当于集合每个元素之后增加一个数字(必须为数字)相当于分数

    zadd 名称 数值 (必须是数字) 元素1 ........	# 创建有序集合
    zrange 名称 下标1 下标2						# 查看集合下标1到下标2的元素 zrange 名称 0 -1 相当于查看所有
    zrange 名称 下标1 下标2						# withscores 查看集合下标1到下标2的元素。以及分值,从小到大排列
    zrevrange 名称 下标1 下标2					# withscores 查看集合下标1到下标2的元素。以及分值,从大到小排列
    zrangebyscore 名称 数字1 数字2				# withscores 查看从数字1到数字2范围的值
    
    zrem 名称 元素								# 删除有序集合指定的值
    zincrby 名称 数字 元素						# 每次以数字增加大小,如果没有这个集合,则创建
    zrank 名称 元素								# 按照元素的数值从小到大的顺序排列取值的下标
    zrevrank 名称 元素							# 按照元素的数值从大到小的顺序排列取值得下标
    
    zcard 名称									# 统计集合的元素个数
    zcount 名称 数字1 数字2						# 统计数字1到数字2之间的元素个数,两数之间的个数
    
    zremrangebyrank 名称 下标1 下标2				# 删除从下标1到下标2的元素
    zremrangbyscore 名称 数字1 数字2				# 删除从数字1到数字2之间的元素
    
    zinterstore 名称3 集合数 名称1 名称2			# 取名称1和名称2的交集保存在名称3之中,取出集合之后分数叠加
    zunionstore 名称3 集合数 名称1 名称2			# 取名称1和名称2的并集保存在名称3之中,取出集合之后分数叠
    

    主从同步:

    -- 住redis设置密码
    
    [root@localhost ~]# vim /etc/redis.conf
    requirepass 1233
    bind 0.0.0.0
    
    [root@localhost ~]# pkill redis-server
    [root@localhost ~]# pkill redis
    [root@localhost ~]# redis-server /etc/redis.conf
    [root@localhost ~]# redis-cli -p 6379 -a 1233
    
    -- 从库
    vim /etc/redis.conf
    slaveof 192.168.1.20 6379   # 指定主服务器IP+端口
    masterauth 1233             # 指定主数据库密码
    slave-read-only yes         # 从库只能读
    
    
    127.0.0.1:6379> info replication # 查看主库服务器信息
    127.0.0.1:6379> slaveof no one   # 断开与主节点的主从复制
    
    
    [root@localhost ~]# redis-server /etc/redis.conf --slaveof 192.168.1.20 6379
    

    故障自动切换,可以使用Sentinel哨兵模式,该模式是一个分布式系统,可为企业提供高可用性


    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
  • 相关阅读:
    阿里云物联网平台: 使用阿里云物联网平台提供的自定义Topic通信控制(Air202,TCP透传指令)
    ESA2GJK1DH1K基础篇: 源码使用注意事项和程序优化
    ESP8266 SDK开发: 常见问题及程序BUG修复
    ESP8266 SDK开发: 微信小程序篇-微信小程序通过UDP实现和ESP8266局域网通信控制
    ESP8266 SDK开发: 物联网篇-ESP8266连接阿里云物联网平台,使用阿里云提供的物模型Topic通信控制
    ESP8266 SDK开发: 物联网篇-ESP8266连接阿里云物联网平台,使用阿里云提供的自定义Topic通信控制
    ESA2GJK1DH1K基础篇: APP使用SmartConfig绑定Wi-Fi 设备并通过MQTT控制设备(V1.0)(AT+TCP非透传指令)
    【spring源码分析】@Value注解原理
    【vue】npm、node版本查看及npm常用命令
    【vue】常用操作
  • 原文地址:https://www.cnblogs.com/LyShark/p/11827455.html
Copyright © 2020-2023  润新知