一、Redis核心数据结构

1,145 阅读9分钟

一、redis简介


1、nosql简介

  • NoSQL泛指非关系型的数据库,是不同于传统的关系数据库的数据库管理系统的统称。其两者最重要的区别是NoSQL不使用SQL作为查询语言。
  • NoSQL数据存储可以不需要固定的表格模式。NoSQL是基于键值对的,可以想象成表中的主键和值的对应关系。
  • 常用NoSQL:redis、memcached、mongodb、guava(loadingCache)

2、redis简介

Redis是一个用C语言编写的开源的高性能key-value分布式内存数据结构存储系统并支持持久化的nosql数据库。它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(list)、集合(sets)、有序集合 (sorted set)等。

3、redis特点

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
  • Redis支持数据的备份,即master-slave模式的数据备份

二、linux下安装redis


下载地址1:redis.io/download

下载地址2:www.redis.cn/download.ht…

1、命令行下载并安装

$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar -zxvf redis-5.0.5.tar.gz -C  /usr/local/
$ cd redis-5.0.5
$ make
$ make install

2、如果make安装失败,则提示缺少gcc环境

$ yum install gcc-c++
$ make distclean
$ make
$ make install    

3、启动客户端

# 启动服务端
$ ./src/redis-server

# 启动服务端并指定配置文件
$ ./src/redis-server ./redis.conf

4、验证启动是否成功

$ ps ‐ef | grep redis

5、启动客户端

# 启动客户端
$ ./src/redis-cli

# 启动客户端并指定端口号
$ ./src/redis-cli -p 6379

6、退出客户端

$ quit

7、退出redis服务

$ kill -9 进程号

三、redis核心数据结构


redis提供五种数据类型:string、hash、list、set、zset(sorted set)

1、string数据类型

  • String类型是redis最基本的数据类型,一个key对应一个value
  • String类型是二进制安全的,redis的String可以包含任何数据,比如jpg图片或者序列化的对象
  • String类型是redis最基本的数据类型,一个redis中字符串value最多可以是512M

string常用操作:

set key value:存入字符串key对应的value值

mset key1 value1 key2 value2 ...:批量存入字符串key对应的value值

setnx key value:当字符串key不存在时才存入其对应的值

get key:获取字符串key对应的值

mget key1 key2 ...:批量获取字符串key对应的值

del key1 key2 ...:批量删除字符串key对应的值

expire key seconds:设置字符串key对应的值的过期时间(秒)

原子加减:

incr key:将key中储存的数字值加1

decr key:将key中储存的数字值减1

incrby key increment:将key中储存的数字值加increment

decrby key decrement:将key中储存的数字值减increment

应用场景:

  • 单值缓存
  • 对象缓存
  • 分布式锁
  • 计数器
  • web集群session共享
  • 分布式系统全局序列号

二、hash数据类型

  • Hash是一个键值对集合
  • Hash是一个String类型的field和value的映射表,Hash特别适合于存储对象
  • 类似于java里面的Map<String,Object>

hash常用操作:

hset key field value:设置hash的key对应的field字段和value值

hsetnx key field value:hash的key对应的field字段不存在才设置value值

hget key field:获取hash的key对应的field字段的值

hmset key field1 value1 field2 value2 ...:批量设置hash的key对应的field字段和value值

hmget key field1 field2 ...:批量获取hash的key对应的field字段的值

hdel key field1 field2 ...:批量删除hash的key对应的field字段的值

hlen key:返回hash的key中字段的数量

hgetall key:返回hash的key中所有的字段和字段值

hincrby key field increment:给hash的key中的field字段对应的值加上增量increment

应用场景:

  • 对象缓存
  • 电商购物车

3、list常用操作

  • redis列表是最简单的字符串列表,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际是个链表,可以包含重复的元素

list常用操作:

lpush key value1 value2 ...:从列表key的左端插入一个或多个值

rpush key value1 value2 ...:从列表key的右端插入一个或多个值

lpop key:从列表key左侧弹出一个值

rpop key:从列表key右侧弹出一个值

lrange key start stop:遍历列表key左侧指定区间内的元素

blpop key1 key2 ... timeout:从列表key表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,则会一直阻塞等待

brpop key1 key2 ... timeout:从列表key表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,则会一直阻塞等待

常用数据结构:

Stack(栈) = LPUSH + LPOP(First In Last Out)
Queue(队列) = LPUSH + RPOP
Blocking MQ(阻塞队列) = LPUSH + BRPOP

应用场景:

  • 微博和微信消息流

4、set数据类型

  • redis的Set是String类型的无序集合,它是通过HashTable来实现的

set常用操作:

sadd key member1 member2 ...:向集合key中存入member元素

srem key member1 member2 ...:从集合key中删除元素member元素

smembers key:获取集合key中的所有元素

scard key:获取有序集合key中元素的数量

sismember key member:判断member元素是否在集合key中

srandmember key count:从集合key中选出count个元素,元素不从key中删除

spop key count:从集合key中选出count个元素,元素从key中删除

set运算操作:

sinter key1 key2 ...:交集运算

