4.Redis基本操作与数据类型
[toc]
数据类型
- Redis通用命令 
- String: 字符串类型 
- Hash: 哈希类型 
- List: 列表类型 
- Set: 集合类型 
- Sorted set: 顺序集合类型 
Redis通用命令
连接Redis
| 1 | # 连接redis | 
库操作
| 1 | # 切换库[1-15] | 
数据操作
- 增- 1 
 2
 3
 4
 5- # 追加数据(在value后追加指定值) 
 127.0.0.1:6379> APPEND name BB
 (integer) 1
 127.0.0.1:6379> get name
 "ChenlinBB"
- 删- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- # 删除所在库的数据 
 127.0.0.1:6379> flushdb
 # 删除所有库的数据
 127.0.0.1:6379> flushall
 # 貌似和del一样(根据value选择非阻塞删除仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。)
 127.0.0.1:6379> UNLINK ke
 (integer) 1
 # 删除一条"key"
 127.0.0.1:6379> del name
 (integer) 1
 # 同时删除多条"key"
 127.0.0.1:6379> del k1 k2 k3
 (integer) 3
- 改- 1 
 2
 3
 4
 5
 6- # 临时修改redis配置 
 127.0.0.1:6379> CONFIG SET protected-mode yes
 # 修改"key"的名字(将chenlin改成cl)
 127.0.0.1:6379> RENAME chenlin cl
 OK
- 查- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- # 查看所有的数据(注意!不要轻易使用,如想查看数据,先查看数据量DBSIZE) 
 127.0.0.1:6379> keys *
 1) "name"
 # 查看数据量
 127.0.0.1:6379> DBSIZE
 (integer) 1
 # 查看单个数据(有数据)
 127.0.0.1:6379> KEYS name
 1) "name"
 # 查看单个数据(无数据)
 127.0.0.1:6379> KEYS xxx
 (empty array)
 # 查看所有的配置
 CONFIG GET *
 # 查看指定配置
 127.0.0.1:6379> CONFIG GET bind
 1) "bind"
 2) "10.0.0.51 172.16.1.51 127.0.0.1"
密码的配置与修改
- 配置文件配置密码- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- # 修改配置文件 
 vim redis.conf
 requirepass 123
 
 # 使用密码连接
 redis-cli -a 123
 # 登陆后输入密码
 redis-cli
 127.0.0.1:6379> AUTH 123
 OK
 127.0.0.1:6379> DBSIZE
 (integer) 1
 # redis连接后获取密码
 127.0.0.1:6379> CONFIG GET requirepass
 1) "requirepass"
 2) "123"
- redis连接后修改密码- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- # 修改redis密码为234 
 127.0.0.1:6379> CONFIG SET requirepass 234
 OK
 127.0.0.1:6379> exit
 # 测试登录
 redis-cli
 127.0.0.1:6379> DBSIZE
 (error) NOAUTH Authentication required.
 127.0.0.1:6379> auth 234
 OK
配置文件
| 1 | # 编辑配置文件 | 
Redis数据结构之字符串(String)
数据结构
String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。
是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.

如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len
当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。
需要注意的是字符串最大长度为512M。
- String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。
- String类型是二进制安全的。意味着Redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
- String类型可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。
命令行模式
| 1 | # 进入命令行模式: | 
查看命令帮助
| 1 | 127.0.0.1:6379> help @string | 
String数据结构中键(key)操作命令
- 增- set - 语法格式 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- # 语法格式 
 set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
 * NX:当数据库中key不存在时,可以将key-value添加数据库
 * XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
 * EX:key的超时秒数
 * PX:key的超时毫秒数,与EX互斥
 * NX:key不存在时创建,已存在则忽略。
 * XX:key存在则更新,不存在则忽略。
 # 增加数据的命令有以下几个:
 * set :标准命令,"key"不存在时创建,已存在则更新。
 * mset :批量创建"key",所有"key"不存在时创建,已存在则更新。
 * setex :增加key并设置生存时间(单位为秒)
 * psetex:增加key并设置生存时间(以毫秒为单位,1s=1000ms)
 * setnx :"key"不存在时创建,已存在则忽略。
 * msetnx:批量创建"key",所有"key"key不存在时创建,已存在则忽略。
