什么!Redis不会用!看完这个你就是Redis大牛了!
Posted 还怕大雨吗-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么!Redis不会用!看完这个你就是Redis大牛了!相关的知识,希望对你有一定的参考价值。
redis
1.nosql
联系作者:扣扣 190557020
什么是nosql:
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
常用的NoSQL数据库,Redis,MongoDB,Es,
大致分为以下几种:
-
键值数据库
-
列组数据库
-
文档数据库
-
图形数据库
2.安装redis
windos下安装redis
直接下载直接解压即可用
下载地址:链接: https://pan.baidu.com/s/1chv4tPBCI6tV3HHIb-92Tw 提取码: g9n3
配置一个快速启动的脚本
创建redis-start.bat文件,右击编辑,输入 redis-server redis.windows.conf 保存即可
双击启动
默认端口为6379
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LctcMVXJ-1627702088495)(H:\\技术点\\redis\\redis-这一篇就够了.assets\\1627566370994.png)]
redis-cli.exe 文件是命令行操作,输入keys * 查看所有键
出现以上界面,windows下的Redis就算安装完成了,
linux下本地安装redis
https://www.cnblogs.com/xsge/p/13841875.html
Docker下安装redis:
记得关闭防火墙/开放端口
centos7 下的 docker安装redis
#启动docker
systemctl start docker
#查找redis的镜像
docker search redis
# 下载指定版本,,
docker pull redis:6.0-rc
此处需要联网
#查看docker里的镜像
docker images
#创建挂载目录,配置文件需要将下载一份配置上去,redis.conf,
mkdir -p /home/redis/myredis
#conf文件的目录
//创建data
cd /home/redis/myredis
mkdir data
redis各版本配置文件下载:https://redis.io/topics/config
安装的命令
docker run -p 6379:6379 \\
--name niuzi_redis -v /home/redis/myredis/myredis.conf:/etc/redis/redis.conf \\
-v /home/redis/myredis/data:/data -d redis redis-server /etc/redis/redis.conf \\
--appendonly yes \\
redis:6.0-rc
#二选一,下面这个使用的默认的配置
docker run -itd --name redis6 -p 6379:6379 redis:6.0-rc
–restart=always 总是开机启动
-p 6379:6379 将6379端口挂载出去
–name 给这个镜像取一个名字
-v 数据卷挂载
/home/redis/myredis/myredis.conf:/etc/redis/redis.conf
这里是将 liunx 路径下的myredis.conf 和redis下的redis.conf 挂载在一起。
/home/redis/myredis/data:/data 这个同上
-d redis 表示后台启动redis
redis-server /etc/redis/redis.conf 以配置文件启动redis,加载容器内的conf文件,最终找到的是挂载的目录 /etc/redis/redis.conf 也就是liunx下的/home/redis/myredis/myredis.conf
–appendonly yes 开启redis 持久化
#查看是否安装成功
docker ps -a
#运行redis
docker start niuzi_redis #可以是名称,也可以是最前面的id
#打开redis命令测试
docker exec -it redis6-two redis-cli
#输入测试命令
keys *
出现以下界面则表示安装成功
3.redis相关知识
端口号默认是6379
一共有16个数据库,
redis是单线程
redis可以进行持久化操作
单线程+多路io复用
原子性 所谓原子操作是指不会被线程调度机制打断的操作
这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
(1)在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间。
(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis单命令的原子性主要得益于Redis的单线程。
4.常用五大数据类型
1.对key进行操作
#查看所有key
keys *
#判断该key是否存在 返回1则存在,0则不存在
exists key
#查看key是什么类型
type key
#删除key
del key
#根据value选择非阻塞删除
unlink key
#设置key的过期时间,10描
expire key 10
#查看还有多少秒过期 -1永不过期,-2表示已过期
ttl key
#切换数据库
select 0/1/2/3/....
#查看当前数据库有多少数量的key
dbsize
!!!!!!慎用!!!!!
#清空当前库
flushdb
#通杀全部库
flushall
2.String类型
String是redis最基本的类型,是非常强大的
String类型是二进制安全的,意味着他可以保存任何数据,比如序列化
一个redis中字符串value最多可以是512M
#存入值,重复往key中存储会覆盖值
set key value
#获取值
get key
#追加值
append key value
#获取长度
strlen
#当key不存在的时候设置key的值
setnx key value
3. List类型
单键多值
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差
#从表头添加或表尾
lpush/rpush key value,key value
#从表头或表尾吐出一个值,
lpop/rpop key #键在则在,键光则亡
#根据下标范围获取值 多用于 0 -1 获取全部
lrange key start stop
#在<value>的后面插入<newvalue>插入值
linsert <key> before <value><newvalue>
#从左边删除n个value(从左到右)
lrem <key><n><value>
#将列表key下标为index的值替换成value
lset<key><index><value>
4.set类型
set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
#将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
sadd <key><value1><value2> .....
#取出该集合的所有值
smembers <key>
#判断集合<key>是否为含有该<value>值,有1,没有0
sismember <key><value>
#返回该集合的元素个数。
scard<key>
#删除集合中的某个元素。
srem <key><value1><value2> ....
#随机从该集合中吐出一个值。
spop <key>
#随机从该集合中取出n个值。不会从集合中删除 。
srandmember <key><n>
#返回两个集合的交集元素。
sinter <key1><key2>
#返回两个集合的并集元素。
sunion <key1><key2>
#返回两个集合的差集元素(key1中的,不包含key2中的)
sdiff <key1><key2>
Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值
5.hash类型
Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
类似Java里面的Map<String,Object>
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,
#给<key>集合中的 <field>键赋值<value>
hset <key><field><value>
#从<key1>集合<field>取出 value
hget <key1><field>
#批量设置hash的值
hmset <key1><field1><value1><field2><value2>...
#查看哈希表 key 中,给定域 field 是否存在。
hexists<key1><field>
#列出该hash集合的所有field
hkeys <key>
#列出该hash集合的所有value
hvals <key>
Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
6.zset有序集合
Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。
不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。
访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
多用于,点赞之类的
#将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
zadd <key><score1><value1><score2><value2>…
#返回有序集 key 中,下标在<start><stop>之间的元素
#带WITHSCORES,可以让分数一起和值返回到结果集。
zrange <key><start><stop> [WITHSCORES]
#返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
zrangebyscore key minmax [withscores] [limit offset count]
#同上,改为从大到小排列。
zrevrangebyscore key maxmin [withscores] [limit offset count]
#为元素的score加上增量
zincrby <key><increment><value>
#删除该集合下,指定值的元素
zrem <key><value>
#统计该集合,分数区间内的元素个数
zcount <key><min><max>
#返回该值在集合中的排名,从0开始
zrank <key><value>
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表
zset底层使用了两个数据结构
(1)hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
(2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
7.新数据类型Bitmaps
进行位操作,
合理地使用操作位能够有效地提高内存使用率和开发效率。
(1) Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。
(2) Bitmaps单独提供了一套命令, 所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。
#添加数据-设置Bitmaps中某个偏移量的值(0或1)
setbit key <key><offset><value>
#获取偏移量
get <key><offset>
统计**字符串**被设置为1的bit数。一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,start、end 是指bit组的字节的下标数,二者皆包含
bitcount<key>[start end] #统计字符串从start字节到end字节比特值为1的数量
start和end代表起始和结束字节数
bitop是一个复合操作, 它可以做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中。
bitop and(or/not/xor) <destkey> [key…]
与set对比
当网站用户访问量大的时候可以使用bitmaps,可以节省内存
当网站访问量较小的时候是不如set的
8.新数据类型HyperLogLog
基数统计的算法
在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用Redis的incr、incrby轻松实现。
但像UV(UniqueVisitor,独立访客)、独立IP数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。
解决基数问题有很多种方案:
(1)数据存储在mysql表中,使用distinct count计算不重复个数
(2)使用Redis提供的hash、set、bitmaps等数据结构来处理
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。
能否能够降低一定的精度来平衡存储空间?Redis推出了HyperLogLog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
#添加指定元素到 HyperLogLog 中
pfadd <key>< element> [element ...]
#将所有元素添加到指定HyperLogLog数据结构中。如果执行命令后HLL估计的近似基数发生变化,则返回1,否则返回0。
#统计数量
pfcount <key>
#pfmerge 将一个或多个HLL合并后的结果存储在另一个HLL中
#将k1 k2的值合并放在k3中
pfmerge k3 k1 k2
9.新数据类型Geographic
Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。
geoadd<key>< longitude><latitude><member> [longitude latitude member...]
#实例
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
两极无法直接添加,一般会下载城市数据,直接通过 Java 程序一次性导入。
有效的经度从 -180 度到 180 度。有效的纬度从 -85.05112878 度到 85.05112878 度。
当坐标位置超出指定范围时,该命令将会返回一个错误。
已经添加的数据,是无法再次往里面添加的。
南极与北极不可添加
geopos <key><member> [member...] #获得指定地区的坐标值
#获取两个地区的直线距离是多少
geodist <key><member1><member2> [m|km|ft|mi ]
单位:
m 表示单位为米[默认值]。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位
#以给定的经纬度为中心,找出某一半径内的元素
georadius <key>< longitude><latitude>radius m|km|ft|mi
5.redis发布和订阅
什么是发布和订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道
当给这个频道发布消息后,消息就会发送给订阅的客户端
命令行实现
打开2个客户端,
1、 打开一个客户端订阅channel1
SUBSCRIBE channel1
2丶打开另一个客户端,给channel1发布消息hello
publish channel1 hello
打开第一个客户端可以看到发送的消息,发布的消息没有持久化,如果在订阅的客户端收不到hello,只能收到订阅后发布的消息
6.安装redis可视化
在开发与练习中,频繁的使用命令是不可行的,为了提升开发效率,更直观的将数据展示出来,需要安装一个redis的可视化
软件安装 RedisDesktopManager
链接:https://pan.baidu.com/s/14rpZn6ZEEfpSWT5bOJJEYg
提取码:t16i
傻瓜式安装–一直下一步,安装链接根据个人修改
启动软件
创建redis链接
显示成功链接后点击ok
可以直观的看到,我们有16个数据库。每个数据库存放了什么,值是什么
7.SpringBoot操作redis
1.创建springboot项目
2.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
3.redis的yml配置文件
redis:
# redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突
database: 3
# redis服务器地址(默认为loaclhost)
host: 192.168.73.12
# redis端口(默认为6379)
port: 6379
# redis访问密码(默认为空)
password: pwd123
# redis连接超时时间(单位毫秒)
timeout: 0
# redis连接池配置
pool:
# 最大可用连接数(默认为8,负数表示无限)
max-active: 8
# 最大空闲连接数(默认为8,负数表示无限)
max-idle: 8
# 最小空闲连接数(默认为0,该值只有为正数才有用)
min-idle: 0
# 从连接池中获取连接最大等待时间(默认为-1,单位为毫秒,负数表示无限)
max-wait: -1
这里我们使用的最终yml为
redis: #redis其他的都使用默认配置,也可以不配,全部使用默认配置,这里为了直观的学习固修改host和port
host: 127.0.0.1 #/localhost
# redis端口(默认为6379)
port: 6379
server:
port: 9001 #端口号
spring:
application:
name: spring-boot-redis-0730 #项目名称
4.注入模板
@Resource
private StringRedisTemplate stringRedisTemplate;
// @Resource 在此工程中使用stringredistemplate
// private RedisTemplate redisTemplate;
StringredisTemplate 与 RedisTemplate 的区别
5. 操作模版
String常用的模板操作
//存入redis
@Test
void addStringRedis() {
ValueOperations<String, String> StringRedis
= stringRedisTemplate.opsForValue();
StringRedis.set("job","male");
StringRedis.set("jack","male");
StringRedis.set("lisa","female");
StringRedis.set("alili","female");
}
/**
* @description 根据key获取值
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 12:18
*/
@Test
void getStringredis(){
ValueOperations<String, String> StringRedis = stringRedisTemplate.opsForValue();
//根据key获取值
String job = StringRedis.get("job");
System.out.println("job = " + job);
}
//job = male
/**
* @description 给key设置过期时间,使用timeunit函数
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 12:23
*/
@Test
void setExpireRedis(){
stringRedisTemplate.opsForValue().set("job","male",30,TimeUnit.SECONDS);
}
List常用模板操作
/**
* @description 对list进行左右插入操作
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:43
*/
@Test
void setRedisList(){
// 在变量左边添加元素值。右边同理,只是方法名换成rightPush
// stringRedisTemplate.opsForList().rightPush()
//批量添加时,直接在后面拼接,例如
// stringRedisTemplate.opsForList().leftPush("list","a","b","c");
//也可以直接将集合放进去
// stringRedisTemplate.opsForList().leftPush("list",List对象);
stringRedisTemplate.opsForList().leftPush("list","a");
stringRedisTemplate.opsForList().leftPush("list","b");
stringRedisTemplate.opsForList().leftPush("list","c");
}
/**
* @description Ipuest
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:50
*/
@Test
void Ipuest(){
// 如果存在集合则添加元素。
stringRedisTemplate.opsForList().leftPushIfPresent("presentList","o");
List<String> list = stringRedisTemplate.opsForList().range("presentList", 0, -1);
System.out.println("通过leftPushIfPresent(K key, V value)方法向已存在的集合添加元素:" + list);
}
// size(K key)
//获取集合长度。
long listLength = redisTemplate.opsForList().size("list");
System.out.println("通过size(K key)方法获取集合list的长度为:" + listLength);
// 16、rightPop(K key)
// 移除集合中右边的元素。
// rightPop(K key, long timeout, TimeUnit unit)
// 移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出
String list = stringRedisTemplate.opsForList().rightPop("list");
System.out.print("通过rightPop(K key)方法移除的元素是:" + list);
List<String> list1 = stringRedisTemplate.opsForList().range("list", 0, -1);
System.out.println(",剩余的元素是:" + list1);
/**
* @description 获取全部的数据
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:46
*/
@Test
以上是关于什么!Redis不会用!看完这个你就是Redis大牛了!的主要内容,如果未能解决你的问题,请参考以下文章