2.1 预备
2.1.1 全局命令
keys *
:查询所有的key
,遍历所有的key
,时间复杂度为O(n)
。当数据量很大时,会非常慢,线上不建议使用;dbsize
:返回所拥有的key
的数量。redis内部有一个记录当前key
数量的值,因此时间复杂度为O(1)
;exists
:检查key
是否存在;del
:删除指定的key
,可批量操作;expire
:设置过期时间;ttl
:返回key
的剩余存货时间,或者-1(key
没有设置过期时间),-2(key
不存在)type
:返回key
的类型
redis一共有五种数据结构:
String, Hash, Set, Sorted Set, List
可以使用
object encoding
命令,来分别查看key
的内部编码文章图片
2.1.3 单线程架构
- 由于redis是单线程架构,因此不会存在并发问题/
- 为什么单线程还那么快?
- 单线程避免了线程切换产生的开销;
- redis是异步非阻塞IO;
- redis是纯内存操作,这个比磁盘操作要快很多。
- 某个命令过长的情况:由于redis是单线程,当某个命令过长的时候,会让其它命令等待时间很长,这种情况应该避免。
1. 常用命令
- 设置值
set key value [ex seconds] [px milliseconds] [nx|xx]
setxx
setnx
:应用场景:分布式锁
- 获取值
get key
- 批量设置,获取值
mset key value [key value ...]
mget key [key ...]
- 使用批量操作和非批量操作的时间消耗:
- 非批量操作:n次get时间 = n次网络时间 + n次命令时间
文章图片
- 批量操作:n次get时间 = 1次网络时间 + n次命令时间
文章图片
- 计数
incr key
decr key
incrby
decrby
int, embstr, raw
2.2.3 典型应用场景
- 缓存:获取用户信息时,我们可以将用户信息存放在redis中,这样子就避免了下一次读取用户信息时,还得从磁盘读取。伪代码如下:
public UserInfo getUser(long userId) { String userKey = "user_info_" + userId; UserInfo userInfo = redis.get(userKey); if(userInfo == null) { userInfo = db.get(userKey); //设置一个小时的过期时间 redis.setex(userKey, 3600, serialize(userInfo)); } return deserialize(userInfo); }
- 计数
public long incrCount(long userId) { String key = "user_counter_" + userId; redis.incr(key); }
- 限速:这个我们的生活中常常能碰到,例如,短信验证码一分钟内最多只能发送五次。
phoneNum = "138xxxxxxxx"; key = "shortMsg:limit:" + phoneNum; // SET key value EX 60 NX isExists = redis.set(key,1,"EX 60","NX"); if(isExists != null || redis.incr(key) <=5) { // 通过 }else { // 限速 }
2.3.1 命令
- 设置值:
hset key field value
- 获取值:
hget key field
- 删除field:
hdel key field [field ... ]
- 计算field个数:
hlen key
- 批量设置,获取field:
hmget key field [field ...]
mset key field value [field value ...]
- 判断key是否存在:
hexists key field
- 获取所有的field:
hkeys key
- 获取所有的value:
hvals key
- 获取所有的key-value:
hgetall key
- ziplist
- hashtable
文章图片
使用redis添加用户信息的伪代码:
public UserInfo getUserInfo(long userId) {
String userKey = "user:info:" + userId;
userInfoMap = redis.hgetAll (userKey);
//取出用户的所有信息
if(userInfomAP != null) {
UserInfo userInfo = transferMapToInfo(userInfoMap);
//将map转换为UserInfo
} else {
userInfo = db.get(id);
redis.hset(userKey, transferInfoToMap(userInfo));
redis.expire(userKey, 3600);
}
}
2.4 列表
2.4.1 命令
- 添加命令:
- 从右边添加元素:
rpush key value [value ...]
- 从左边添加元素:
lpush key value [value ...]
- 从指定位置添加元素:
linsert key before|after pivot value
- 查找:
- 获取指定范围内的元素:
lrange key start end
- 获取指定下标的元素:
lindex key index
;index = -1代表最后一个 - 获取列表长度:
llen key
- 从左侧弹出:
lpop
- 从右侧弹出:
rpop
- 删除指定元素:
lrem key count value
,删除指定元素value,最多删除count个。count > 0,从左开始; count < 0,从右开始, count = 0,删除所有。 - 按照范围裁剪列表:
ltrim key start end
- 修改指定下标元素:
lset key index newValue
- ziplist
- linkedlist
- quicklist
2.5 集合
2.5.1 命令
- 集合内操作
- 添加元素:
sadd key element [element ...]
- 删除元素:
srem key element [element...]
- 查询大小:
scard key
- 随机返回指定个数:
srandmember key [count]
- 从集合随机弹出元素:
spop key
- 获取所有元素:
smembers key
- 集合间的操作
- 求交集:
sinter key [key...]
- 求并集:
sunion key [key..]
- 求差集:
sdiff key [key...]
- 上面三个命令后缀加
store
,可以将得到的结果存储起来,例如:sinterstore user1_2inter user:1:follow user:2:follow
- intset:元素较少且均为整数
- hashtable
2.6 有序集合
2.6.1 命令
- 集合内
- 添加成员:
zadd key score memeber [score member...]
- 计算成员个数:
zcard key
- 计算某个成员的分数:
zcore key member
- 计算某个成员排名:
低到高:zrank key member
高到低:zrevrank key member
- 删除成员:
zrem key member
- 给指定成员增加分数:
zincrby key increment member
- ziplist
- skiplist
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 数据库|SQL行转列方式优化查询性能实践
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- mysql|一文深入理解mysql
- 达梦数据库|DM8表空间备份恢复