- 基础用法 - 1 
 2
 3
 4
 5
 6
 7- # 增加key 
 127.0.0.1:6379> set name cl
 OK
 # 设置多个key
 127.0.0.1:6379> MSET name1 cl age1 18
 OK
- 使用set命令结合”EX”,”PX”的用法 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- # 增加key并设置生存时间(单位为秒) 
 127.0.0.1:6379> set name cl ex 10
 OK
 # "set"和"ex"合并成"setex"
 127.0.0.1:6379> SETEX name 10 cl
 OK
 # 增加key并设置生存时间(以毫秒为单位,1s=1000ms)
 127.0.0.1:6379> set name cl px 10
 OK
 # "set"和"px"合并成"psetex"
 127.0.0.1:6379> PSETEX name 15 cl
 OK
- 使用set命令结合”NX”,”XX”的用法 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- # 使用"nx"后:"key"不存在时创建,已存在则忽略。 
 127.0.0.1:6379> set name cl nx
 OK
 127.0.0.1:6379> set name cl1 nx
 (nil)
 127.0.0.1:6379> get name
 "cl"
 # "set"与"nx"合并成“setnx”
 127.0.0.1:6379> SETNX name cl1
 (integer) 0
 127.0.0.1:6379> get name
 "cl"
- 批量增加多个”key”,同时定义多个键值对,”mset”也可以和”nx”一起用。 - 1 
 2
 3
 4
 5- # 批量创建"key",所有"key"不存在时创建,已存在则更新。 
 mset key1 value1 [key2 value2...]
 # 批量创建"key",所有"key"不存在时创建,已存在则忽略。
 msetnx key1 value1 [key2 value2...]
 
- 追加数据 - 基础用法 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- # 使用setrange在第"num"个字符处更新数据(从0开始算起) 
 127.0.0.1:6379> SETRANGE name 3 cccccc
 (integer) 9
 127.0.0.1:6379> get name
 "123cccccc"
 # 在指定"key"的"value"后追加字符,如果"key"不存在则创建
 127.0.0.1:6379> append name BB
 "chenlinBB"
 
- 计数 - 整数递增 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- # 使用规则 
 * 如果key不存在,则初始值为0,incr之后其值为1
 * 如果value非整型(如hello),则执行失败并返回错误信息。
 * 步长increment为整数,当为负数时效果等于递减
 # 对指定的"key"的"value"递增,递增步长默认1
 127.0.0.1:6379> INCR num
 1
 127.0.0.1:6379> INCR num
 2
 # 对指定的"key"的"value"递增,并指定递增步长
 127.0.0.1:6379> incrby num 2
 4
 127.0.0.1:6379> incrby num 2
 6
 # 对指定的"key"的"value"递增,并指定递增步长
 127.0.0.1:6379> incrbyfloat num 0.2
 0.4
 127.0.0.1:6379> incrbyfloat num 0.2
 0.6
- 小数递增 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # 使用规则 
 * 如果key不存在,则初始值为0,incr之后其值为1
 * 如果value非整型(如hello),则执行失败并返回错误信息。
 * 步长increment为小数,当为负数时效果等于递减
 # 对指定的"key"的"value"递增,并指定递增步长
 127.0.0.1:6379> incrbyfloat num 0.2
 0.4
 127.0.0.1:6379> incrbyfloat num 0.2
 0.6
- 整数递减 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- # 使用规则 
 * 如果key不存在,则初始值为0,incr之后其值为1
 * 如果value非整型(如hello),则执行失败并返回错误信息。
 * 步长increment为整数,当为负数时效果等于递减
 # 对指定的"key"的"value"递减,递减步长默认1
 127.0.0.1:6379> DECR num
 1
 127.0.0.1:6379> DECR num
 0
 # 对指定的"key"的"value"递减,并指定递减步长
 127.0.0.1:6379> decrby num 2
 8
 127.0.0.1:6379> decrby num 2
 6
 
 
