Redis 及其分布式应用场景

转自:

https://zhuanlan.zhihu.com/p/126344521

Redis概况

Redis(Remote Dictionary Server,即远程字典服务),是一个开源的(BSD 许可的)内存中的数据结构存储器,用作数据库、缓存和消息代理。它支持丰富的数据结构(如字符串、哈希、列表、集、带范围查询的排序集、位图、超日志、具有半径查询和流的地理空间索引)。Redis 具有内置复制、Lua 脚本、LRU eviction、事务和不同级别的磁盘持久性,并通过 Redis Sentinel 提供高可用性,并通过 Redis 群集自动分区。

从2010年3月15日起,Redis的开发工作由VMware主持;从2013年5月开始,Redis的开发由Pivotal赞助。

Redis 主要内容:

  • 性能:数据在内存中(避免了磁盘IO的成本),读写速度非常快,支持并发 10W QPS;
  • 进程、线程模型:单进程单线程,是线程安全的,采用 IO 多路复用机制模型(同步非阻塞)。
  • 丰富的数据结构:String字符串、Hash哈希映射、List列表、Set集合、ZSet带范围查询的排序集合、bitmap位图、hyperloglog超日志、具有半径查询和流的地理空间索引;
  • 数据持久化机制:可以将内存中数据保存在磁盘中,重启时加载;
  • 高可用集群架构:通过 Redis Sentinel 提供高可用性,并通过 Redis 群集自动分区。(主从复制、哨兵架构);
  • 分布式应用场景:用作缓存;可用作消息中间件,支持发布订阅;用作分布式锁(redis的并发竞争key机制)等等;

核心数据结构-操作命令-应用场景

#macos简单安装redis
brew install redis
#配置文件
vim /usr/local/etc/redis.conf
#启动服务
redis-server

#进入客户端
redis-cli -p 127.0.0.1 -p 6379
#后续执行操作命令即可
127.0.0.1:6379> set owner Yoland
OK
127.0.0.1:6379> get owner
"Yoland"
127.0.0.1:6379> exists owner
(integer) 1
127.0.0.1:6379> type onwer
String
127.0.0.1:6379> del owner
(integer) 1
127.0.0.1:6379> exists owner
(integer) 0

# 设置过期时间
127.0.0.1:6379> expire key timeout(单位为秒)
  • 实现分布式锁:

1.获取锁的时候,使用 setnx(SETNX key val:当且仅当 key 不存在时,set 一个 key 为 val 的字符串,返回 1;若 key 存在,则什么都不做,返回 0)加锁,锁的 value 值为一个随机生成的 UUID,在释放锁的时候进行判断。并使用 expire 命令为锁添加一个超时时间,超过该时间则自动释放锁。

2. 获取锁的时候调用 setnx,如果返回 0,则该锁正在被别人使用,返回 1 则成功获取 锁。 还设置一个获取的超时时间,若超过这个时间则放弃获取锁。

3. 释放锁的时候,通过 UUID 判断是不是该锁,若是该锁,则执行 delete 进行锁释放。

  • 事务操作

Redis事务可以一次执行多个命令,事务具有以下特征

  • 隔离操作:事务中的所有命令都会序列化、按顺序地执行,不会被其他命令打扰。
  • 原子操作:事务中的命令要么全部被执行,要么全部都不执行
  • 开启一个事务
multi
以后执行的所有命令,都在这个事务中执行的。

执行事务
1exec
  会将在multi和exec中的操作一并提交。

取消事务
1discard
  会将multi后的所有命令取消。

监视一个或者多个key
watch key...
  监视一个(或多个)key,如果在事务执行之前这个(或这些) key被其他命令所改动,那么事务将被打断。

取消所有key的监视
unwatch 
  • 发布/订阅操作
给某个频道发布消息
publish channel message
订阅某个频道的消息
subscribe channel 

 

key-String

String 是 Redis 最基本的类型,可以理解成与 Memcached 一模一样的类型;

  • 一个 Key 对应一个 Value, value是一个整体;
  • Value 可以是任何类型数据(因为String 类型是二进制安全的:意思是 String 类型可以包含任何数据,如:String、数字、 jpg 图片、序列化的对象);
  • Value最大能存储 512M;

操作命令:

#S听类型 对字符串的支持
> SET mykey somevalue
OK
> GET mykey
"somevalue"

#String类型 对数字的支持
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152

# 设置多数据
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
> mget a
1) "10"

应用场景:

  • 单值缓存;
SET key value
GET key
  • 对象缓存(json格式,但不如使用hash更灵活):