sinterstore destination key1 key2 ...:将交集结果存入新集合destination中

sunion key1 key2 ...:并集运算

sunionstore destination key1 key2 ...:将并集结果存入新集合destination中

sdiff key1 key2 ...:差集运算

sdiffstore destination key1 key2 ...:将差集结果存入新集合destination中

应用场景:

  • 微信抽奖小程序
  • 微信微博点赞、收藏、标签
  • 集合操作实现微博微信关注模型
  • 集合操作实现电商商品筛选

5、zset(sorted set)数据类型

  • zset是set的一个升级版本,和Set一样也是String类型元素的集合,且不允许有重复的元素
  • 不同的是每个元素都会关联一个double类型的分数
  • redis正是通过分数来为集合中的成员进行从小到大的排序,Zset的成员是唯一的,但分数(score)却可以重复

zset常用操作:

zadd key score1 member1 score2 member2 ...:向有序集合key中加入一个带score分数值的member元素

zrem key member1 member2 ...:从有序集合key中删除member元素

zscore key member:获取有序集合key中元素member的分数值

zincrby key increment member:增加有序集合key中member元素的分数值(增加的分数值大小为increment)

zcard key:获取有序集合key中元素的数量

zrange key start stop:正序获取有序集合key中从start下表到stop下标的元素

zrevrange key start stop:倒序获取有序集合key中从start下表到stop下标的元素

zset集合操作:

zunionstore destination numkeys key1 key2 ...:并集计算

zinterstore destination numkeys key1 key2:交集计算

应用场景:

  • zset集合操作实现排行榜

6、redis更多应用场景

  • 微博、微信、默默<附近的人>
  • 微信<摇一摇><抢红包>
  • 滴滴打车、摩拜单车<附近的车>
  • 美团和饿了么<附近的餐馆>
  • 搜索自动补全
  • 布隆过滤器
  • ... ...

四、redis核心原理


1、redis的单线程和高性能

redis单线程为什么还能这么快?

因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为Redis是单线程,所以要小心使用Redis指令,对于那些耗时的指令(比如keys *),一定要谨慎使用,一不小心就可能会导致Redis卡顿。

redis单线程如何处理那么多的并发客户端连接?

Redis的IO是多路复用的,redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到 文件事件分派器,事件分派器将事件分发给事件处理器

查看redis支持的最大连接数,在redis.conf文件中可修改,默认配置如下:

# maxclients 10000

2、其他高级命令

keys全量遍历键:

用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用

scan渐进式遍历键:

scan cursor match pattern count count]

scan命令提供了三个参数,第一个是cursor(整数值),第二个是key的正则模式,第三个是一次遍历的key的数量,并不是符合条件的结果数量。第一次遍历时,cursor值为0,然后将返回结果中第一个整数值作为下一次遍历的cursor,一直遍历到返回的cursor值为0时结束。

info:查看redis服务运行信息

分为9大块,每个块都有非常多的参数,这9个块分别是:

  1. Server 服务器运行的环境参数
  2. Clients 客户端相关信息
  3. Memory 服务器运行内存统计数据
  4. Persistence 持久化信息
  5. Stats 通用统计数据
  6. Replication 主从复制相关信息
  7. CPU CPU 使用情况
  8. Cluster 集群信息
  9. KeySpace 键值对统计数量信息
127.0.0.1:6379> info
# Server
redis_version:5.0.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:5ecb0246e42149d4
redis_mode:standalone
os:Linux 3.10.0-957.27.2.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:1974
run_id:763e43b749326a3ced814f36c0a847df8ab85370
tcp_port:6379
uptime_in_seconds:125801
uptime_in_days:1
hz:10
configured_hz:10
lru_clock:13884734
executable:/usr/local/redis-5.0.6/./src/redis-server
config_file:

# Clients
connected_clients:1
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0

# Memory
used_memory:854632
used_memory_human:834.60K
used_memory_rss:3821568
used_memory_rss_human:3.64M
used_memory_peak:4957272
used_memory_peak_human:4.73M
used_memory_peak_perc:17.24%
used_memory_overhead:842310
used_memory_startup:792312
used_memory_dataset:12322
used_memory_dataset_perc:19.77%
allocator_allocated:1258048
allocator_active:1507328
allocator_resident:7380992
total_system_memory:4142325760
total_system_memory_human:3.86G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.20
allocator_frag_bytes:249280
allocator_rss_ratio:4.90
allocator_rss_bytes:5873664
rss_overhead_ratio:0.52
rss_overhead_bytes:-3559424
mem_fragmentation_ratio:4.70
mem_fragmentation_bytes:3008896
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1574165776
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:151552
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:7
total_commands_processed:166
instantaneous_ops_per_sec:0
total_net_input_bytes:7635
total_net_output_bytes:84380
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:54
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:2
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:43
keyspace_misses:5
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:339
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:4df5e4af04a0670996de7170b1387111487b0899
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:80.226871
used_cpu_user:114.513057
used_cpu_sys_children:0.008760
used_cpu_user_children:0.007374

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=6,expires=0,avg_ttl=0