- 改- 修改”key”和”value” - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # 将"key"的值(将"cl"改成"chenlin") 
 127.0.0.1:6379> set name chenlin
 OK
 # 使用getset命令修改数据
 ## 等同于"get"+"set",先执行"get",再执行"set"
 127.0.0.1:6379> GETSET name chenlin
 "cl"
 127.0.0.1:6379> get name
 "chenlin"
- 修改生存时间 - 1 
 2
 3
 4
 5
 6
 7- # 修改生存时间(将指定key的生存时间修改为"200") 
 127.0.0.1:6379> EXPIRE cl 200
 (integer) 1
 # 取消生存时间(将指定key的生存时间取消)
 127.0.0.1:6379> PERSIST jh
 (integer) 1
 
- 查- 查看”key”和”value”值 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- # 查看所有的数据(注意!不要轻易使用,如想查看数据,先查看数据量DBSIZE) 
 127.0.0.1:6379> keys *
 1) "name"
 # 查看数据量
 127.0.0.1:6379> DBSIZE
 (integer) 1
 # 查看"key"的值"value"
 127.0.0.1:6379> get name
 "cl"
 # 批量查看"key"的值"value"
 127.0.0.1:6379> mget k1 k2 k3
 1) "a"
 2) "b"
 3) "c"
 # 匹配key(键)cl
 127.0.0.1:6379> keys *cl
 1) "cl"
 # 随机返回一个key
 127.0.0.1:6379> RANDOMKEY
 "cl2"
 # 使用setrange在第"num"个字符处更新数据(从0开始算起)
 # 从指定的字符范围截取字符串(从0开始算起)
 getrange key start end
 127.0.0.1:6379> GETRANGE name 1 4
 "henl"
- 查看生存时间 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- # 以秒为单位查看key生存时间倒计时 
 ## "-1"=未设置生存时间,永不过期
 ## "-2"=生存时间已到期
 127.0.0.1:6379> TTL cl
 (integer) 16
 # 以毫秒为单位查看key生存时间倒计时
 ## "-1"=未设置生存时间,永不过期
 ## "-2"=生存时间已到期
 127.0.0.1:6379> PTTL cl
 (integer) 12199
- 查看”key”,”value”属性 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- # 查看key是否存在(存在:1 不存在:0) 
 127.0.0.1:6379> EXISTS k1
 (integer) 1
 127.0.0.1:6379> EXISTS k2
 (integer) 0
 # 查看指定key数据类型
 127.0.0.1:6379> TYPE cl
 string
 # 查看字符的长度
 127.0.0.1:6379> strlen name
 (integer) 2
 
Redis数据结构之哈希(Hash)
数据结构
Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似于python中的dict和java中的map集合。
- 应用场景:- 存储部分变更的数据,如用户信息,商品信息等。
- 最接近表结构的一种类型。
 
- 数据结构- Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
 
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:
- 方法一 
- 每次修改用户的某个属性需要,先反序列化改好后再序列化回去。开销较大。
 
- 方法二 
- 用户ID数据冗余
 
- Hash方案 
- 通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题
 
查看命令帮助
| 1 | 127.0.0.1:6379> help @hash | 
String数据结构中键(key)操作命令
- 增- 增加数据 - 语法格式 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # 语法格式 
 HSET key field value [field value ...]
 HSETNX key field value
 * NX:当数据库中key不存在时,可以将key-value添加数据库
 # 增加数据的命令有以下几个:
 * hset :标准命令,"key"不存在时创建,已存在则更新。
 * hmset :批量创建"key",等同于"hset"
 * hsetnx :单个创建,"hash表"或"key"不存在则创建,已存在则忽略。
- 基础用法 - 1 
 2
 3
 4
 5
 6
 7- # 增加hash类型的单个field或增加多个field 
 127.0.0.1:6379> hset test id 1 name cl company 上海
 (integer) 3
 # 单个创建,"hash表"或"key"不存在则创建,已存在则忽略。
 127.0.0.1:6379> HSETNX test id 1
 (integer) 0
 
