- 本文是在阿里云服务器上进行的学习redis,因此gcc等安装操作不需要进行,可以直接进行安装redis,在安装完成之后,我们进行以下的学习。
- 本次学习的redis安装路径为/usr/local/bin,安装的步骤可以参照尚硅谷教程进行安装。
2.6. Redis 有序集合 Zset(sorted set)
04-概述和安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Rv41177Af?p=4&vd_source=7b32287884d43c4ae590e89cdf55a096
1.Redis的后台启动(推荐)
[root@iZuf6085c1lnhffxqh52xzZ bin]# redis-server /etc/redis.conf
[root@iZuf6085c1lnhffxqh52xzZ bin]# ps -ef | grep redis
root 66433 1 0 19:42 ? 00:00:00 redis-server 127.0.0.1:6379
root 66439 66386 0 19:43 pts/0 00:00:00 grep --color=auto redis
[root@iZuf6085c1lnhffxqh52xzZ bin]# redis-cli
127.0.0.1:6379>
- 首先在usr/local/bin目录下运行 redis-server /etc/redis.conf,这个命令是我们的启动命令。
- ps -ef | grep redis可以查看Redis是否启动了,从上面的运行结果可以知道Redis的端口号为6379。
- redis-cli:使用客户端连接Redis,测试验证–在其中输入ping会有pong回复。
- Redis关闭:进入终端使用shutdown关闭或者在bin目录下使用redis-cli shutdown.
2.Redis相关知识介绍
Redis有五大常用数据类型,分别为:
- Redis 键(key)
- Redis 字符串(String)
- Redis 列表(List)
- Redis 集合(Set)
- Redis 哈希(Hash)
- Redis 有序集合 Zset(sorted set)
2.1 Redis 键(key)
[root@iZuf6085c1lnhffxqh52xzZ ~]# redis-cli
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 caojiajun
OK
127.0.0.1:6379> set k2 jiangwei
OK
127.0.0.1:6379> set k3 icezrj
OK
127.0.0.1:6379> exist k1
(error) ERR unknown command `exist`, with args beginning with: `k1`,
127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> exists k4
(integer) 0
127.0.0.1:6379> type k3
string
127.0.0.1:6379> del k3
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> unlink k2
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> expire k1 20
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> ttl k1
(integer) -2
127.0.0.1:6379> set k2 zeyein
OK
127.0.0.1:6379> set k3 huge
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
127.0.0.1:6379> set k1 icezrj
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379>
特别注意:-2表示已经过期,-1表示永不过期(del删除和unlink删除的区别)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 4
OK
127.0.0.1:6379[4]> select 0
OK
127.0.0.1:6379> dbsize
(integer) 3
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> dbsize
(integer) 0
127.0.0.1:6379> flushall
OK
127.0.0.1:6379>
[root@iZuf6085c1lnhffxqh52xzZ ~]#
flushdb和flushall在现实中用的比较少,dbsize表示查看当前库中(key)键的数量。
- keys * 查看当前库所有key (匹配: keys *1)
- exists key 判断某个key是否存在
- type key 查看你的key是什么类型
- del key 删除指定的key数据
- unlink key 根据value选择非阻塞删除 仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。
- expire key 10 10 秒钟:为给定的key设置过期时间
- ttl key 查看还有多少秒过期,-1 表示永不过期,-2 表示已过期
- select 命令切换数据库
- dbsize 查看当前数据库的key的数量
- flushdb 清空当前库
- flushall 通杀全部库
2.2 Redis 字符串(String)
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 v120
OK
127.0.0.1:6379> set k2 v122
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> get k1
"v120"
127.0.0.1:6379> get k2
"v122"
127.0.0.1:6379> set k2 v1314
OK
127.0.0.1:6379> get k2
"v1314"
127.0.0.1:6379> append k2 502
(integer) 8
127.0.0.1:6379> get k2
"v1314502"
127.0.0.1:6379> strlen k2
(integer) 8
127.0.0.1:6379> strlen k1
(integer) 4
127.0.0.1:6379> setnx k1 123
(integer) 0
127.0.0.1:6379> decr k2
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k3 123
OK
127.0.0.1:6379> incr k3
(integer) 124
127.0.0.1:6379> decr k33
(integer) -1
127.0.0.1:6379> decr k3
(integer) 123
127.0.0.1:6379> decr k2
(error) ERR value is not an integer or out of range
127.0.0.1:6379> get k3
"123"
127.0.0.1:6379> incrby k3 10
(integer) 133
127.0.0.1:6379> decrby k3 30
(integer) 103
127.0.0.1:6379> keys *
1) "k1"
2) "k33"
3) "k3"
4) "k2"
127.0.0.1:6379> mset k1 1 k2 2 k3 5
OK
127.0.0.1:6379> mget k1 k2 k3
1) "1"
2) "2"
3) "5"
127.0.0.1:6379> msetnx k1 3 k4 6
(integer) 0
127.0.0.1:6379> msetnx k4 6 k5 66
(integer) 1
127.0.0.1:6379>
incr是原子操作:所谓原子操作是指不会被线程调度机制打断的操作
- (1)在单线程中, 能够在单条指令中完成的操作都可以认为是”原子操作“,因为中 断只能发生于指令之间。
- (2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。 Redis 单命令的原子性主要得益于 Redis 的单线程。
- mset <key1><value><key2><value><key3><value>…..同时设置一个或多个 key-value
- mget <key1><key2><key3> 同时获取一个或多个 value
- msetnx <key1><value><key2><value><key3><value>…..同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
- get <key> 查询对应键值
- append <key> <value>将给定的<value>追加到原值的末尾
- strlen <key> 获得值的长度
- setnx <key> <value>只有在key不存在时设置 key的值
- incr <key>将key中储存的数字值增1,只能对数字值操作,如果为空,新增值为1
- decr <key>将key中储存的数字值减1,只能对数字值操作,如果为空,新增值为-1
- incrby / decrby <key> <步长>将key中储存的数字值增减。自定义步长。
2.3. Redis 列表(List)
- lpush/rpush <key> <value1> <value2> <value3> … 从左边/右边插入-个或多个值。
- lpop/rpop <key> 从左边/右边吐出一一个值。 值在键在,值光键亡。
- rpoplpush <key1> <key2> 从<key1>列表右边吐出一个值, 插到<key2>列表左边。
- lrange <key> <start> <stop> 按照索引下标获得元素(从左到右)
- lrange mylist0-1 0 左边第一个,-1 右边第一个,(0-1 表示获取所有)
- lindex <key> <index> 按照索引下标获得元素(从左到右)
- llen <key> 获得列表长度
- linsert <key> before <value> <newvalue> 在<value>的后面插入<newvalue >插入值
- Irem <key> <n> <value> 从左边删除n个value(从左到右)
- Iset <key> <index> <value> 将列表key下标为index的值替换成value
2.4. Redis 集合(Set)
Redis set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选 择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所 不能提供的。
- sadd. <key> <value1> <value2> …. 将一个或多个member元素加入到集合key中,已经存在的member元素将被忽略
- smembers <key> 取出该集合的所有值。
- sismember <key> <value> 判断集合<key>是否为含有该<value>值,有1,没有0
- scard <key> 返回该集合的元素个数。
- srem <key> <value1> <value2> … 删除集合中的某个元素。
- spop <key> 随机从该集合中吐出一个值。
- srandmember <key> <n> 随机从该集合中取出n个值。不会从集合中删除。
- smove <source> <destination>value 把集合中一个值从-一个集合移动到另一个集合
- sinter <key1> <key2> 返回两个集合的交集元素。
- sunion <key1> <key2> 返回两个集合的并集元素。
- sdiff <key1> <key2> 返回两个集合的差集元素(key1中的,不包含key2中的)
2.5. Redis 哈希(Hash)
Redis hash 是一个键值对集合。 Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。 类似 Java 里面的 Map 用户 ID 为查找的 key,存储的 value 用户对象包含姓名,年龄,生日等信息,如果用 普通的 key/value 结构来存储
- hset <key><field><value> 给<key>集合中的<field> 键赋值<value>
- hget <keyl><field> 从<key1>集合<field>取出value
- hmset <key1><field1><value1><field2><value2>… 批量设置hash的值
- hexists<key1><field> 查看哈希表key中,给定域field 是否存在。
- hkeys <key> 列出该hash集合的所有field
- hvals <key> 列出该hash集合的所有value
- hincrby <key><field>< increment> 为哈希表key中的域field 的值加.上增量1 -1
- hsetnx <key><field><value> 将哈希表key中的域field 的值设置为value ,当且仅当域field不存在.
2.6. Redis 有序集合 Zset(sorted set)
Redis 有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合。
不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用 来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分 可以是重复了 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获 取一个范围的元素。 访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成 员的智能列表。
- zadd <key> <score1> <value1> <score2> <value2>… 将一个或多个member元素及其score值加入到有序集key当中。
- zrange <key> <start> <stop> [WITHSCORES] 返回有序集key中,下标在<start><stop> 之间的元素 带WITHSCORES,可以让分数-起和值返回到结果集。
- zrangebyscore key minmax [withscores] [limit offset count] 返回有序集key中,所有score 值介于min和max之间(包括等于min或max )的成员。
- 有序集成员按score值递增(从小到大)次序排列。
- zrevrangebyscore key maxmin [withscores] [limit offset count] 同上,改为从大到小排列。
- zincrby <key> <increment> <value> 为元素的score加上增量
- zrem <key> <value> 删除该集合下,指定值的元素
- zcount <key> <min> <max> 统计该集合,分数区间内的元素个数
- zrank <key> <value> 返回该值在集合中的排名,从0开始。
3.配置文件
在安装Redis之后是将配置文件放在了目录/etc/redis.conf下面,使用vi命令将其打开,现在对其进行分析。
3.1 单位
配置大小单位,开头定义了一些基本的度量单位,只支持 bytes,不支持 bit 大小写不敏感。
[root@iZuf6085c1lnhffxqh52xzZ ~]# vi /etc/redis.conf
# Redis configuration file example.
#
# Note that in order to read the configuration file, Redis must be
# started with the file path as first argument:
#
# ./redis-server /path/to/redis.conf
# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.
3.2 INCLUDES 包含
类似 jsp 中的 include,多实例的情况可以把公用的配置文件提取出来
# Include one or more other config files here. This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings. Include files can include
# other files, so use this wisely.
#
# Note that option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf
3.3 网络相关配置
默认情况 bind=127.0.0.1 只能接受本机的访问请求不写的情况下(注释后),无限制接受任何 ip 地址的访问。
- Port
设置 tcp 的 backlog,backlog 其实是一个连接队列,backlog 队列总和=未完成三次握手 队列 + 已经完成三次握手队列。
在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。
注意 Linux 内核会将这个值减小到/proc/sys/net/core/somaxconn 的值(128),所以需要 确认增大/proc/sys/net/core/somaxconn 和/proc/sys/net/ipv4/tcp_max_syn_backlog(128) 两个值来达到想要的效果
一个空闲的客户端维持多少秒会关闭,0 表示关闭该功能。即永不关闭。
对访问客户端的一种心跳检测,每个 n 秒检测一次。 单位为秒,如果设置为 0,则不会进行 Keepalive 检测,建议设置成 60
3.4 GENERAL 通用设置
存放 pid 文件的位置,每个实例会产生一个不同的 pid 文件
指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默 认为 notice
- databases 16
设定库的数量 默认 16,默认数据库为 0,可以使用 SELECT 命令在连接上指定 数据库 id
3.5 SECURITY 安全
- 设置密码
在命令中设置密码,只是临时的。重启 redis 服务器,密码就还原了。 永久设置,需要再配置文件中进行设置。
本文就不进行设置了。
- LIMITS 限制
➢ 默认情况下为 10000 个客户端。
➢如果达到了此限制,redis 则会拒绝新的连接请求,并且向这些连接请求方发出 “max number of clients reached”以作回应。
➢ 设置 redis 可以使用的内存量。一旦到达内存使用上限,redis 将会试图移除内部数 据,移除规则可以通过 maxmemory–policy 来指定。
4.Redis 的发布和订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。
SUBSCRIBE channel1
publish channel1 hello
#返回的 1 是订阅者数量
注:发布的消息没有持久化,如果在订阅的客户端收不到 hello,只能收到订阅后发布 的消息
5.Redis 新数据类型
5.1 Bitmaps(位操作)
合理地使用操作位能够有效地提高内存使用率和开发效率。
Redis 提供了 Bitmaps 这个“数据类型”可以实现对位的操作:
- Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value), 但是它可以对字符串的位进行操作。
- Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字 符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。
命令:setbit
setbit<key> <offset> <value> 设置Bitmaps中某个偏移量的值(0 或1)。
- 每个独立用户是否访问过网站存放在 Bitmaps 中, 将访问的用户记做 1, 没有 访问的用户记做 0, 用偏移量作为用户的 id。
- 设置键的第 offset 个位的值(从 0 算起) , 假设现在有 20 个用户,userid=1, 6, 11, 15, 19 的用户对网站进行了访问, 那么当前 Bitmaps 初始化结果如图
- 在第一次初始化 Bitmaps 时, 假如偏移量非常大, 那么整个初始化过程执行会 比较慢, 可能会造成 Redis 的阻塞
命令:getbit
getbit <key> <offset> 获取Bitmaps中某个偏移量的值
获取 id=8 的用户是否在 2020-11-06 这天访问过, 返回 0 说明没有访问过:
计算出两天都访问过网站的用户数量===>
bitop and unique:users:and:20201104_03 unique:users:20201103unique:users:20201104
命令:Bitmaps 与 set 对比
- 很明显, 这种情况下使用 Bitmaps 能节省很多的内存空间, 尤其是随着时间推 移节省的内存还是非常可观的。
- 但 Bitmaps 并不是万金油, 假如该网站每天的独立访问用户很少, 例如只有 10 万(大量的僵尸用户) , 那么两者的对比如下表所示, 很显然, 这时候使用 Bitmaps 就不太合适了, 因为基本上大部分位都是 0。
5.2 HyperLogLog(统计)
pfadd <key> < element> [element ..]添加指定元素到 HyperLogLog中
将所有元素添加到指定 HyperLogLog 数据结构中。如果执行命令后 HLL 估计的 近似基数发生变化,则返回 1,否则返回 0。
[root@iZuf6085c1lnhffxqh52xzZ ~]# redis-cli
127.0.0.1:6379> pfadd zrj "jiangwei"
(integer) 1
127.0.0.1:6379> pfadd zrj "java"
(integer) 1
127.0.0.1:6379> pfadd zrj "c++"
(integer) 1
127.0.0.1:6379> pfadd zrj "c++"
(integer) 0
127.0.0.1:6379> pfcount zrj
(integer) 3
127.0.0.1:6379>
pfmerge <destkey> <sourcekey> [sourcekey] 将-个或多个HLL合并后的结果存储在另一个HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得
5.3 Geospatial(经纬度)
该类型,就是元素的 2 维坐标,在地图上就是经纬度。redis 基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度 Hash 等常见操作。
127.0.0.1:6379> geoadd china:city 121.37 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
(integer) 3
127.0.0.1:6379>
- 两极无法直接添加,一般会下载城市数据,直接通过 Java 程序一次性导入。
- 有效的经度从 -180 度 到 180 度 。 有 效 的纬 度 从 -85.05112878 度 到 85.05112878 度。 当坐标位置超出指定范围时,该命令将会返回一个错误。
- 已经添加的数据,是无法再次往里面添加的。
geopos <key> <member> [member..] 获得指定地区的坐标值
geodist<key> <member1> <member2>[m|km|ft|mi ] 获取两个位置之间的直线距离
georadius<key> < longitude> <latitude>radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素
6.Redis_Jedis_测试
创建maven工程后引入Jedis 所需要的 jar 包
由于引入3.2.0版本我们的idea会报错,于是我们引入2.9.0版本的jedis。
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
在进行操作之前我们需要确保/etc/redis.conf中的bind 127.0.0.1 -::1是注释完成还有protected-mode yes改成protected-mode no。 之后保存这个文件后再重启一下redis,这里可以在本文开头查看如何重启操作,还有将服务器的防火墙规则添加6379端口。(如果是虚拟机则只需要将自己的防火墙关闭 systemctl stop firewalld)
package com.atzrj.jedis;
import redis.clients.jedis.Jedis;
/**
* @Program:jedis_redis
* @description:jedis
* @author:
* @create: 2022-11-17 11
**/
public class jedisDemo1 {
public static void main(String[] args) {
//创建jedis对象
Jedis jedis = new Jedis("此处填写自己的虚拟机ip",6379);
//测试
String value = jedis.ping();
System.out.printf(value);
}
}
6.1 操作key
向redis中添加键值k1,k2,k3,并且获取k3的对应值(value):
System.out.println(jedis.exists("k1"));//查看键值k1是否存在
System.out.println(jedis.ttl("k1")); //查看k1还有多少秒过期,-1 表示永不过期,-2 表示已过期
System.out.println(jedis.get("k1"));
6.2 完成一个手机验证码功能
要求:
package com.atzrj.jedis;
import java.util.Random;
/**
* @Program:jedis_redis
* @description:jedis
* @author: j
* @create: 2022-11-17 18
**/
public class PhoneCode {
public static void main(String[] args) {
String code = getCode();
System.out.println(code);
}
//生成六位数字验证码
public static String getCode() {
Random random = new Random();
String code = "";
for (int i = 0; i < 6; i++) {
int rand = random.nextInt(10);//生成10以内的值
code += rand;
}
return code;
}
}
在完成编写一个生成6位数的类之后,还要完成两点钟内有效和每天只能输入三次,两分钟内有效可以想到使用redis中的expire key times 设置键值的过期时间。
如果报上面的错误输入下面这行代码在redis中再次运行即可。
config set stop-writes-on-bgsave-error no
package com.atzrj.jedis;
import redis.clients.jedis.Jedis;
import java.util.Random;
/**
* @Program:jedis_redis
* @description:jedis
* @author: j
* @create: 2022-11-17 18
**/
public class PhoneCode {
public static void main(String[] args) {
//模拟验证码发送
verifyCode("17779141914");
}
//1.生成六位数字验证码
public static String getCode() {
Random random = new Random();
String code = "";
for (int i = 0; i < 6; i++) {
int rand = random.nextInt(10);//生成10以内的值
code += rand;
}
return code;
}
//2.每个手机每天只能发送三次,验证码放到redis中,设置过期时间
public static void verifyCode(String phone){
//连接redis
Jedis jedis = new Jedis("IP地址", 6379);
//拼接key
//手机发送次数key
String countkey = "VerifyCode"+phone+":count";
//验证码key
String codekey = "VerifyCode"+phone+":code";
//每个手机每天只能发送三次
String count = jedis.get(countkey);
//没有发送次数,第一次发送
//设置发送次数为1
if (count==null){
jedis.setex(countkey,24*60*60,"1");
}else if (Integer.parseInt(count)<=2){
//发送次数+1
jedis.incr(countkey);
}else if (Integer.parseInt(count)>2){
//发送三次,不能在发送了
System.out.println("今天发送次数已达上限!");
jedis.close();
return;//不返回验证码仍会更新,虽然次数已经达到上限
}
//发送的验证码要放到redis中去
String vcode = getCode();
jedis.setex(codekey,120,vcode);
jedis.close();
}
//3.验证码校验
public static void getRedisCode(String phone,String code){
//从redis中获取验证码
Jedis jedis = new Jedis("IP地址", 6379);
//验证码key
String codekey = "VerifyCode"+phone+":code";
String redisCode = jedis.get(codekey);
//判断
if (redisCode.equals(code)){
System.out.println("成功~");
}else {
System.out.println("失败!");
}
jedis.close();
}
}
原文地址:https://blog.csdn.net/weixin_55848732/article/details/127836219
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_30340.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!