Redis学习 知识总结 一
- 1 Redis初识
- 1.1 Redis八大特性
- 1.2 redis使用场景
- 1.3 Docker安装redis
- 2 API的理解和使用
- 2.1 通用命令
- 2.2 字符串(String)类型
- 2.3 哈希(Hash)类型
- 2.4 有序列表(list)
- 2.5 集合(Set)
- 2.6 有序集合(Sort Set)
- 3 Redis客户端的使用
- 3.1 Jedis客户端
- 4 Redis其他功能
1 Redis初识
1.1 Redis八大特性
Redis的键的类型是String的。
特性详解:
- 速度快:① 数据存储在内存中 ② 使用C语言编写(与系统融合性好)③ 单线程,避免资源争夺(
Redis6.0之前是单线程的,Redis6.0之后开始支持多线程)。 - 持久化:
redis可以将内存中的数据异步保存到磁盘中,防止在断电等情况下的数据丢失。 - 支持多种数据类型:
String、Hash、linked List、Set、Sorted Set - 支持多种编程语言:
Java、Go、python、php、Lua、Node.js、Ruby - 功能丰富:发布订阅、
Lua脚本、事务、pipeline等 - 简单:源码的代码量少,可以修改。
- 支持主从复制:可为高可用、分布式提供便利。
- 高可用、分布式
1.2 redis使用场景
- 缓存系统
- 计数器
- 消息队列系统
- 排行榜
- 社交网络
- 实时系统
1.3 Docker安装redis
略
2 API的理解和使用
2.1 通用命令
keys:查看所有的键 (keys *:遍历所有的key) 注意:keys一般不在生产环境中使用,因为比较花销时间,会产生阻塞情况。dbsize:计算key的总数。exists key:判断指定键是否存在。del key [key1 key2 ...]:删除指定键的数据。expire key seconds:给指定键设置过期时间(过期后自动删除)。ttl key:查看key的剩余过期时间。persist key:去掉key的过期时间。type key:判断指定键的value类型,返回结果String、hash、list、set、zset、none。- 时间复杂度:
keys:O(n)、dbsize:O(1)、del:O(1)、exists:O(1)、expire:O(1)、type:O(1)。 - 数据结构和内部编码:
string:raw、int、embstr;hash:hashtable、ziplist;list:linkedlist、ziplist;set:hashtable、intset;zet:skiplist、ziplist;
- 单线程:单线程为什么这么快?
- 纯内存。
- 非阻塞IO。
- 避免线程切换和竞态消耗。
- 单线程:
- 一次只运行一条命令。
- 拒绝长(慢)命令:
keys,flushall,flushdb,slow lua script,multi/exec,operate,big value(collection) - 其实不是真正的单线程:
fysnc file descriptor,close file descriptor
2.2 字符串(String)类型
使用场景:缓存、计数器、分布式锁 等等。
常用命令:
set:设置key-value时间复杂度O(1)。get:获取key对应的value时间复杂度O(1)。del:删除key-value。incr key:key的值自增1,如果key不存在,自增后get(key)= 1。desc key:key的值自减1,如果key不存在,自增后get(key)= -1。incrby key k:key的值自增k,如果key不存在,自增后get(key)= k。desc key k:key的值自减k,如果key不存在,自增后get(key)= -k。set key:不管key是否存在,都设置 时间复杂度O(1)。
setnx key:key不存在,才设置,相当于添加操作,时间复杂度O(1)。
setxx key:key存在,才设置, 相当于更新操作,时间复杂度O(1)。mset:批量设置key-value,时间复杂度O(n)。例:mset key1 value1 key2 value2 key3 value3mget:批量获取key,原子操作,时间复杂度O(n)。例:mget key1 key2 key3...getset key newvalue:set key newvalue并返回旧的value,时间复杂度O(1)。append key value:将value追加到旧的value后面,时间复杂度O(1)。strlen key: 返回字符串的长度(注意中文的情况),时间复杂度O(1)。incrbyfloat key:以浮点数增加。getrange key start end:获取指定起始索引的值。setrange key index value:设置指定索引处的值。
2.3 哈希(Hash)类型
哈希命令是以字母h为前缀,哈希键值结构,由key(String类型) field(属性) value(值)三部分组成,一个key可以对应多个field-value,可以把它看成一个对象。
特点:
Map-Map即类似于map嵌套了一个map。Small redis:相当于一个微小型的redis。
常用命令:
hset:(hset key field value)设置hash的key对应的field-value,时间复杂度O(1)。hget:(hget key field) 获取hash key对应的field的value,时间复杂度O(1)。hdel:(hdel key field)删除hash key对应的field的value, 时间复杂度O(1)。hexists:(hexists key field)判断hash key是否有field, 时间复杂度O(1)。hlen:(hlen key)获取hash key field的数量 , 时间复杂度O(1)。hmset:(hmset key field1 value1 field2 value2 ...)批量设置hash key的field value,时间复杂度O(n)。hmget:(hmget key field1 field2 field3 ...)批量获取hash key的field对应的值,时间复杂度O(n)。hgetall: (hgetall key) 返回hash key对应的所有的field和value,时间复杂度O(n),注意小心使用hgetall,牢记redis是单线程的,使用hgetall可能会造成阻塞现象。hvals:(hvals key)返回hash key对应所有field的value,时间复杂度O(n)。hkeys:(hkeys key)返回hash key对应所有的field,时间复杂度O(n)。
2.4 有序列表(list)
列表是有序可以重复的,列表的左右两边插入弹出。
常用命令: 注意列表的命令是以 l- 为前缀。
rpush(rpush key value1 value2 ... valueN):从列表的右端插入(1 ~ N)个值,时间复杂度O(1~n)。
注意:push时是从离键最近的值开始。lpush(lpush key value1 value2 ... valueN):从列表左端插入(1 ~ N)个值,时间复杂度O(1~n)。
注意:push时是从离键最近的值开始。linsert(linsert key before/after value newValue):在list的指定值的前或后插入新值 时间复杂度O(n)。lpop(lpop key):从列表左侧弹出一个元素,时间复杂度O(1)。rpop(rpop key):从列表右侧弹出一个元素,时间复杂度O(1)。lrem(lrem key count value):根据count值,从列表中删除所有与value相等的元素,时间复杂度O(n)。
- count > 0,从左到右开始删除最多
count个与value相等的元素。 - count <0,从右到左开始删除最多(
count绝对值)个与value相等的元素。 - count = 0,删除所有与
value相等的元素。
ltrim(ltrim key start end):按照索引范围截取列表(将会只保留从指定索引开始到指定索引结束的子列表0,时间复杂度O(n)。lrange(lrange key start end(包括end)):获取列表指定索引范围内的所有元素,时间复杂度O(n)。lindex(lindex key index):获取列表中指定索引的元素,时间复杂度O(n)。
注意:当索引为-1时表示是列表中最后一个元素。llen(llen key):获取列表长度(size),时间复杂度O(1)。lset(lset key index newValue):修改列表指定索引处的元素为newValue,时间复杂度O(n)。blpop(blpop key timeout):从列表左端移出并获取列表第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。(lpop阻塞版本,timeout是阻塞超时时间,timeout = 0表示永不阻塞),时间复杂度O(1)。brpop(brpop key timeout):从列表右端移出并获取列表第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。(lpop阻塞版本,timeout是阻塞超时时间,timeout = 0表示永不阻塞),时间复杂度O(1)。
总结:
- lpush + lpop = Stack(实现栈)
- lpush + rpop = Queue(实现队列)
- lpush + ltrim = Capped Collection(实现固定集合)
- lpush + brpop = Message Queue(实现消息队列)
2.5 集合(Set)
集合的特点是元素是无序、不重复,支持集合间的操作(即两个集合取交集、并集、差集)。
常用命令:
注意集合的命令是以s-为前缀;
sadd(sadd key value):向集合key中添加value,如果value已经存在,则添加失败,时间复杂度O(1)。srem(srem key value):将集合key中的value元素删除(删除元素的前提是知道集合中有此元素),时间复杂度O(1)。scard(scard key):计算集合中有多少个元素。sismember(sismember key value):判断集合中是否存在值为value的元素。srandmember(srandmember key count):从集合中随机挑count个元素(集合中还有这些元素)。spop(spop key):从集合中随机弹出一个元素(弹出后集合中就没有此元素了)。smembers(smember key):获取集合中所有的元素。
注意:如果集合中的元素很多,因为redis是单线程的,可能会发生阻塞现象,因此该命令应小心使用。sdiff(sdiff key1 key2):返回两个集合的差集(返回的是key1中不在key2中的元素)。sinter(sinter key1 key2):返回两个集合的交集(两个集合中共有的元素)。sunion(sunion key1 key2):返回两个集合的并集。sdiff|sinter|sunion +store destkey..:将差集、交集、并集结果保存在destkey中。
实际应用:
在社交应用中使用集合的交集就能找到共同关注的人。
2.6 有序集合(Sort Set)
有序集合不同于普通集合的是它有一个score用来保持集合的有序性,有序集合的score可以重复,但是集合中的元素仍保持不重复。
常用命令:
有序集合的命令是以z-为前缀的。
zadd(zadd key score value,可以是多对score-value):向集合key中添加score-value,时间复杂度O(logN)。zrem(zrem key value,可以是多个value):删除集合中的元素,可以一次删除多个,时间复杂度O(1)zscore(zscore key value):返回元素的score,时间复杂度O(1)。zincrby(zincrby key score value):增加或减少元素的score值,时间复杂度O(1)。zcard(zcard key):返回元素的总个数,时间复杂度O(1)。zrange(zrange key start end [withscores]):返回指定索引范围内的升序元素(附带显示score), 时间复杂度O(log(n)+m)。zrangebyscore(zrangebyscore key minScore maxScore[withscores]):返回指定score范围内的升序元素(附带显示score),时间复杂度O(log(n)+m)。zcount(zcount key minScore maxScore):返回有序集合内在指定score范围内的元素个数 ,时间复杂度O(log(n)+m)。zremrangebyrank(zremrangebyrank key start end):删除指定排名内的升序元素,时间复杂度O(log(n)+m)。zremrangebyscore(zremrangebyscore key minScore maxScore):删除指定分数范围内的升序元素 ,时间复杂度O(log(n)+m)。zrank(zrank key value):从小到大排列,返回索引。zrevank(zrevank key value):从大到小排列。与上面相反。zrevrange():与zrange相反。zrevrangebyscore():与zrangebyscore相反。zinterstore():计算给定的一个或多个有序集的交集,其中给定key的数量必须以numkeys参数指定,并将该交集(结果集)储存到destination。zunionstore():计算给定的一个或多个有序集的并集,其中给定key的数量必须以numkeys参数指定,并将该并集(结果集)储存到destination。
3 Redis客户端的使用
3.1 Jedis客户端
Jedis是Redis面向Java语言的客户端,通过使用jedis可以来操作Redis数据库。
- Jedis直连:
- 在
pom.xml中加入Jedis的依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.0.1</version>
</dependency>
- 生成一个
Jedis对象,使用这个对象来和指定的Redis数据库进行通信:
Jedis jedis = new Jedis("192.168.1.105",6379);
- 使用
jedis执行操作,例:
jedis.set("hh","world");
- 使用
jedis执行get操作,例:
System.out.println("显示存入的数据:"+jedis.get("hh"));
- 参数介绍:
Jedis jedis = new Jedis(String host,int port,int connectionTimeout,int soTimeout);
host:Redis所在服务器的Ip;
port:Redis的端口;
connectionTimeout:客户端连接超时;
soTimeout:客户端读写超时;
Jedis连接池的简单使用:
- 初始化
Jedis连接池,通常情况下JedisPool是单例的:
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
JedisPool jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379);
Jedis jedis1 = null;
try{//1、从连接池中获取jedis对象jedis1 = jedisPool.getResource();//2、执行操作jedis1.set("hello","world");
}catch (Exception e){e.printStackTrace();
}finally {if(jedis1 != null){jedis1.close();//close()表示归还连接给连接池}
}
4 Redis其他功能
- 配置方法:
- 默认值
config get slowlog-max-len = 128
cofig get slowlog-log-slower-than = 10000
- 修改配置文件重启
- 动态配置:
config get slowlog-max-len 1000
cofig get slowlog-log-slower-than 1000
三个命令:
slowlog get[n]:获取慢查询队列。slowlog len:获取慢查询队列长度。slowlog reset:清空慢查询队列。
运维经验:
slowlog-max-len不要设置过大,默认10ms,通常设置1ms。slowlog-log-slower-than不要设置过小,通常设置1000左右。- 理解命令的生命周期。
- 定期持久化慢查询:是为了日后能查询以前的慢查询日志。