- 计数 - hincrby - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- # hincrby可以对hash对象的指定的field的value做递增操作 
 # 语法格式
 HINCRBY key field increment
 * 如果key不存在,则初始值为0,incr之后其值为1
 * 对hash对象的指定的field的value做递增操作
 * value必须是整型,否则执行失败并返回错误信息。
 * 步长increment必须是整数,当increment为负数时为递减操作
 # 示例
 127.0.0.1:6379> HINCRBY test id 10
 11
- hincrbyfloat - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- # hincrbyfloat可以对hash对象的指定的field的value做递增操作 
 # 语法格式
 HINCRBYFLOAT key field increment
 * 如果key不存在,则初始值为0,incr之后其值为1
 * 对hash对象的指定的field的value做递增操作
 * value必须是数字类型,否则执行失败并返回错误信息。
 * 步长increment必须是整数或浮点数,当increment为负数时为递减操作
 # 示例
 127.0.0.1:6379> HINCRBYFLOAT test id 10.9
 21.9
 
- 过期策略(类似于生存时间) - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- # hash类型可以使用全局函数expire做过期策略。 
 # 语法格式
 expire key seconds
 # 示例
 127.0.0.1:6379> EXPIRE test 1000
 1
 127.0.0.1:6379> ttl test
 993
 
- 删- 基础用法 - 1 
 2
 3
 4
 5
 6
 7
 8- # 使用hdel命令删除hash类型的value中的fields,可批量或单个删除 
 # 语法格式
 HDEL key field1 [field2 ...]
 # 示例
 127.0.0.1:6379> HDEL test name
 1
 
- 改- 基础用法 - 1 
 2
 3
 4
 5
 6
 7
 8- # 修改hash类型中指定的field的值 
 # 语法格式
 HSET key field value [field value ...]
 # 示例
 127.0.0.1:6379> HSET test name cl
 0
 
- 查- 查询”field”或”value”值 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29- # 查询指定hash类型的field对应的值 
 127.0.0.1:6379> Hget test name
 cl
 # 查询指定hash类型的多个field对应的值
 127.0.0.1:6379> hmget test name company
 1) "cl"
 2) "上海"
 # 查询指定hash类型对象的全部field和对应的value值
 127.0.0.1:6379> HGETALL test
 1) "id"
 2) "1"
 3) "name"
 4) "chenlin"
 5) "company"
 6) "上海"
 # 查询指定hash类型对象的全部field
 127.0.0.1:6379> HKEYS test
 1) "id"
 2) "name"
 3) "company"
 # 查询指定hash类型对象的全部field的values值
 127.0.0.1:6379> HVALS test
 1) "1"
 2) "chenlin"
 3) "上海"
- 查询”field”或”value”属性 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- # 查看hash类型的key中指定的field是否存在(存在:1 不存在:0) 
 127.0.0.1:6379> HEXISTS test name
 1
 # 查询hash类型中field的数量
 127.0.0.1:6379> HLEN test
 3
 # 查询hash类型中指定filed对应的value的字符长度
 127.0.0.1:6379> HSTRLEN test name
 7
 
Redis数据结构之列表(List)
单键多值
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

数据结构
List的数据结构为快速链表quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
查看命令帮助
| 1 | help @list | 
操作命令
- 增- 增加元素 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37- # 从左边插入元素,从左边依次追加进栈,先进后出,后进先出 
 127.0.0.1:6379> LPUSH name xxx yyy
 (integer) 2
 127.0.0.1:6379> LPUSH name zzz
 (integer) 3
 127.0.0.1:6379> LRANGE name 0 -1
 1) "zzz"
 2) "yyy"
 3) "xxx"
 # 从右边插入元素,从右边依次追加进队列,先进先出,后进后出。
 127.0.0.1:6379> rpush name xxx yyy
 (integer) 2
 127.0.0.1:6379> rpush name zzz
 (integer) 3
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "yyy"
 3) "zzz"
 # 从左边追加元素,只有list存在时才会执行
 127.0.0.1:6379> LPUSHX name cl
 (integer) 4
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "cl"
 2) "xxx"
 3) "yyy"
 4) "zzz"
 # 从右边追加元素,只有list存在时才会执行
 127.0.0.1:6379> LPUSHX name cl
 (integer) 4
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "xxx"
 2) "yyy"
 3) "zzz"
 4) "cl"
