redis知识点总结
Posted z啵唧啵唧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis知识点总结相关的知识,希望对你有一定的参考价值。
文章目录
redis学习
redis简介
redis:远程词典服务,用c语言开发的开源键值对数据库。
特征:
- 数据之间没有特定的联系
- 内部采用单线程机制进行工作
- 高性能。
- 多数据类型支持:string、list、hash、set、sorted_set
- 也可以支持简单的持久化支持,对数据进行灾难性的恢复
windows学习
版本:3.2.100
下载解压即安装成功
redis端口号:6379
pid:每启动一次都会随机生成
redis的基本操作
命令行模式工具思考
-
信息存放指令
set key value
-
信息获取指令
get key
-
清除屏幕指令
clear
-
帮助命令
help:例如想要查询get的用法 help get
-
help @group 查询一个群组的功能信息
-
退出命令
quit、exit、ese键这三个都可以退出
-
删除指令
del key:返回(integer)1 表示删除成功(integer)10表示删除失败)
-
mset key1 value key2 value …同时添加多个数据
-
mget key1 key2 …同时查询多个数据
-
strlen key 获取字符串长度
-
append key value 在value后面追加数据:当key不存在的时候会新建一个key然后存放数据
-
incr key 对key的value值自增1
-
incrby key increment 对key对应的value值加上increment值
-
incrbyfloat key increment (增加浮点数值)
-
decr key 对key的value值减1
-
decrby key increment 对key对应的值减increment值
-
设置数据具有指定的生命周期
setex key seconds value 这个指令表示设置的value值只在一定的时间范围内部才有效
psetex key millisecondsvalue value和上一个指定功能一样只不过时间是毫秒级别
hash类型数据的基本操作
-
添加修改数据
hset key field value
-
获取数据
hget key field
hgetall key
-
删除数据
hdel key field1[field2]
-
添加多个数据
hmset key field1 value1 field2 value2 …
-
查询多个数据
hmget key field1 field2
-
获取哈希表中字段的数量
hlen key (注意这条指令拿到的是field的数量)
-
查询哈希表当中是否含有某个字段
hexists key field(查询key中是否存在field字段)
-
获取哈希表当中的字段或者字段值
hkeys key:获取哈希表当中的字段名
hvals key:获取哈希表当中的字段值
-
设置指定字段的数值数据增加指定的范围
hincrby key field increment
hincrbyfloat key field increment(增加带浮点数的数值)
hash实现购物车
-
分析一个购物车
-
g01:nums代表g01商品的数量,g01:info代表g01商品的图片信息的地址等信息
-
现在有两个用户001和002他们共同购买了g01这个商品,对于他们两个人而言,就是g01商品的数量不同,其他信息都是相同的
-
这样就可以将这种公共的信息单独放在一个哈希表当中
-
hsetnx key field value 表示在添加之前是否存在,如果存在就不添加,如果不存在就添加
list类型数据基本操作
-
lpush key value1 value2 … 从左往进添加元素
-
rpush key value1 value2 …从右往进添加元素
-
lrange key start stop从左边依次读取元素(start起始位置的索引,从0开始,stop结束位置的索引,-1代表倒数第一个元素)
-
llen key 查询list的元素个数
-
lpop key 从左边移除元素
-
rpop key 从右边移除元素
list数据扩展操作
-
blpop key1 key2… timeout(阻塞版本的pop)
-
brpop key1 key2… timeout
-
上面两条指令是在基础的pop指令上面扩展的功能,表示的意思是从指定的list种移除元素,也是要么从左边移除要么从右边移除当list种没有元素的时候就在规定的timeout时间等待,那么只要是在规定的时间以内,当外界添加一个元素就执行依次移除一个元素,所以这条指令会在哪里一直等待的执行功能。
-
list的应用场景:朋友圈点赞:要求按照点赞的顺序现实好友信息,如果取消了点赞就移除相应的好友信息,因为取消点赞的好友可能是中间顺序的好友,但是lpop和rpop都是从两端进行移除元素,所以需要用到从中间移除元素的指令
-
从中间移除元素:lrem key count value (key指定相应的操作链表,value表示要移除的指定元素值,count表示要移除的个数,因为在list当中是允许元素进行重复的)
set的类型数据的基本操作
-
添加数据
sadd key member1 member2…
-
获取全部元素
smembers key
-
删除数据
srem key member1 member2…
-
获取集合set集合的数据总量
scard key
-
panduanset集合当中是否包含指定元素
sismembers key member
set类型数据的扩展操作
-
随机获取集合中指定数量的数据
srandmember key count 它只是随机展示出来指定数量的数据,并不会将集合中的元素删除
-
随机获取集合当中指定数量的元素并将它们移除集合
spop key count 这条指令相比较于上一条指令来说,在上一条指令的基础上将展示出来的元素移除了集合。
-
所以根据上面这种特性redis可以适用于随机推荐的信息检索,比如歌单推荐,热点新闻推荐
-
求两个集合的交、并、差
交:sinter key1 key2
并:sunion key1 key2
差:sdiff key1 key2 (注意差是有方向性的)
-
就两个集合的交、并、差并将他们的集合转存到新的集合当中
交:sinterstore distination key1 key2
并:sunionstore distination key1 key2
差:sdiffstore distination key1 key2 (注意差是有方向性的)
-
将指定元素从指定集合当中移动到目标集合当中
smove source(指定集合) distination(目标集合) member
sorted_set类型的基本操作
-
添加数据
zadd key score1 member1 score2 membre2…(其中score不是数据,他只是用来排序的字段,意思就是排序的标准是score,member是真正的数据)
-
获取全部数据
zrange key start stop WITHSCORES:获取的数据是从小到大排序的
zrevrange key start stop WITHSCORES:获取的数据是从大到小排列的
-
模拟成绩排行
- 删除数据
zrem key member1 memnre2…
-
按照条件获取数据
zrangebyscore key min max withscores limit(这个表示吧score值按照添加查询,这条命令的具体值是查询score值在min 到 max 之间的数据,limit和mysql中的limit一样表示分页)
zrevrangebyscore key max min withscores (这条是反向查的意思)
-
按照条件删除数据
zremrangebyrank key start stop
zremrangebyscore key min max
-
获取集合数据量
zcard key 获取key集合当中的数据总量
zcount key min max 获取score值在min到max范围当中的数据量数目 -
获取数据对应的索引
zrank key member 获取member这个数据的索引值
zrevrank key member 这个获取出来的索引值和上面那种方法顺序相反
-
score值的获取和修改
zscore key member 获取member这个数据的score值
zincrby key increment member 对member这个数据的值进行修改
数据类型综合案列分析
- 按次计费的计数器
- 微信的消息按照时间排列
key的通用操作
key的基本操作
-
删除指定的key
del key
-
判断key是否存在
exists key
-
获取key的数据类型
type key
key的扩展操作
-
为指定的key的设置有效期
expire key seconds 为key设置指定的有效期时间(秒级)
pexpire key milliseconds 功能和上一条指令一样只不过他的时间级别是毫秒级
-
获取key的有效时间
ttl key 就是说当一个key设置了生命周期,通过这个指令就可以获取到这个key还剩余的有效时间,注意这个获取的是剩余的有效时间不是设置的时候的时间
这条指令有三个返回值:
当返回-2的时候表示这个key已经失效,不存在了
当返回-1的时候表示这个key存在但是并没有设置时间周期
当返回一个正数的值的时候表示返回的就是这个key的剩余的有效时间
-
切换key的有效时间成为永久性的
persist key 就可以将有时间限制的key切换成永久性的key
key的查询操作
key的其他操作
-
为key改名
rename key newkey 将key的名字改成newkey,这种改名的方式需要慎重,因为原先可能已经存在newkey这个名字,这样的话回将原先key中的值覆盖成为newkey中的值
renamenx key newkey 这种改名方式是如果新的名字不存在的话既可以将改名成功,如果原先已经存在新的名字的话就不能够更改,这种改名方式会更加安全,有效避免了数据的丢失
数据库通用的操作
首先我们要知道的是在redis中呢有16个数据库编号分别是从0到15,我们可以通过一些操作来使用不同的数据库以及对数据库进行一些操作,我们默认使用的数据库是0好数据库
-
切换数据库
select index 通过这个指令可以进行数据库的切换使用,index代表我们要使用的数据库的编号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 -
其他操作
qiut 退出操作
ping 用来测试和服务器是否还联通
-
数据移动
mov key db 表示将当前数据库中的key移动到指定的数据库当中,这是一个剪切的过程,当这个key移动过去之后自己这个库当中就没有这个数据了
-
数据清除
flushdb 将当前数据库中的数据全部清除
-
flushall将redis中所有的数据清除
Jedis简介
jedis的作用是用java语言连接redis服务
之前介绍的redis的所有命令在jedis中完全适用
使用jedis的三个步骤
-
创建连接
-
进行具体操作
-
关闭连接
-
package com.zb.jedis; import org.junit.Test; import redis.clients.jedis.Jedis; public class jedisTest @Test public void test01() //创建连接 Jedis jedis = new Jedis("127.0.0.1", 6379);//redis的ip和他的端口号 //操作 jedis.set("name","123456"); System.out.println(jedis.get("name")); //关闭 jedis.close();
-
jedis的一些常规操作
-
对list的操作
@Test public void test01() //创建连接 Jedis jedis = new Jedis("127.0.0.1", 6379); //操作 /* jedis.set("name","123456"); System.out.println(jedis.get("name"));*/ jedis.lpush("list4","a","b","c");//从左边往进依次放a,b,c jedis.rpush("list4","x");//从右边往进放一个x List<String> list1 = jedis.lrange("list4", 0, -1);//调用lrange方法读取一下 // 存入的数据,他返回的是一个list集合 for(String s:list1) System.out.println(s); //获取list的长度 System.out.println(jedis.llen("list1")); //关闭 jedis.close();
-
对Hash的操作
@Test
public void test02()
//创建连接
Jedis jedis = new Jedis("127.0.0.1", 6379);
//操作
jedis.hset("hash3","a1","1");
jedis.hset("hash3","a2","2");
jedis.hset("hash3","a3","3");
Map<String, String> hash3 = jedis.hgetAll("hash3");//返回hash当中的数据
System.out.println(hash3);
System.out.println(jedis.hlen("hash3"));//获取hash的长度
- 在jedis中取出来的数据都会作为java中的类型进行展示
案例:服务调用次数控制
package com.zb;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;
public class Service
public String id;
public int num;
public Service(String id, int num)
this.id = id;
this.num = num;
//设计redis的控制方案
public void service()
Jedis jedis = new Jedis("127.0.0.1",6379);
String value = jedis.get("compid:"+id);
//判断该值是否存在
try
if (value==null)
//不存在,创建该值
jedis.setex("compid:"+id, 5, Long.MAX_VALUE + "");
else
//存在,自增,调用业务
Long val = jedis.incr("compid:"+id);
business(id,num-(Long.MAX_VALUE-val));
catch (JedisDataException e)
System.out.println("使用次数已达上限,请升级会员级别");
return;
finally
jedis.close();
//设定业务方法
public void business(String id,Long val)
System.out.println("用户"+id+"业务逻辑执行第"+val+"次");
//设定多线程类,模拟用户调用,业务方法
class MyThread extends Thread
Service sc;
public MyThread(String id ,int num)
sc = new Service(id,num);
public void run()
while (true)
sc.service();
try
Thread.sleep(1000L);
catch (InterruptedException e)
e.printStackTrace();
class Main
public static void main(String[] args)
MyThread mt1 = new MyThread("初级用户",10);
MyThread mt2 = new MyThread("高级用户",30);
mt1.start();
mt2.start();
jedis工具开发
-
redis.properties配置文件封装连接参数
# jedis.host host=127.0.0.1 #redis的端口号 port=6379 #最大连接数 maxTotal=30 #最大活动数 maxIdle=10
-
工具类
package com.zb.util; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.ResourceBundle; public class JedisUtils private static JedisPool jp = null; private static String host = null; private static int port; private static int maxTotal; private static int maxIdle; //静态代码块初始化资源 static //读取配置文件获取配置参数 ResourceBundle rb = ResourceBundle.getBundle("redis"); host = rb.getString("host"); port = Integer.parseInt(rb.getString("port")); maxTotal = Integer.parseInt(rb.getString("maxTotal")); maxIdle = Integer.parseInt(rb.getString("maxIdle")); //获取一个jedis连接池配置 JedisPoolConfig jpc = new JedisPoolConfig(); jpc.setMaxTotal(maxTotal);//设置连接池的最大连接数 jpc.setMaxIdle(maxIdle);//设置连接池的最大活动数 //初始化连接池,将连接池配置和主机ip和端口号放进去 jp = new JedisPool(jpc,host,port); public static Jedis getJedis() return jp.getResource();
基于linux系统安装redis
安装教程
出现错误以及解决方案
启动方法
- 进入redis安装目录下的scr目录下 启动服务命令 redis-server
- 启动完毕之后克隆一个会话 用来启动客户端,启动客户端的指令:redis-cli
多用户启动
-
需要指定配置文件启动
-
将配置文件放在conf目录下
-
配置为文件内容
-
redis-server conf/redis-6379.conf 通过多个配置文件即可打开多个服务
客户端连接方式
- 默认连接方式 redis-cli
- redis-cli -p 6379 指定端口号进行连接
- redis-cli -h 127.0.0.1 指定ip地址连接
- redis-cli -h 127.0.0.1 -p 6379 指定ip地址和端口号连接
redis的持久化
- 持久化的概念:利用永久存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化
- 持久化的目的是防止数据意外丢失
redis持久化的两种方式
数据(快照)RDB
- RDB启动方式——save命令
- 作用是手动执行依次保存操作
- save指令会造成服务器的阻塞,线上环境不建议使用save指令
- bgsave命令是针对save阻塞问题做的优化,redis内部所有涉及rdb操作的都采用bgsave来解决,基本放弃save操作
自动执行的方式(重点)
-
配置
save second changes
-
作用:满足限定时间范围内key的变化数量达到指定的数量即进行持久化
-
参数
second 监控的时间范围
changes 监控的key的变化量
-
位置:在conf文件中进行配置
-
自动执行的后台用的是bgsave机制,注意是一定是对应次数的key发生变化
过程(日志)AOF
- RDB存储的弊端:存储的数据量大,效率低下,基于快照思想,每次读写都是全部数据,当数据量过大的时候,效率非常低下
- AOF主要是解决了数据持久化的实时性,他是改记录数据为记录数据的产生过程
AOF写数据的过程
- always(每次):每次写入操作均同步到AOF文件中,数据零失误,但是性能较低,不建议使用
- everysec(每秒):每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能也比较高,默认使用,也建议使用
- no(系统控制):由操作系统控制每次同步到到AOF文件的周期,整体过程是不可以控制的
- 配置 appendonly yes|no 作用:是否开启AOF持久化功能,默认为不开启的状态
- appendfsync always|everysec|no 配置AOF的读写策略,默认是everysec
AOF重写
- 降低磁盘的占用率,提高磁盘的利用率
- 提高持久化的效率,降低持久化写时间,提高IO性能
- 降低数据恢复复用时,提高数据恢复率
AOF的重写方式
- 手动重写:bgrewriteaof
- aof工作原理:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
AOF工作的流程
AOF VS RDB
事务
事务简介
- redis事务就是一个命令执行的队列,将一系列预定义的命令包装成一个整体(一个队列)。当执行的时候,一次性按照添加顺序依次执行,中间不会被打断或者干扰
- 一个队列中,一次性、顺序性、排他性的执行一次命令
事务的基本操作
-
事务的开启:multi
作用:设定事务的开启位置,此指令执行后,后续所有的指令均加入到事务中
-
执行事务:exec
作用:设定事务的结束位置,同时执行事务,与multi成对出现,成对使用。
-
注意:加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令之后才开始执行
-
执行流程:
-
取消事务操作:discard
作用:终止当前事务,发生在multi之后,exec之前
-
事务的工作流程
事务的注意事项
- 定义事务的过程中,命令格式出现错误怎么办?
- 1、语法错误:命令书写的格式出现问题
- 处理结果:如果定义的事务中所包含的命令存在语法错误,整体事务所有命令均不会执行,包括那些语法正确的命令
- 2、运行出错:指令格式正确但是无法正确执行,例如对list进行incr操作
- 处理结果:能够运行正确的命令,错误的指令不会执行
- 注意:像第二种这种语法错误,已经执行完毕的命令是不会回滚的,需要程序员自己在代码中实现回滚。
手动进行事务回滚
- 先记录操作过程中被影响的数据之前的状态
- 但数据 string
- 多数据 hash、list、set、zset
- 设置指令恢复所有的被修改的项
- 单数据:直接set
- 多数据:修改对应值,或者整体克隆回去
基于特定条件的事务执行——锁
-
对key添加锁监视,在执行exec前如果发生了变化,终止事务执行
watch key1 key2…
-
取消对所有key的监视
unwatch
分布式锁
- 使用setnx设置一个公共的锁
- setnx lock-key value
- 利用setnx命令的返回值特性,有值则返回失败,无值则返回成功
- 对于返回成功的,拥有控制权,进行下一步具体的业务操作
- 对于返回失败的,不具有控制权,排队或者等候操作完毕之后通过del操作来释放锁
- 注意上述解决方案是一种设计的概念,依赖规范保障,具有风险性
- 所以redis可以应用于基于分布式锁的对应场景
分布式锁的改良
- 防止锁的拥有者拿到锁之后一直不解锁,导致等待拿锁的线程一直等待,这样就造成了死锁的状态
- 解决方案
- 使用expire为锁添加时间限定,到时候不释放,就放弃锁
- expire lock-key second
- pexpire lock-key milliseconds
- 注意:由于通常都是微妙,毫秒级,因此锁的时间不宜设置过大,具体时间需要业务测试后确认
redis的删除策略
过期数据
- redis中的数据特征
- redis是一种内存级数据库,所有的数据均存放在内存当中,内存中的数据可以通过ttl指令获取其状态
- xx:具有时效的数据
- -1:永久有效的数据
- -2:已经过期的数据或者被删除的数据或未定义的数据
删除策略
-
1、定时删除
- 创建一个定时器,当key设置的有过期时间,且当过期时间到达时,由定时任务立即执行对键的删除
- 优点:节约内存,到设定的时间就删除,快速时掉不必要的内存占用
- 缺点:这种方式给cpu造成的压力比较大,因为它到点就要删除,没有考虑cpu的工作状态,会影响redis服务器的响应时间和指令吞吐量
- 总结:用处理器的性能来换取存储空间。(拿时间换空间)
-
2、惰性删除
- 数据到达过期时间,不做处理。等下一次访问的时候,如果未过期返回数据,如果发现已经过期就删除,返回不存在
- 优点:节约cpu的性能,发现必须删除的时候才删除
- 缺点:内存的压力很大,出现长期占用内存的数据
- 总结:这是用存储空间来换取cpu的性能,空间换时间的做法 <
以上是关于redis知识点总结的主要内容,如果未能解决你的问题,请参考以下文章