#使用String缓存对象
SET user:1 value(json格式数据)
GET user:1 
#使用Hash缓存对象
MSET user:1:name yuan user:1:age 18
MGET user:1:name user:1:age 

key-Hash

Hash是一个键值(key-value)的集合。

  • 一个key对应一个Hash(key-value entry 的集合);
  • 适合存储对象:

操作命令:HMSet、HGet、HGetAll、HLen、HDel、hincrby

//todo

应用场景:适合存储对象,对象的每个属性和值,可以用hash的key-value来存储;虽然对象也可以通过json存储到String值中,但是使用Hash更方便操作对象的某个属性;

 

key-List

  • List 列表是简单的字符串列表,按照插入顺序排序。
  • 数据结构:List 就是链表,可以用来当消息队列用。Redis 提供了 List 的 Push 和 Pop 操作,还提供了操作某一段的 API,可以直接查询或者删除某一段的元素。
  • 实现方式:Redis 的 List 的是实现是一个双向链表,既可以支持反向查找和遍历,更方便操作,不过带来了额外的内存开销。

操作命令:可以添加一个元素到列表的头部(左边)或者尾部(右边) 常用命令:插入lpush/rpush、查询lpop/rpop、范围查询lrange(获取列表片段)、阻塞查询BLPop/BRPop(list空时阻塞)、删除LDrop/RDrop等。

//todo

应用场景:List 应用场景非常多,也是 Redis 最重要的数据结构之一,比如 :

  • 微博、Twitter 的关注列表、粉丝列表都可以用 List 结构来实现。
  • 公众号、微博的新消息列表, 使用:LRange key start end;

 

key-Set

  • Set 是 String 类型的无序集合(集合即元素唯一)。Set 中的元素是无序的,而且是不重复的。
  • Set 是通过 hashtable 实现的;

操作命令:SADDSCARDSDIFFSDIFFSTORESINTERSINTERSTORESISMEMBERSMEMBERSSMOVESPOPSRANDMEMBERSREMSSCANSUNIONSUNIONSTORE

#添加集合中的成员
> sadd myset 1 2 3
(integer) 3
#查看集合中的成员
> smembers myset
1. 3
2. 1
3. 2
#成员是否属于集合
> sismember myset 3
(integer) 1
> sismember myset 30
(integer) 0
#集合操作
#交集
SINTER set1 set2
#并集 set1 + set2
SUNION set1 set2
#差集 set1-(set2+set3)
SDIFF set1 set2 set3

应用场景:Redis 的 Set 对外提供的功能和 List 一样是一个列表,特殊之处在于 Set 是自动去重的,而且 Set 提供了判断某个成员是否在一个 Set 集合中。

  • 微信抽奖小程序
redis> SADD myset one two three
(integer) 3
# 从集合中随机获取n个成员
redis> SRANDMEMBER myset
"two"
redis> SRANDMEMBER myset 2
1) "one"
2) "three"
redis> SRANDMEMBER myset -5
1) "two"
2) "three"
3) "two"
4) "three"
5) "one"

# 从集合中随机获取n个成员,同时将取出的成员从集合中删除
  • 微信/微博的点赞、收藏、标签,用:
SREM
SISMEMBER
SMEMBER
SCARD

  • 实现微博、微信的关注模型:
#共同关注(关注某明星的粉丝也关注的其他明星)

#我关注的人也关注的明星

#推荐关注/可能认识的人(我的好友关注了,而我没有关注的人)

key-ZSet

Zset 和 Set 一样是 String 类型元素的集合,且不允许重复的元素,但是它时排序的( Sorted Set 结构)。

  • 和 Set 相比,Sorted Set关联了一个 Double 类型权重的参数 Score,使得集合中的元素能够按照 Score 进行有序排列,Redis 正是通过分数来为集合中的成员进行从小到大的排序。
  • 实现方式:Redis Sorted Set 的内部使用 HashMap 和跳跃表(skipList)来保证数据的存储和有序,HashMap 里放的是成员到 Score 的映射。 而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 Score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

常用命令:zadd、zrange、zrem、zcard 等。

使用场景:ZSet 可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。

  • 排行榜/热度榜
  • 带优先级(权重)的消息队列

 

Redis高可用、分布式集群架构(千万级)

(待续)

SpringBoot 用 redis 作缓存

Spring Boot 使用的。一般有两种方式,一种是直接通过 RedisTemplate 来使用,另一种是使用 Spring Cache 集成 Redis(也就是注解的方式)。

(待续)

posted @ 2020-04-29 09:07  adaandy  阅读(1091)  评论(0编辑  收藏  举报