- 插入元素 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- # 从list中指定的元素的前/后 插入一个新元素 
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "yyy"
 3) "zzz"
 # 在某个KEY值之前插入一个值
 127.0.0.1:6379> LINSERT name before zzz cl
 (integer) 4
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "yyy"
 3) "cl"
 4) "zzz"
 # 在某个KEY值后面添加一个值
 127.0.0.1:6379> LINSERT name after xxx chenlin
 (integer) 5
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "chenlin"
 3) "yyy"
 4) "cl"
 5) "zzz"
- 消费和消费追加 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56- # 从左边消费列表中的元素,消费完之后从列表中删除。 
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "19"
 2) "1616"
 3) "1615"
 4) "jh"
 5) "python"
 6) "linux"
 127.0.0.1:6379> LPOP mylist
 "19"
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "1616"
 2) "1615"
 3) "jh"
 4) "python"
 5) "linux"
 # 从右边消费列表中的元素,消费完之后从列表中删除。
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "1616"
 2) "1615"
 3) "jh"
 4) "python"
 5) "linux"
 127.0.0.1:6379> RPOP mylist
 "linux"
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "1616"
 2) "1615"
 3) "jh"
 4) "python"
 # 消费列表A的最右边的元素返回,然后追加到列表B的最左边。
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "1616"
 2) "1615"
 3) "jh"
 4) "python"
 127.0.0.1:6379> RPOPLPUSH mylist mylist
 "python"
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "python"
 2) "1616"
 3) "1615"
 4) "jh"
 # 从列表中左侧查询元素,返回列表的key和左侧第一个元素,若所有查询的列表中都没有元素,则会阻塞等待至设置的timeout秒之后返回空,若在这期间,这些列表新增了元素,则会立刻消费并返回该元素。
 127.0.0.1:6379> BLPOP mylist 10
 1) "mylist"
 2) "1616"
 127.0.0.1:6379> BLPOP mylist 10
 1) "mylist"
 2) "1615"
 127.0.0.1:6379> BLPOP mylist 10
 1) "mylist"
 2) "jh"
 
- 删- 删除数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25- # 从列表左侧,删除指定"个数"的"值" 
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "chenlin"
 3) "yyy"
 4) "cl"
 5) "zzz"
 127.0.0.1:6379> LREM name 1 cl
 (integer) 1
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "chenlin"
 3) "yyy"
 4) "zzz"
 # 从列表左侧,删除指定范围之外的数据
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "chenlin"
 3) "yyy"
 127.0.0.1:6379> LTRIM name 0 1
 OK
 127.0.0.1:6379> LRANGE name 0 -1
 1) "xxx"
 2) "chenlin"
 
- 改- 修改元素 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- # 修改元素内容(将左边第3个元素修改为19) 
 127.0.0.1:6379> LSET mylist 2 19
 OK
 127.0.0.1:6379> LRANGE mylist 0 -1
 1) "Shanghai7"
 2) "shanghai"
 3) "19"
 4) "1616"
 5) "1615"
 6) "jh"
 7) "python"
 8) "linux"
 
- 查- 查询数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- # 查看列表中元素的个数 
 127.0.0.1:6379> LLEN name
 (integer) 4
 # 根据起止下标范围查询列表元素
 ## 查询全部元素
 127.0.0.1:6379> lrange mylist 0 -1
 1) "19"
 2) "1616"
 3) "1615"
 4) "jh"
 5) "python"
 6) "linux"
 ## 查询最右边的元素
 127.0.0.1:6379> lrange mylist -1 -1
 1) "linux"
 # 根据指定的index下标查看列表中的元素
 127.0.0.1:6379> LINDEX mylist 3
 "jh"
 
