Redis [1]

Redis 特征和基本数据类型

Posted by ZYT on November 16, 2018

Redis

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Redis 安装

Mac

$ brew install redis

$ brew services start redis

Linux

# ubuntu
$ sudo apt-get install redis-server

$ redis-server

# centos
$ sudo yum install epel-release

$ sudo yum install redis -y

$ sudo systemctl start redis.service && systemctl enable redis.service

Redis 的特点

  1. 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速
  2. 数据结构简单,对数据操作也简单
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
  4. Redis 是线程安全的(因为只有一个线程),其所有操作都是原子的,不会因并发产生数据异常
  5. 使用 I/O 多路复用模型
  6. 使用高耗时的 Redis 命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢

Redis 的数据类型

Redis 采用 Key-Value 型的基本数据结构,任何二进制序列都可以作为 Redis 的 Key 使用。Redis 的 key二进制安全 的,这意味着你可以用任意二进制序列作为 key 值,包括空字符串。

key 需要注意的事项:

  • 使用太长的 key 值并不是 a good idea。太长的 key 值不仅消耗内存,而且在数据集中查找的成本也很高
  • 太短的 key 值也不是 a good idea,缺失可读性
  • 最好使用统一的规范来设计 key,比如 object-type:id
  • Redis 允许的最大 key size 是 512 MB ( String 和 Bitmaps 的长度限制也是 512 MB

1. Binary-safe strings

# 为一个 key 赋值
> set mykey somevalue
  OK

 -------- mykey --------
|        somevalue      |
 -----------------------
          图示

# 获取某个 key 对应的值
> get mykey
  "somevalue"

# 如果 key 值存在,直接执行 set 操作会替换掉对应的 value 值
# 只对不存在的 key 赋值
> set mykey newval nx
  (nil)
# 只对已存在的 key 赋值
> set mykey newval xx
  OK

# 将 value 值作为整型或浮点型数字使用
> set counter 100
# 自增 1
> incr counter
  101
# 自减 1
> decr counter
  100
# 按指定的整型数值自增
> incrby counter 50
  150
# 按指定的整型数值自减
> decrby counter 50
  100

# 为多个 key 赋值
> mset a 10 b 20 c 30
  OK

# 获取多个 key 对应的值
> mget a b c
1) "10"
2) "20"
3) "30"

# 查询和修改 key
# exists: key 是否存在
# del: 删除 key
# type: key 的类型
> set mykey hello
  OK
> exists mykey
  1
> type mykey
  string
> del mykey
  1
> exists mykey
  0
> type mykey
  none

# 过期时间
> set key some-value
# 设置过期时间,默认单位为秒
> expire key 5
  1
# 或者上面的过程可以一步完成
> set key some-value ex 5
  OK
# 查看剩余生存时间
> ttl key
  4

2. Lists

# 添加一个元素到列表的头部(左边)或者尾部(右边)。
# 列表的尾部
> rpush mylist A
  1
> rpush mylist B
  2
# 列表的头部
> lpush mylist first
  3

 -------- mylist--------
|          first        |
|            A          |
|            B          |
 -----------------------
           图示

# 提取列表中的元素
> lrange mylist 0 -1
1) "first"
2) "A"
3) "B"

# 添加多个元素
> rpush mylist C D E
# 移除元素
> rpop mylist

# 修剪列表
# ltrim 保留指定范围的指定元素
> rpush mylist 1 2 3 4 5
  5
> ltrim mylist 0 2
  OK
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"

# list 的阻塞操作
# 对于用 list 实现一个 producer / consumer 的问题,可以用 lpush / rpop 或者 rpush / lpop
# 实现,但是会对 Redis 增加过多无用的请求和延迟,不是好的解决方案。
# brpop / blpop 实现阻塞操作
# 例如:等待队列添加新的元素,如果 5 秒内没有新的元素返回 null
> brpop tasks 5

## 数组长度
> llen mylist

3. Hashes

# 赋值
> hset hash_key1 sub_key1 value1
  1

 ---------- hash_key1 ----------
|       sub_key1    value1      |
|       sub_key2    value2      |
|       sub_key3    value3      |
 -------------------------------
                图示

# 获取值
> hget hash_key1 sub_key1
  "value1"

# 操作多个值
> hmset user:1000 username antirez birthyear 1977 verified 1
  OK
> hmget user:1000 username birthyear
1) "antirez"
2) "1977"

# 获取散列包含的所有键值对
> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

# 获取不存在的键值
> hmget user:1000 no-such-field
  (nil)

# 对 hash 中的值进行自增操作
> hincrby user:1000 birthyear 10
  1987

4. Sets

# 添加元素
> sadd myset 1 2 3

 -------- myset --------
|           1           |
|           2           |
|           3           |
 -----------------------
           图示

# 移除元素
> srem myset 1
# 查看集合成员
> smembers myset
1. 3
2. 2

# 元素是否在集合中
> sismember myset 3
# 集合包含的元素的数量
> scard myset
# 随机移除集合元素
> spop myset

# 交集
> sinter myset1 myset2
# 将交集存储在 dest-key 中
> sinter dest-key myset1 myset2
# 差集
> sdiff myset1 myset2
# 将差集存储在 dest-key 中
> sdiff dest-key myset1 myset2
# 并集
> sunion myset1 myset2
# 将并集存储在 dest-key 中
> sunion dest-key myset1 myset2

5. Sorted sets

# 添加成员
> zadd key-name score member

 ---------- key-name ----------
|       member1    score1      |
|       member2    score2      |
|       member3    score3      |
 ------------------------------
                图示

# 移除成员
> zrem key-name member

# 成员数量
> zcard key-name
# 将 member 的分值加上 increment
> zincrby key-name increment member
# 分值介于 min 和 max 之间的成员数量
> zcount key-name min max
# 成员在有序集合中的排名
> zrank key-name member
# 成员的分值
> zscore key-name member

# 有序集合中排名介于 start 和 stop 之间的成员
> zrange key-name start stop
# 有序集合中排名介于 start 和 stop 之间的成员,从大到小排序
> zrevrange key-name start stop

# 返回指定成员区间内的成员,按成员字典正序排序,
# min 和 max 可以用 [值 或者 - 表示最小值 + 表示最大值
> zrangebylex key-name min max

Redis 5.0 添加的新功能:

# 移除有序集合中分值最大的 count 个元素
> ZPOPMAX key [count]

# 移除有序集合中分值最小的 count 个元素
> ZPOPMIN key [count]

# 上述连个命令的阻塞变种,用 timeout 指定命令的最长阻塞时间:
> BZPOPMAX key [key ...] timeout
> BZPOPMIN key [key ...] timeout

6. Bitmaps

# 面向字节操作,最大长度为 512 M,即最多 2^32 个字节
# 设置指定偏移量上的位,
> setbit key offset value
# 获取指定偏移量上的位
> getbit key offset

# 统计设置为 1 的位的数量,单位为字节,即 8 个位置
> bitcount key [start] [stop]

# 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上
> bitop [AND / OR / XOR / NOT] destkey key [key ...]

# 寻找指定值的位置
> bitpos key value

7. HyperLogLogs

# 一种被用于计算唯一事物的概率数据结构
# 添加元素
> pfadd key value [value ...]

# 唯一元素的近似数量
> pfcount key

# 合并多个 HLL,并存储在 destkey 中
> pfmerge destkey key [key ...]