Redis入门
笔记
选择 2 号数据库 select 2 查看 DB 大小 DBSIZE 查看数据库所有的 key keys * 清除全部数据库的内容 flushall 清除当前数据库 flushdb
查看键的类型
type key
127.0.0.1:6379> set key1 v1 set 设置值 OK 127.0.0.1:6379> get key1 get 获取值 "v1" 127.0.0.1:6379> keys * keys * 获得该库的所有值 "key1" 127.0.0.1:6379> exists key1 exists 判断是否存在键 (integer) 1 127.0.0.1:6379> append key1 key2 append 追加字符串 append 键 值 (integer) 6 127.0.0.1:6379> get key1 "v1key2" 127.0.0.1:6379> strlen key1 strlen 返回键的长度 (integer) 6
1.2. 增量 (增减) incr decr incrby decrby
127.0.0.1:6379> set views 0 OK 127.0.0.1:6379> get views "0" 127.0.0.1:6379> incr views 自增 1 (integer) 1 127.0.0.1:6379> get views "1" 127.0.0.1:6379> decr views 自减 1 (integer) 0 127.0.0.1:6379> get views "0" 127.0.0.1:6379> decr views (integer) -1 127.0.0.1:6379> get views "-1"127.0.0.1:6379> incrby views 10 设置指定增量 incrby 键 增量
(integer) 9
127.0.0.1:6379> get views
"9"
127.0.0.1:6379> decrby views 7 设置指定减量
(integer) 2
127.0.0.1:6379> get views
"2"
1.3 字符串切片 getrange
127.0.0.1:6379> get key1 "nameoplokijuhygt" 127.0.0.1:6379> getrange key1 0 3 截取字符串 0,1,2,3 getrange 键 开始索引 结束索引 "name" 127.0.0.1:6379> getrange key1 0 -1 获取全部的字符串 "nameoplokijuhygt"
1.4 替换字符串 setrange
127.0.0.1:6379> set key2 abcdefg OK 127.0.0.1:6379> get key2 "abcdefg" 127.0.0.1:6379> setrange key2 2 xx 替换指定位置开始的字符串 (integer) 7 127.0.0.1:6379> get key2 "abxxefg"
1.5 过期时间 setex
127.0.0.1:6379> setex key3 30 "nihao" setex 键 过期时间 值 设置过期时间 OK 127.0.0.1:6379> get key3 "nihao" 127.0.0.1:6379> ttl key3 查看 ttl 时间 (integer) 23 127.0.0.1:6379> setnx mykey "redis" setnx 如果不存在则设置, 成功返回 1, 失败返回 0 (integer) 1 127.0.0.1:6379> ttl key3 (integer) 0 127.0.0.1:6379> setnx mykey "mysql" setnx, 返回 0, 设置失败 (integer) 0 127.0.0.1:6379> get mykey 没有修改 mykey 的值 "redis"
1.6 mset mget 设置多个值
127.0.0.1:6379> mset name "gg" age 89 type "student" mset 键 值 键 值... OK 127.0.0.1:6379> keys * 1) "name" 2) "type" 3) "age" 127.0.0.1:6379> mget name age type mget 键 键 键... 1) "gg" 2) "89" 3) "studen 127.0.0.1:6379> msetnx address qin name oo oop java msetnx 是一个原子操作,name 存在, 全部设置失败 (integer) 0 127.0.0.1:6379> get oop 则 oop 设置失败查询不到 (nil) 127.0.0.1:6379> get name "gg"
1.7 对象的巧妙设计
127.0.0.1:6379> mset user:1:name gg user:1:age 78 OK 127.0.0.1:6379> mget user:1:name user:1:age 1) "gg" 2) "78"
1.8 getset 先 get 再 set 获去旧值, 设置新值
127.0.0.1:6379> getset db redis 没有旧值,get 为 nil,set 执行 db=redis (nil) 127.0.0.1:6379> get db "redis" 127.0.0.1:6379> getset db mongdb 有旧值,getdb=redis, 然后执行 setdb=mongdb "redis" 127.0.0.1:6379> get db "mongdb"
-
统计数
-
统计多单位的数量
-
对象缓存存储
127.0.0.1:6379> lpush list one 将一个值或者多个值插入到列表的头部 (integer) 1 (0.70s) 127.0.0.1:6379> lpush list two (integer) 2 127.0.0.1:6379> lpush list three (integer) 3 127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "two" 3) "one" 127.0.0.1:6379> lrange list 0 1 获取 list 0,1 索引的值 1) "three" 2) "two" 127.0.0.1:6379> rpush list right 将一个值或者多个值插入到列表的尾部 (integer) 4 127.0.0.1:6379> lrange list 0 -1 获取 list 全部的值 1) "three" 2) "two" 3) "one" 4) "right"
2.2 移除 lpop
127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "two" 3) "one" 4) "right" 127.0.0.1:6379> lpop list 移除列表的第一个元素 "three" 127.0.0.1:6379> rpop list 移除列表的最后一个元素 "right" 127.0.0.1:6379> lrange list 0 -1 1) "two" 2) "one"
移除指定的值 lrem
127.0.0.1:6379> lrange list 0 -1
1) "three1"
2) "three2"
3) "three2"
4) "three1"
5) "three"
6) "three"
7) "two"
8) "one"
127.0.0.1:6379> lrem list 1 three1 lrem 键 数量 值
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three2"
2) "three2"
3) "three1"
4) "three"
5) "three"
6) "two"
7) "one"
2.3 通过下标获取值 lindex
127.0.0.1:6379> lrange list 0 -1 1) "two" 2) "one" 127.0.0.1:6379> lindex list 1 获取下标为 1 的值 "one" 127.0.0.1:6379> lindex list 0 获取下标为 0 的值 "two" 127.0.0.1:6379> llen list 获取列表的长度 (integer) 2
2.4 截取指定的长度 ltrim
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2 ltrim 键 开始索引 结束索引
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
2.5 移动 rpoplpush
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> rpoplpush mylist myother 移除最后一个元素, 移动到其他列表
"hello2"
127.0.0.1:6379> lrange myother 0 -1
1) "hello2"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
127.0.0.1:6379>
2.6 lset
127.0.0.1:6379> lpush list "hello" (integer) 1 127.0.0.1:6379> lrange list 0 0 1) "hello" 127.0.0.1:6379> lset list 0 item 将指定下标的值替换为另外一个值, 更新操作 OK 127.0.0.1:6379> lrange list 0 0 1) "item" 127.0.0.1:6379> lset list 1 item1 不存在的会报错 (error) ERR index out of range
127.0.0.1:6379> sadd myset "hello" set 集合中添加元素 (integer) 1 127.0.0.1:6379> sadd myset "gg" (integer) 1 127.0.0.1:6379> sadd myset "nihao" (integer) 1 127.0.0.1:6379> smembers myset 查看 set 集合中的值 1) "nihao" 2) "gg" 3) "hello" 127.0.0.1:6379> sismember myset nihao 查看 set 集合中是否存在某个值 (integer) 0 127.0.0.1:6379> sismember myset nihao (integer) 0 127.0.0.1:6379> sismember myset gg (integer) 1 127.0.0.1:6379> sismember myset "nihao" (integer) 1
3.2 指定移除 srem scard
127.0.0.1:6379> srem myset "nihao" (integer) 1 127.0.0.1:6379> scard myset 获取集合的长度 (integer) 2 127.0.0.1:6379> smembers myset 1) "gg" 2) "hello"
3.3 随机获取元素 srandmember myset count 多个元素
127.0.0.1:6379> srandmember myset "pop" 127.0.0.1:6379> srandmember myset "gg"
3.4. 随机删除 key spop
127.0.0.1:6379> spop myset 随机删除 set 集合中的元素 "gg" 127.0.0.1:6379> spop myset "hello" 127.0.0.1:6379> spop myset "pop" 127.0.0.1:6379> spop myset
3.5. 移动集合元素 smove 集合 1 集合 2 值
127.0.0.1:6379> smove myset myset1 "hell1" 将一个集合中的值移动到另一个集合 (integer) 1 127.0.0.1:6379> smembers myset 1) "heopop" 2) "hello" 127.0.0.1:6379> smembers myset1 1) "ss" 2) "hell1"
3.6 集合 交差并补
key1 a b c key2 b c e 127.0.0.1:6379> sdiff key1 key2 key1 与 key2 的差集 1) "a" 127.0.0.1:6379> sdiff key2 key1 key12 与 key1 的差集 1) "e" 127.0.0.1:6379> sinter key1 key2 key1 与 key2 的交集 1) "c" 2) "b" 127.0.0.1:6379> sinter key2 key1 1) "c" 2) "b" 127.0.0.1:6379> sunion key1 key2 key1 与 key2 的并集 1) "b" 2) "e" 3) "c" 4) "a"
127.0.0.1:6379> hset myhash name1 "gg" hset 键 字段 值 (integer) 1 127.0.0.1:6379> hget myhash name1 "gg" hmset 键 字段 1 值 1 字段 2 值 2... 127.0.0.1:6379> hmset myhash name1 "hello" name2 gg name3 woow OK 127.0.0.1:6379> hmget myhash name1 name2 name3 1) "hello" 2) "gg" 3) "woow" 127.0.0.1:6379> hgetall myhash 1) "name1" 2) "hello" 3) "name2" 4) "gg" 5) "name3" 6) "woow"
4.2 删除指定的字段 hdel
127.0.0.1:6379> hdel myhash name1 hdel 键 字段 (integer) 1 127.0.0.1:6379> hgetall myhash 1) "name2" 2) "gg" 3) "name3" 4) "woow"
4.3 获取 hash 的长度
127.0.0.1:6379> hlen myhash
(integer) 2
4.4 判断 hash 中的指定字段是否存在 hexists
127.0.0.1:6379> hexists myhash name2 (integer) 1 127.0.0.1:6379> hexists myhash name1 (integer) 0 127.0.0.1:6379>
4.5 只获取键或只获取值 hkeys hvals
127.0.0.1:6379> hkeys myhash 1) "name2" 2) "name3" 127.0.0.1:6379> hvalues myhash (error) ERR unknown command 'hvalues' 127.0.0.1:6379> hvals myhash 1) "gg" 2) "woow"
4.6 hash 增量 hincrby 键 字段 增量
127.0.0.1:6379> hset myhash name4 5 (integer) 1 127.0.0.1:6379> hincrby myhash name4 1 (integer) 6 127.0.0.1:6379> hget myhash name4 "6" 127.0.0.1:6379> hincrby myhash name4 -1 (integer) 5
4.7 hsetnx 存在则设置, 不存在设置失败
127.0.0.1:6379> hsetnx myhash name5 op (integer) 1 127.0.0.1:6379> hsetnx myhash name5 op (integer) 0
127.0.0.1:6379> zadd myset 1 one zadd 键 权重 成员 (integer) 1 (0.70s) 127.0.0.1:6379> zadd myset 2 two 3 three zadd 键 权重 成员 权重 成员... (integer) 2 127.0.0.1:6379> zrange myset 0 -1 zrange 键 开始索引 结束索引 1) "one" 2) "two" 3) "three"
127.0.0.1:6379> zadd salary 2500 xiaohong (integer) 1 127.0.0.1:6379> zadd salary 5000 zhangsan (integer) 1 127.0.0.1:6379> zadd salary 288 gg (integer) 1 127.0.0.1:6379> zrangebyscore salary -inf +inf 1) "gg" 2) "xiaohong" 3) "zhangsan"
拓展:
ZRANGEBYSCORE zset (1 5 返回所有符合条件 1 < score <= 5 的成员,而 ZRANGEBYSCORE zset (5 (10 则返回所有符合条件 5 < score < 10 的成员。区间及无限
min 和 max 可以是 -inf 和 +inf ,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,使用 ZRANGEBYSCORE 这类命令。可选的 LIMIT 参数指定返回结果的数量及区间 (就像 SQL 中的 SELECT LIMIT offset, count),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。
ZRANGEBYSCORE salary -inf +inf WITHSCORES # 显示整个有序集及成员的 score 值
1) "jack"
2) "2500"
3) "tom"
4) "5000"
5) "peter"
6) "12000"redis> ZRANGEBYSCORE salary -inf 5000 WITHSCORES # 显示工资 <=5000 的所有成员
1) "jack"
2) "2500"
3) "tom"
4) "5000"redis> ZRANGEBYSCORE salary (5000 400000 # 显示工资大于 5000 小于等于 400000 的成员
1) "peter"
5.3 移除 zrem 获取长度 zcard
127.0.0.1:6379> zrange salary 0 -1 1) "gg" 2) "xiaohong" 3) "zhangsan" 127.0.0.1:6379> zrem salary xiaohong (integer) 1 127.0.0.1:6379> zrange salary 0 -1 1) "gg" 2) "zhangsan" 127.0.0.1:6379> zcard salary (integer) 2
5.4 升序与降序 zrangebyscore zrevrange
redis> ZRANGE salary 0 -1 WITHSCORES # 递增排列 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000"redis> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列
1) "jack"
2) "5000"
3) "tom"
4) "4000"
5) "peter"
6) "3500"
5.5 计算返回成员数量 zcount 包括 min 和 max 值 大于等于, 小于等于
redis> ZRANGE salary 0 -1 WITHSCORES # 测试数据 1) "jack" 2) "2000" 3) "peter" 4) "3500" 5) "tom" 6) "5000"redis> ZCOUNT salary 2000 5000 # 计算薪水在 2000-5000 之间的人数
(integer) 3redis> ZCOUNT salary 3000 5000 # 计算薪水在 3000-5000 之间的人数
(integer) 2
-
GEOADD
-
GEODIST
-
GEOHASH
-
GEOPOS
-
GEORADIUS
-
GEORADIUSBYMEMBER
127.0.0.1:6379> PFadd mykey a b c d e f g h i j k 创建第一组元素 (integer) 1 127.0.0.1:6379> PFcount mykey 统计元素 (integer) 11 127.0.0.1:6379> PFadd mykey2 p o i u y t r e w 创建第二组元素 (integer) 1 127.0.0.1:6379> PFcount mykey2 (integer) 9 127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 合并两组数据 (并集) OK 127.0.0.1:6379> pfcount mykey3 (integer) 17
127.0.0.1:6379> setbit sign 0 1 (integer) 0 127.0.0.1:6379> setbit sign 1 1 (integer) 0 127.0.0.1:6379> setbit sign 2 1 (integer) 0 127.0.0.1:6379> setbit sign 3 0 (integer) 0 127.0.0.1:6379> setbit sign 4 1 (integer) 0 127.0.0.1:6379> setbit sign 5 0 (integer) 0 127.0.0.1:6379> setbit sign 6 0 (integer) 0127.0.0.1:6379> getbit sign 4
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 0
127.0.0.1:6379>
统计: 返回 bitmap 为 1 的值的总数
127.0.0.1:6379> bitcount sign
(integer) 4
-
开启事务 (mylti)
-
命令入队
-
执行事务
127.0.0.1:6379> multi 开启事务 (error) ERR MULTI calls can not be nested 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> get k2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> exec 执行事务 1) OK 2) OK 3) OK 4) "v2" 5) OK (0.75s) 127.0.0.1:6379>
2. 放弃事务 discard
127.0.0.1:6379> multi 开启事务 OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> discard 取消事务 OK 127.0.0.1:6379> get k2 (nil)
3. 编译型异常 (代码有问题! 命令有错!), 事务中的所有的命令都不会被执行
127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> getset k3 (error) ERR wrong number of arguments for 'getset' command 127.0.0.1:6379> exec 执行事务报错, 所有的命令都不会执行 (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k2 (nil)
运行时异常 (1/0), 如果事务队列中存在语法型, 那么执行命令的时候, 其他命令是可以正常执行, 错误命令抛出异常
127.0.0.1:6379> set k1 "v1" OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr k1 执行失败 QUEUED 127.0.0.1:6379> set k2 v2 执行成功 QUEUED 127.0.0.1:6379> set k3 v4 执行成功 QUEUED 127.0.0.1:6379> get k3 执行成功 QUEUED 127.0.0.1:6379> exec 1)(error) ERR value is not an integer or out of range 2) OK 3) OK 4) "v4"
-
认为生命时候都不会出问题, 无论做什么都会上锁
-
认为生命时候都不会出问题, 所以不会上锁, 更新数据的时候去判断一下在此期间是否有人修改过这个数据
-
获取 version
- 更新的时候比较 version
127.0.0.1:6379> set money 100 OK 127.0.0.1:6379> set out 0 OK 127.0.0.1:6379> watch money 监视 money 对象 OK 127.0.0.1:6379> multi 事务正常结束, 数据期间没有发生变动, 执行成功! OK 127.0.0.1:6379> decrby money 20 QUEUED 127.0.0.1:6379> incrby out 20 QUEUED 127.0.0.1:6379> exec 1)(integer) 80 2)(integer) 20
线程 1
127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 10 QUEUED 127.0.0.1:6379> incrby out 10 QUEUED 127.0.0.1:6379> exec (nil)
线程 2: 线程 1 没完成之前线程 2 线改变了 money 的值, 执行失败, 返回 nil
127.0.0.1:6379> get money "80" 127.0.0.1:6379> set money 100 OK 127.0.0.1:6379> get money "100"
127.0.0.1:6379> unwatch OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby money 10 QUEUED 127.0.0.1:6379> incrby out 10 QUEUED 127.0.0.1:6379> exec 1)(integer) 90 2)(integer) 30
锁:redis 可以实现乐观锁
User user = new User("序列化", 3);String jsonUser </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ObjectMapper().writeValueAsString(user); redisTemplate.opsForValue().set(</span>"user"<span style="color: rgba(0, 0, 0, 1)">,jsonUser); System.out.println(redisTemplate.opsForValue().get(</span>"user"));</pre>
2. 方式 2: 实体类实现 Serializable 接口
public class User implements Serializable {
3. 方式 3: 自定义 redisTemplate
@Configuration public class RedisConfig {@Bean </span><span style="color: rgba(0, 0, 255, 1)">public</span> RedisTemplate<String, Object><span style="color: rgba(0, 0, 0, 1)"> myRedisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate</span><String, Object> template = <span style="color: rgba(0, 0, 255, 1)">new</span> RedisTemplate<String, Object><span style="color: rgba(0, 0, 0, 1)">(); template.setConnectionFactory(redisConnectionFactory); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">配置具体的序列化方式</span> Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = <span style="color: rgba(0, 0, 255, 1)">new</span> Jackson2JsonRedisSerializer<Object>(Object.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); ObjectMapper objectMapper </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2021-02-03 官方不建议使用
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//2021-02-03 使用这个
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(objectJackson2JsonRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);template.setHashValueSerializer(objectJackson2JsonRedisSerializer); template.afterPropertiesSet(); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> template; }
}
//注入 @Autowired @Qualifier("myRedisTemplate") private RedisTemplate redisTemplate;