Redis数据结构之无序集合(Set)
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的复杂度都是O(1)。一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变。集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
数据结构
Set数据结构是dict字典,字典是用哈希表实现的。
Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。
查看帮助命令
| 1 | # 使用Redis命令手册查看 | 
操作命令
- 增 - 增加数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- # 给集合内新增成员,若集合不存在则创建集合并新增成员。 
 SADD key member [member ...]
 # 增加一条member
 127.0.0.1:6379> SADD fan 1
 (integer) 1
 127.0.0.1:6379> SMEMBERS fan
 1) "1"
 # 增加多条member
 127.0.0.1:6379> SADD fan 2 3 4 5
 (integer) 4
 127.0.0.1:6379> SMEMBERS fan
 1) "1"
 2) "2"
 3) "3"
 4) "4"
 5) "5"
 
- 删 - 删除数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- # 从集合中删除指定的成员,返回删除的个数。 
 SREM key member [member ...]
 # 示例
 127.0.0.1:6379> SREM myset 2 4
 (integer) 2
 127.0.0.1:6379> SMEMBERS myset
 1) "1"
 2) "3"
 
- 改 - 修改数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- #1.移动数据 
 SMOVE source destination member
 #2.示例
 127.0.0.1:6379> SADD myset1 1 2 3 4 5
 (integer) 5
 127.0.0.1:6379> SADD myset2 one two three
 (integer) 3
 127.0.0.1:6379> SMOVE myset1 myset2 4
 (integer) 1
 127.0.0.1:6379> SMEMBERS myset1
 1) "1"
 2) "2"
 3) "3"
 4) "5"
 127.0.0.1:6379> SMEMBERS myset2
 1) "three"
 2) "two"
 3) "4"
 4) "one"
 
- 查 - 查看数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41- # 查看集合中所有的成员 
 127.0.0.1:6379> SMEMBERS myset1
 1) "1"
 2) "2"
 3) "3"
 4) "5"
 # 返回集合中成员的个数
 127.0.0.1:6379> SCARD myset1
 (integer) 4
 # 从集合中随机返回指定个数的成员
 127.0.0.1:6379> SRANDMEMBER myset1 2
 1) "3"
 2) "2"
 127.0.0.1:6379> SRANDMEMBER myset1 2
 1) "5"
 2) "3"
 #4.判断对象是否是集合中的成员,1表示true,0表示false
 SISMEMBER key member
 127.0.0.1:6379> SISMEMBER myset1 6
 (integer) 0
 127.0.0.1:6379> SISMEMBER myset1 2
 (integer) 1
 #5.随机返回一个成员,从集合中随机弹出一个成员,返回该成员并从集合中删除该成员。
 SPOP key
 127.0.0.1:6379> SPOP myset2
 "one"
 127.0.0.1:6379> SPOP myset2
 "two"
 127.0.0.1:6379> SPOP myset2
 "three"
 127.0.0.1:6379> SMEMBERS myset2
 1) "4"
- 集合 - 交集 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- #1.取多个集合的交集,返回这些集合中共同拥有的成员。 
 SINTER key [key ...]
 127.0.0.1:6379> sadd myseta 1 2 3 4 5
 (integer) 5
 127.0.0.1:6379> sadd mysetb 4 5 6 7 8
 (integer) 5
 127.0.0.1:6379> sadd mysetc 5 6 7 8 9
 (integer) 5
 127.0.0.1:6379> SINTER myseta mysetb mysetc
 1) "5"
 
 #2.将多个集合的交集的结果保存为一个新的集合destination,返回新集合的成员个数。
 SINTERSTORE destination key [key ...]
 
 127.0.0.1:6379> SINTERSTORE mysetc mysetb myseta
 (integer) 2
 
 127.0.0.1:6379> SMEMBERS mysetc
 1) "4"
 2) "5"
- 并集 - 1 
 2
 3- #1.取多个集合的并集,相同的成员会被去重。 
 SUNION key [key ...]
 - 127.0.0.1:6379> SMEMBERS mysetb - “4”
