string
普通缓存
- 整个JSON字符串存储,代码里面unmarshall解析
127.0.0.1:6379> set mazi '{"age":12,"addr":"anhui"}' ex 10
OK
127.0.0.1:6379> get mazi
"{\"age\":12,\"addr\":\"anhui\"}"
- key隔离,val是对应的值 比如某个用户id对应的等级
| key | val |
|---|---|
| level:$uid | 1 |
127.0.0.1:6379> mset zhangsan 18 lisi 19
OK
127.0.0.1:6379> mget zhangsan lisi
1) "18"
2) "19"
计数器
因为Redis是单线程操作,所以执行命令是原子性的,适合计数场景,比如计算访问次数、点赞、转发、库存数量等等
127.0.0.1:6379> mset zhangsan 18 lisi 19
OK
127.0.0.1:6379> mget zhangsan lisi
1) "18"
2) "19"
127.0.0.1:6379>
127.0.0.1:6379> incr zhangsan
(integer) 19
127.0.0.1:6379> incr wanger //不存在的不报错 自动创建 从0开始
(integer) 1
127.0.0.1:6379> incrby lisi 10
(integer) 29
分布式锁
setnx命令可以做分布式锁使用
加锁
func (d *Idempotent) getNxLock(ctx context.Context, key string, value int) (res bool, err error) {
//过期时间固定为5秒
res, err = d.redis.SetNX(ctx, key, value, time.Second*lockExpire).Result()
//如果设置成功返回true 没成功返回false
if err != nil {
log.Errorc(ctx, "[SetLock] d.xRedis.SetNX failed ,err(%+v)", err)
return
}
return
}
func (s *Idempotent) getRedisLock(ctx context.Context) (res bool, lockVal int, err error) {
key := s.getLockKey()
rand.Seed(time.Now().Unix())
lockVal = rand.Intn(100) + 1
res, err = s.getNxLock(ctx, key, lockVal)
if err != nil {
log.Errorc(ctx, "[getRedisLock] failed ,err(%+v)", err)
return
}
if !res {
//加报警日志
log.Warnc(ctx, "[getRedisLock] lock been taken key(%s) lockVal(%d)", key, lockVal)
}
return
}
解锁
在方法退出之前的defer 中添加解锁操作
//操作完成解锁
func (s *Idempotent) Unlock(ctx context.Context) {
//说明没有获取到锁
if s.lockVal == 0 {
return
}
key := s.getLockKey()
err := s.unlock(ctx, key, s.lockVal)
if err != nil {
log.Errorc(ctx, "[Unlock] s.dao.Unlock failed ,err(%+v)", err)
return
}
}
func (d *Idempotent) unlock(ctx context.Context, key string, value int) (err error) {
res, err := d.redis.Get(ctx, key).Int()
if err != nil && err != redis.ErrNil {
log.Errorc(ctx, "[Unlock] d.xRedis.Get failed ,key(%s) err(%+v)", key, err)
return
}
//说明锁已经没有了
if err == redis.ErrNil {
err = nil
return
}
//说明目前锁已经是别人的了
if res != value {
log.Warnc(ctx, "[Unlock] lock already been token key(%s) old(%d) now(%d)", key, value, res)
//不做错误处理,直接返回
return
}
//释放锁
cmd, err := d.redis.Del(ctx, key).Result()
if err != nil {
log.Errorc(ctx, "[Unlock] del failed ,err(%+v) key(%s) return(%d)", err, key, cmd)
return
}
return
}
list
消息队列
lpush + rpop 组合可以实现前进先出的消息队列
127.0.0.1:6379> lpush myhobby sing sport read
(integer) 3
127.0.0.1:6379> rpop myhobby
"sing"
想要主动及时读取消息,可以使用阻塞式读取,brpop key timeout 命令表示阻塞timeout时间等待消息,时间过了,命令结束,不再等待
127.0.0.1:6379> lpush myhobby sing sport read
(integer) 3
127.0.0.1:6379> rpop myhobby
"sing"
127.0.0.1:6379> brpop myhobby 5 //设置阻塞5秒,因为list里面目前有元素所以立即返回
1) "myhobby"
2) "sport"
127.0.0.1:6379> brpop myhobby 50 //继续立即返回
1) "myhobby"
2) "read"
127.0.0.1:6379> brpop myhobby 50 //等待50秒没有元素,直接返回
(nil)
获取一段范围内的val
127.0.0.1:6379> lpush myhobby 1 2 3 4 5
(integer) 5
127.0.0.1:6379> lrange myhobby 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lrange myhobby 0 2
1) "5"
2) "4"
3) "3"
删除某个元素
lrem key count val
- count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
- count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
- count = 0 : 移除表中所有与 VALUE 相等的值
127.0.0.1:6379> lpush myhobby 5
(integer) 6
127.0.0.1:6379> lrange myhobby 0 -1
1) "5"
2) "5"
3) "4"
4) "3"
5) "2"
6) "1"
127.0.0.1:6379> lrem myhobby 2 5 //从表头开始删除2个val为5的元素
(integer) 2
127.0.0.1:6379> lrange myhobby 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
修改某个元素
lset key index val 修改索引index位置出的元素
127.0.0.1:6379> lrange myhobby 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> lset myhobby 0 7 //修改位置0 的值为7
OK
127.0.0.1:6379> lrange 0 -1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange myhobby 0 -1
1) "7"
2) "3"
3) "2"
4) "1"
hash
对象有多种属性
一个有多种属性的对象,filed 对应属性
127.0.0.1:6379> hmset profile name lisi age 28 sexuality female
OK
127.0.0.1:6379> hgetall profile
1) "name"
2) "lisi"
3) "age"
4) "28"
5) "sexuality"
6) "female"
127.0.0.1:6379> hdel profile age name
(integer) 2
127.0.0.1:6379> hset profile name zhangsan age 36
(integer) 2
127.0.0.1:6379> hmget profile name age
1) "zhangsan"
2) "36"
127.0.0.1:6379> hlen profile
(integer) 3
127.0.0.1:6379> hincrby profile age 4
(integer) 40
127.0.0.1:6379> hincrby profile age -4
(integer) 36
购物车
| key | field | val |
|---|---|---|
| 用户ID | 收藏商品id | 商品数量 |
图片地址
xiaolincoding.com/redis/data_…
127.0.0.1:6379> hset cart:21700655 100 1 //添加商品id为100 的商品
(integer) 1
127.0.0.1:6379> hincrby cart:21700655 100 2 //添加数量
(integer) 3
127.0.0.1:6379> hlen cart:21700655 //获取收藏商品总数
(integer) 1
127.0.0.1:6379> hgetall cart:21700655 //获取所有购物车商品
1) "100"
2) "3"
127.0.0.1:6379> hdel cart:21700655 100 //删除id为100 的商品
(integer) 1
set
特点是 去重,无序,支持交并差
点赞
对一篇文档每个人只能点赞一次
127.0.0.1:6379> sadd article:1 zhangsan lisi wanger //张三 李四 王二 点赞了文章
(integer) 3
127.0.0.1:6379> smembers article:1 //查看所有点赞文章的用户
1) "wanger"
2) "lisi"
3) "zhangsan"
127.0.0.1:6379> srem article:1 zhangsan //张三取消了点赞
(integer) 1
127.0.0.1:6379> scard article:1 //文档点赞用户数
(integer) 2
127.0.0.1:6379> sismember article:1 zhangsan //张三是否点赞了文章
(integer) 0
127.0.0.1:6379> sismember article:1 lisi
(integer) 1
共同关注
支持交集,所以可以查找共用拥有元素
127.0.0.1:6379> sadd uid:1 zhangsan lisi //用户1关注了 张三 李四
(integer) 2
127.0.0.1:6379> sadd uid:2 lisi wanger //用户2 关注了 李四 王二
(integer) 2
127.0.0.1:6379> sinter uid:1 uid:2 //两个人共同关注
1) "lisi"
127.0.0.1:6379> sdiff uid:1 uid:2 //找到用户1 关注的 推荐给用户2
1) "zhangsan"
抽奖活动
如果一个人只能有一次中奖机会,中完即删
127.0.0.1:6379> sadd pool zhangsan lisi wanger //员工添加到中奖池
(integer) 3
127.0.0.1:6379> srandmember pool 2 //随机抽两个一等奖,可以重复中奖
1) "wanger"
2) "zhangsan"
127.0.0.1:6379> smembers pool //全部都在
1) "wanger"
2) "lisi"
3) "zhangsan"
127.0.0.1:6379> spop pool 2 // 随机两名,不能重复,直接剔除
1) "wanger"
2) "lisi"
127.0.0.1:6379> smembers pool
1) "zhangsan"
zset
特点 比较set 多了根据score值排序
排行榜
127.0.0.1:6379> zadd rank 10 uid:1 20 uid:20 30 uid:30 30 uid:40 //添加成员
(integer) 4
127.0.0.1:6379> zrange rank 0 -1 //获取所有成员
1) "uid:1"
2) "uid:20"
3) "uid:30"
4) "uid:40"
127.0.0.1:6379> zscore rank uid:1 //查询某个成员的分数
"10"
127.0.0.1:6379> zcard rank //获取排行榜成员数
(integer) 4
127.0.0.1:6379> zincrby rank 2 uid:1 //排行榜中成员1 分值增加2
"12"
127.0.0.1:6379> zrem rank uid:3 //删除成员3
(integer) 0
127.0.0.1:6379> zrange rank 0 1 withscores //获取排行榜最后两名用户 附加分值返回
1) "uid:1"
2) "12"
3) "uid:20"
4) "20"
127.0.0.1:6379> zrevrange rank 0 -1 withscores //倒序返回排行榜信息,一般应用按照分高到低展示排序 用这个命令
1) "uid:40"
2) "30"
3) "uid:30"
4) "30"
5) "uid:20"
6) "20"
7) "uid:1"
8) "12"
127.0.0.1:6379> zrangebyscore rank 30 100 //找到分值30-100 的所有用户
1) "uid:30"
2) "uid:40"
命令大全
| 类型 | 增 | 删 | 改 | 查 | 长度 |
|---|---|---|---|---|---|
| string | set mset incr incrby | del | set | get | / |
| list | lpush | lrem | lset | lrange 查范围 lindex 查某个索引 rpop 弹出元素 | llen |
| hash | hset hmset hincrby 修改field值 | hdel | hset hincrby 修改field值 | hget hgetall | hlen |
| set | sadd | srem | / | srandmember 随机返回 sismember 是否是成员 spop 随机弹出 sinter 交集 sdiff 差集 | scard |
| zset | zadd zincrby 修改元素分数 | zrem 删除元素 zremrangebyscore 删除分数区间元素 zremrangebyrank 删除排名区间元素 | zadd 修改分数 zincrby 修改元素分数 | zrank 某个成员排名 zrange 正序范围排名 zrevrange 倒序排名 zrangebyscore 分数区间内成员 | zcard |