(二)Redis API的使用和理解
二、Redis API的使用和理解
- 通用命令
- 字符串类型
- 哈希类型
- 列表类型
- 集合类型
- 有序集合类型
1.通用命令
- 通用命令:
- keys:列出redis中所有的键
- 例如:keys *
- keys [pattern] pattern是通配符或者说是正则表达式的形式
- 注意:keys一般不在生产环境中使用(意义不大,O(n))
- 一般用在热备从节点、scan中
- dbsize:算出redis数据库中键的总数
- dbsize的时间复杂度是O(1),有个专门的计数器
- exists key 判断键是否存在
- del key [key...] 删除键-值对
- expire key seconds 设置key的存活时间,key在seconds秒后过期,过期的时候内部执行del命令删除键-值对
- 此外还有:ttl key:查看key的剩余的过期时间
- persist key:去掉key的过期时间,即不进行计时删除的操作了
- type key 得到键对应的值的数据类型
- 综上,除keys命令时间复杂度是O(n)外,其余的命令都是O(1)的复杂度
- keys:列出redis中所有的键
- 数据结构和内部编码
- key
- string
- raw
- int
- embstr
- hash
- hashtable
- ziplist
- list
- linkedlist
- ziplist
- set
- hashtable
- intset
- zset(sorted-set)
- skiplist
- ziplist
- string
- key
- 单线程架构
- 单线程为什么这么快?
- 1.纯内存(内存的响应时间小于100ns)
- 2.非阻塞IO
- 3.避免线程切换和竞态消耗
- 一次只运行一条命令
- 拒绝长(慢)命令
- 比如:keys、flushall、flushdb、slow lua script、multi/exec、operate big value(Collection)
- 其实不是单线程
- 处理下面两种操作时有独立的线程
- fsync file descriptor
- close file descriptor
- 单线程为什么这么快?
2.字符串类型
结构和命令
key value
hello world(真的字符串)
counter 1(转换成整数类型)
bits 1010101010 (最高512MB)
场景
- 缓存
- 计数器
- 分布式锁
- ...
命令
- get key
- set key value
- del key
- incr key
- decr key
- incrby key k
- decrby key k
- set key value
- setnx key value 只有key不存在,才设置
- set key value xx 只有key存在,才设置,xx是命令的一部分
- mget key1 key2 key3... 批量获取key的值,原子操作,批量操作效率高,减少网络IO次数 O(n)
- mset key1 value1 key2 value2...批量设置key-value
快速实战
- 实现如下功能:记录网站每个用户个人主页的访问量?incr userid:pageview(单线程,无竞争)
- 缓存视频的基本信息(数据源在MySql中):
-
伪代码:
public VideoInfo get(long id){ String redisKey = redisPrefix + id; VideoInfo videoInfo = redis.get(redisKey); if (videoInfo == null){ videoInfo = mysql.get(id); if (videoInfo != null){ //序列化 redis.set(redisKey, serialize(videoInfo)); } } return videoInfo; }
-
查漏补缺
- getset key newvalue 设置为新的值,并返回旧的值
- append key value 将value追加到旧的value
- strlen key 返回字符串(value)的长度(使用中文的时候要注意)
- incrbyfloat key 3.5 浮点数自增
- getrange key start end 获取字符串指定下标所有的值
- setrange key index value 设置指定下标所有对应的值
3.哈希类型
特点
- Mapmap
- Small Redis
- field不能相同,value可以相同
结构例如:
| key | field | value |
|---|---|---|
| john@gmail.com | ||
| user:1:info | name | John |
| password | 123456 | |
| id | 1 |
重要API
- hget key field 获取hash key对应的field的value
- hset key field value 设置hash key对应的field的value
- hdel key field 删除hash key中的某个field
- hexists key field 判断一个field是否存在
- hlen key 获取hash key field的数量
- hmget key field1 field2...fieldN 批量获取hash key的一批field对应的值
- hmset key field1 value1 field2 value2... 批量设置hash key的一批field value
- hgetall key 返回hash key对应的所有field和value(小心使用,防止数据量过大)
- hvals key 返回hash key对应所有field的value
- hkeys key 返回hash key对应所 有field
实战
1.记录网站每个用户个人主页的访问量?
hincrby user:1:info pageview count
2.缓存视频的基本信息:
public VideoInfo get(long id){
String redisKey = redisPrefix + id;
Map<String,String> hashMap = redis.hgetAll(redisKey);
VideoInfo videoInfo = transferMapToVideo(hashMap);
if (videoInfo == null){
videoInfo = mysql.get(id);
if (videoInfo != null){
redis.hmset(redisKey,transferVideoToMap(videoInfo));
}
}
return videoInfo;
}
hash vs String




查漏补缺
- hsetnx key field value 设置hash key对应field的value(如果field已经存在,则操作失败)
- hincrby key field intCounter hash key对应field的value自增intCounter
- hincrbyfloat key field floatCounter hash key对应field的value自增浮点数floatCounter
4.列表
列表结构

特点
- 有序
- 元素可以重复
- 左右两边都可以插入和弹出
重要API
增
- rpush key value1 value2... 从列表右端依次插入值
- lpush key value1 value2... 从列表左端依次插入值
insert
- insert key before|after value newvalue 在list指定的值 前|后 插入newvalue 时间复杂度O(n)
![]()
删除
- lpop key 从列表左端弹出一个元素
- rpop key 从列表右端弹出一个元素
- lrem key count value 根据count值,从列表中删除所有value相等的项
- count>0:从左到右,删除最多count个value相等的项
- count<0:从右到左,删除最多abs(count)个value相等的项
- count=0:删除所有value相等的项
- ltrim key start end 按照索引范围修建列表(保留下标start到end之间的元素)
查
- lrange key start end(包含end) 获取列表指定范围内的的元素

- lindex key index 获取列表指定索引的元素
- llen key 获取列表长度
改
- lset key index newvalue 设置列表指定索引值为newvalue
实战
微博TimeLine
查漏补缺
- blpop key timeout lpop的阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞
- brpop key timeout
Tips
LPUSH + LPOP = STACK
LPUSH + RPOP = QUEUE
LPUSH + LTRIM = Capped Collection(固定大小列表)
LPUSH + BRPOP = Message Queue
5.Set
集合结构

特点
- 无序
- 没有重复元素
- 支持集合间操作
集合内API
- sadd key element 向集合中添加元素
- srem key element 将集合key中的element删除
- scard key 计算集合大小
- sismember key element 判断element是否在集合key中
- srandmember key count 从集合中随机挑count个元素
- spop key 从集合中随机弹出一个元素(会破会集合数据,即弹出就没了)
- smemebers key 取出集合key中所有的元素,返回结果是无序的(小心使用,数据量可能很大)
集合内实战
- 给用户添加标签:
- sadd user:1:tags tag1 tag2 tag3
- sadd user:2:tags tag2 tag3 tag5
- 给标签添加用户
- sadd tag1:users user:1 user:3
- sadd tag2:users user2: user:4
- 微博抽奖系统:将用户放在一个集合中,然后通过spop或者srandmember来抽取用户
- 微博点赞、点踩(把用户id放在某条微博的赞、踩集合中)
集合间API
- sdiff key1 key2 差集
- sinter key1 key2 交集
- sunion key1 key2 并集
集合间实战
比如求用户的共同关注
Tips
SADD = Tagging
SPOP、SRANDMEMBER = Random item
SADD + SINTER = Social Graph
有序集合
结构
![]()
集合里每个元素是有序的,根据score排序
集合和有序集合对比

重要API
- zadd key score element 注意score可以重复,element不可以重复O(logN)
- zrem key element 删除元素 O(1)
- zscore key element 返回元素的分数
- zincryby key increScore element 增加或减少元素的分数
- zcard key 返回元素的个数 O(1)
- zrank key element 获取某个元素的排名(从0开始数)
- zrange key start end [withscores] [带分数]返回指定范围的升序元素 O((logN) + m)
- zrangebyscore key minScore maxScore [withscores] [带分数]返回指定分数范围内的升序元素 时间复杂度同上
- zcount key minScore maxScore 返回个数
- zremrangebyrank key start end 删除指定排名内的升序元素
实战
排行榜:可以使用timeStamp、saleCount或者followCount作为score
查缺补漏
- zrevrank 降序
- zrevrange 降序
- zrevrangebyscore 降序
- zinterstore
- zunionstore




浙公网安备 33010602011771号