- “5”
- “6”
- “7”
- “8”
 - 127.0.0.1:6379> SMEMBERS myseta - “1”
- “2”
- “3”
- “4”
- “5”
 - 127.0.0.1:6379> SUNION myseta mysetb - “1”
- “2”
- “3”
- “4”
- “5”
- “6”
- “7”
- “8”
 - #2.将多个集合的并集的结果保存为一个新的集合 
 SUNIONSTORE destination key [key …]- 127.0.0.1:6379> SUNIONSTORE mysetc myseta mysetb 
 (integer) 8
 127.0.0.1:6379> SMEMBERS mysetc- “1”
- “2”
- “3”
- “4”
- “5”
- “6”
- “7”
- “8”1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 - 差集
 ```bash
 # 取多个集合的差集,以最左边的为主集合,返回左集合中有而其他集合没有的成员。
 127.0.0.1:6379> SDIFF myseta mysetb
 1) "1"
 2) "2"
 3) "3"
 #将多个集合的差集的结果保存为一个新的集合 ,返回新集合的成员个数 。
 SDIFFSTORE destination key [key ...]
 
 127.0.0.1:6379> SDIFFSTORE mysetc myseta mysetb
 (integer) 3
 127.0.0.1:6379> SMEMBERS mysetc
 1) "1"
 2) "2"
 3) "3"
 
 
模拟发朋友圈
| 1 | 127.0.0.1:6379> lpush wechat 'zhouyi' | 
Redis数据结构之有序集合Zset(sorted set)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
数据结构
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
- zset底层使用了两个数据结构:- hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
- 跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
 
跳跃表(跳表)
- 简介 - 有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。Redis采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。
 
- 实例 - 对比有序链表和跳跃表,从链表中查询出51 - 有序链表 - 要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。  
 
- 跳跃表 - 从第2层开始,1节点比51节点小,向后比较。 
- 21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层 
- 在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下 
- 在第0层,51节点为要查找的节点,节点被找到,共查找4次。 
- 从此可以看出跳跃表比有序链表效率要高  
 
 
 
查看命令帮助
| 1 | help @sorted_set | 
操作命令
- 增 - 增加数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- # 往有序集合中新增成员,需要指定该成员的分数,分数可以是整形或浮点型,当分数相同时候,索引下标按照字典排序。 
 # 语法格式
 ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
 # 增加一条数据
 127.0.0.1:6379> ZADD myzset 1 jh
 1
 # 增加多条数据
 127.0.0.1:6379> ZADD myzset 2 shanghai 3 beijing
 2
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 shanghai
 beijing
 
- 删 - 删除数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- #1.移除指定的成员 
 ZREM key member [member ...]
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 shanghai
 beijing
 127.0.0.1:6379> ZREM myzset shanghai
 1
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 beijing
 
- 改 - 修改数据 - 1 
 
- 查 - 查看数据 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51- # 获取有序集合的成员数 
 ZCARD key
 127.0.0.1:6379> ZCARD myzset
 3
 # 获取指定分数区间内的成员数
 从有序集合内获取指定分数区间内的成员数。
 ZCOUNT key min max
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 shanghai
 beijing
 127.0.0.1:6379> ZCOUNT myzset 1 2
 2
 #3.字典排序
 根据字典排序返回min ,max之间的数据量.
 ZLEXCOUNT key min max
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 shanghai
 beijing
 127.0.0.1:6379> ZLEXCOUNT myzset [sh [zzz
 0
 #4.获取成员的分数值
 返回有序集中,成员的分数值,不存在的成员返回空。
 ZSCORE key member
 127.0.0.1:6379> ZRANGE myzset 0 -1
 jh
 shanghai
 beijing
 127.0.0.1:6379> ZSCORE myzset shanghai
 2
 #5.迭代有序集合中的元素(包括元素成员和元素分值)
 127.0.0.1:6379> ZSCAN myzset 0 match "sh*"
 0
 shanghai
 2
 127.0.0.1:6379> ZSCAN myzset 0 match "j*"
 0
 jh
 1
 




