Redis常用数据类型
Redis是NoSQL型数据库,数据都在内存中,支持持久化,支持多种数据结构的存储,如String、list、set、hash、zset。一般作为缓存数据库辅助持久化的数据库。本篇记录基本概念和操作,关于持久化、主从复制、事务、集群等内容的学习查看官方文档。
Redis安装配置
Redis安装
- 下载官网最新redis压缩包,上传到虚拟机中并解压
- 安装c语言编译环境:yum install gcc
- 进入redis解压后目录,make进行编译
- make install
- 安装目录在/usr/local/bin,包括
- redis-benchmark:性能测试工具
- redis-check-aof:修复有问题的AOF文件
- redis-check-dump:修复有问题的dump.rdb文件
- redis-sentinel:Redis集群使用
- redis-server:Redis服务器启动命令
- redis-cli:客户端操作入口
Redis启动
- 备份redis.conf到其它目录下,如cp redis.conf /etc/
- 修改备份文件中daemonize no改为yes,可以让服务在后台启动
- 启动:redis-server /etc/redis.conf
- 连接:redis-cli
五大数据类型
Redis默认16个数据库,从0到15,select dbid 可以切换数据库,所有库统一密码。
dbsize:查看当前库的key数量
flushdb:清空当前库
flushall:清空所有库(慎用)
Redis是单线程+多路IO复用技术
String
- keys *:查看当前库所有key
- exists key:判断某个key是否存在
- type key:查看key是什么类型
- del key:删除指定key的数据
- unlink key:根据value选择非阻塞删除
- expire key n:为key设置过期时间,ttl key可以查看过期时间,-1表示永不过期,-2表示已过期
- set key value:添加键值对
- get key:查询对应键值
- append key value:将给定的value追加到原值末尾
- strlen key:获取值的长度
- setnx key value:只有key不存在时,设置key值成功
- incr/decr key:将 key中储存的数字值增1/减1
- 该操作是原子操作,不会被线程调度机制打断,一旦开始,就一直运行到结束,中间不会切换到另一个线程,Redis单命令的原子性得益于Redis的单线程。
- incrby/decrby key <步长>:将key中存储数值增减步长
- mset key1 value1 key2 value2 …:同时设置多个key-value
- mget key1 key2…:同时获取多个value
- msetnx key1 value1 key2 value2:同时设置多个key-value,当且仅当所有key不存在成功。
- 原子性:有一个key存在则都设置失败
- getrange key start end :获取值的范围,两端都闭
- setrange key offset value:从offset开始,用value覆盖原字符串
- setex key 过期时间 value:设置键值同时设置过期时间,单位秒
- getset key value:获取key对应旧值,同时设置新值为value
数据结构:简单动态字符串(Simple Dynamic String,缩写SDS),是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。
List
- lpush/rpush key value1 value2…:从左边/右边插入一个/多个值
- lpop/rpop key:从左边/右边取出一个值。值取完,键也不存在了
- rpoplpush key1 key2:从key1列表右侧取出一个值,查到key2的左侧
- lrange key start stop:按照索引下标获得元素(从左到右),0 -1表示所有
- lindex key index:按照索引下标获取元素
- llen key:获得列表长度
- linsert key before/after value newvalue:在value前/后插入newvalue
- lset key index value:将列表key 下标为index的值替换成value
数据结构:快速链表quickList。在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。
Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
Set
- sadd key value1 value2…:将元素加入集合key中,已存在的元素被忽略
- smembers key:查询该集合所有值
- sismember key value:判断集合key是否含有该value值
- scard key:返回集合元素个数
- srem key value1 value2…:删除集合中的元素
- spop key:从集合中随机去除一个值
- srandmember key n:从集合中随机取出n个值。不会删除
- smove key1 key2 value:把key1集合的value移到key2中去
- sinter k1 k2:返回两集合交集
- sunion k1 k2:返回两集合并集
- sdiff k1 k2:返回两集合差集,在k1中不在k2中的
数据结构:Set数据结构是dict字典,字典是用哈希表实现的。Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。
Hash
Redis hash是一个String类型的field和value的映射表,适合用于存储对象
- hset key field value field value…:设置key中的field键为value
- 如hset user id 1 name jack age 20
- hget key field:从key中取出键为field的值
- hdel key field1 field2…:删除key中的field域
- hexists key field:判断key中是否存在域field
- hkeys key:列出该key的所有field
- hvals key:列出该key的所有value
- hincrby key field increment:为key中field域加上increment
- hsetnx key field value:将key中域field值设置为value,仅当field域不存在时成功
数据结构:Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
Zset(有序集合)
与普通集合set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员
- zadd key score1 value1 score2 value2…:将value值加入有序集合key中,并指定score值
- zrange key start stop [withscores]:返回有序集合中,下标在[start,stop]之间的元素
- zrangebyscore key min max:返回有序集 key 中,所有 score 值介于 min 和 max 之间的成员
- zincrby:为元素加上增量
- zrem key value:删除该集合指定元素
- zcount key min max:返回该集合分数区间内元素个数
- zrank key value:返回该值排名,从0开始
zset结构同时包含一个字典和一个跳跃表,跳跃表按score从小到大保存所有集合元素。字典保存着从member到score的映射。这两种结构通过指针共享相同元素的member和score,不会浪费额外内存。
跳跃表的结构:跳跃表
Jedis操作Redis
依赖
1 | <dependency> |
连接Redis
1 | public class JedisDemo { |
Key
1 | jedis.set("k1", "v1"); |
String
1 | jedis.mset("str1","v1","str2","v2","str3","v3"); |
List
1 | jedis.lpush("k1","v1","v2"); |
Set
1 | jedis.sadd("orders", "order01"); |
Hash
1 | jedis.hset("hash1","userName","lisi"); |
Zset
1 | jedis.zadd("zset01", 100d, "z3"); |