>  기사  >  데이터 베이스  >  Redis의 5가지 데이터 유형에 대해 이야기하고 이를 어떻게 적용할 수 있는지 살펴보겠습니다!

Redis의 5가지 데이터 유형에 대해 이야기하고 이를 어떻게 적용할 수 있는지 살펴보겠습니다!

青灯夜游
青灯夜游앞으로
2022-03-09 10:56:202788검색

이 글에서는 Redis의 5가지 데이터 유형을 이해하고, 이를 적용하는 방법을 알아보고, Redis의 실제 적용 시나리오를 소개하겠습니다. 모든 분들께 도움이 되기를 바랍니다.

Redis의 5가지 데이터 유형에 대해 이야기하고 이를 어떻게 적용할 수 있는지 살펴보겠습니다!

MySql+Memcached 아키텍처 문제

실제 MySQL은 액세스 속도를 높이기 위해 핫 데이터를 캐시에 로드하는 데 적합합니다. 그러나 비즈니스 데이터의 양이 계속 늘어나고, 방문 횟수도 계속 증가하면서 많은 문제에 직면하게 되었습니다:

  1. MySQL은 데이터베이스와 테이블을 계속해서 해체해야 하고, Memcached도 계속 확장해야 합니다. 확장 및 유지 관리 작업에는 많은 개발 시간이 소요됩니다.

 2. Memcached와 MySQL 데이터베이스 간의 데이터 일관성 문제.

  3. Memcached 데이터 적중률이 낮거나 머신이 다운된 경우 MySQL이 지원할 수 없는 DB에 직접 침투하는 경우가 많습니다.

 4. 기계실 간 캐시 동기화 문제.

 많은 NoSQL 꽃이 피고, 어떻게 선택해야 할까

최근 업계에는 다양한 NoSQL 제품이 많이 등장하고 있는데, 이들 제품을 어떻게 올바르게 사용하고 장점을 극대화할 수 있을지에 대해 깊이 연구해야 할 부분이다. 그리고 최종 분석에서 가장 중요한 것은 이러한 제품의 포지셔닝을 이해하고 각 제품의 장단점을 이해하며 실제 응용 프로그램에서 장점을 사용하고 단점을 피하는 것입니다. 일반적으로 이러한 NoSQL은 주로 문제를 해결하는 데 사용됩니다. 다음 문제

 1 .소량의 데이터 저장 공간, 고속 읽기 및 쓰기 액세스. 이러한 제품은 모든 데이터를 메모리에 유지하여 고속 액세스를 보장하는 동시에 데이터 랜딩 기능을 제공합니다. 실제로 이것이 Redis의 주요 적용 시나리오입니다. [관련 권장사항: Redis 동영상 튜토리얼]

  2. 대용량 데이터 저장, 분산 시스템 지원, 데이터 일관성 보장, 편리한 클러스터 노드 추가/삭제.

  3. 이와 관련하여 가장 대표적인 아이디어는 두 논문인 Dynamo와 Bigtable입니다. 전자는 완전히 센터리스 설계이며, 클러스터 정보는 가십을 통해 노드 간에 전송되고, 데이터는 최종 일관성을 보장합니다. 후자는 분산 잠금 서비스를 통해 강력한 일관성을 보장하는 중앙 집중식 솔루션 설계이며, 메모리 및 리두 로그는 다음과 같습니다. 먼저 쓴 다음 정기적으로 디스크에 압축 및 병합하여 임의 쓰기를 순차 쓰기로 최적화하여 쓰기 성능을 향상시킵니다.

 4.스키마 프리, 자동 샤딩 등 예를 들어, 일부 일반적인 문서 데이터베이스는 현재 스키마 프리를 지원하고, json 형식 데이터를 직접 저장하고, 자동 샤딩 및 mongodb와 같은 기타 기능을 지원합니다.适 Redis는 메모리 내 모든 데이터에 가장 적합합니다. Redis도 Persistency 기능을 제공하지만 실제로는 기존 Persistence와는 상대적으로 다른 점이 더 많은 것 같습니다. Memcached의 향상된 버전과 같으니 언제 Memcached를 사용해야 하고 언제 Redis를 사용해야 할까요?

단순히 Redis와 Memcached의 차이점을 비교해 보면 대부분의 사람들은 다음과 같은 의견을 갖게 될 것입니다.

1. Redis는 단순한 k/만 지원하는 것이 아닙니다. v 데이터를 입력할 뿐만 아니라 목록, 세트, ​​zset 및 해시와 같은 데이터 구조의 저장 공간도 제공합니다.

2. Redis는 데이터 백업, 즉 마스터-슬레이브 모드에서의 데이터 백업을 지원합니다.

3. Redis는 데이터 지속성을 지원합니다. 이를 통해 데이터를 디스크 메모리에 보관하고 다시 시작할 때 사용하기 위해 다시 로드할 수 있습니다.

  Redis의 내부 메모리 관리에서 이러한 다양한 데이터 유형이 어떻게 설명되는지 이해하세요.

  우선 Redis는 내부적으로 redisObject 객체를 사용하여 모든 키와 값을 나타냅니다. 위 그림에서 다음을 나타냅니다. 유형은 값 개체의 특정 데이터 유형을 나타내고 인코딩은 redis 내에서 다양한 데이터 유형의 저장 방법을 나타냅니다. 예: type=string은 값이 일반 문자열로 저장됨을 나타냅니다. 인코딩은 raw 또는 int일 수 있으며, int인 경우 숫자 유형에 따라 실제 문자열이 redis 내부에 저장되고 표현된다는 의미입니다. 물론 문자열 자체가 다음과 같은 숫자 값으로 표현될 수 있다는 전제가 있습니다. : "123" "456"과 같은 문자열.

 여기서는 vm 필드에 대해 특별한 설명이 필요합니다. Redis의 가상 메모리 기능이 활성화된 경우에만 이 필드가 실제로 메모리를 할당할 수 있습니다. 이 기능은 기본적으로 비활성화되어 있습니다. 위 그림에서 우리는 Redis가 모든 키/값 데이터를 표현하기 위해 redisObject를 사용한다는 것을 알 수 있습니다. 이는 메모리 낭비입니다. 물론 이러한 메모리 관리 비용은 주로 Redis의 다양한 데이터 유형에 대한 통합 관리 인터페이스를 제공하기 위한 것입니다. 실제 저자는 메모리 사용량을 최대한 절약하는 데 도움이 되는 다양한 방법도 제공합니다. 이에 대해서는 나중에 자세히 설명하겠습니다.

Redis는 5가지 데이터 유형

을 지원합니다: 문자열(string), 해시(hash), 목록(list), 집합(set) 및 zset(sorted set: ordered set).

 ① string은 Redis의 가장 기본적인 유형으로 Memcached와 완전히 동일한 유형으로 이해하면 됩니다. 하나의 키가 하나의 값에 해당합니다. 실제로 값은 문자열일 뿐만 아니라 숫자이기도 합니다. 문자열 유형은 바이너리 안전합니다. 이는 redis 문자열에 모든 데이터가 포함될 수 있음을 의미합니다. 예를 들어 jpg 이미지 또는 직렬화된 개체입니다. 문자열 유형은 Redis의 가장 기본적인 데이터 유형으로, 문자열 유형 값은 최대 512MB까지 저장할 수 있습니다.

  일반적인 명령: get, set, incr, decr, mget 등

응용 시나리오: 문자열은 가장 일반적으로 사용되는 데이터 유형이며 일반 키/값 저장소가 이 범주로 분류될 수 있습니다. 이는 Memcached의 현재 기능을 완전히 구현하고 더 효율적으로 사용할 수 있음을 의미합니다. Redis의 예약 지속성, 작업 로그 및 복제 기능도 즐길 수 있습니다. Memcached와 동일한 get, set, incr, decr 및 기타 작업을 제공하는 것 외에도 Redis는 다음 작업도 제공합니다.

  • 문자열 길이 가져오기
  • 문자열에 콘텐츠 추가
  • Memcached의 특정 세그먼트 설정 및 가져오기 문자열 콘텐츠
  • 문자열의 특정 비트 설정 및 가져오기
  • 일련의 문자열 콘텐츠를 일괄 설정

사용 시나리오: 일반 키-값 캐싱 애플리케이션. 정기 집계: 웨이보 게시물 수, 팬 수.

구현 방법: 문자열은 기본적으로 redis에 문자열로 저장되며 redisObject에서 참조됩니다. incr, decr 및 기타 작업이 발생하면 계산을 위해 숫자 형식으로 변환됩니다. redisObject는 int입니다.

redis 127.0.0.1:6379> SET name "runoob"
"OK"redis 127.0.0.1:6379> GET name
"runoob"

 위의 예에서는 Redis의 SETGET 명령을 사용했습니다. 키는 이름이고 해당 값은 runoob입니다.

참고: 키는 최대 512MB까지 저장할 수 있습니다.

 ② Redis 해시는 키-값(키 => 값) 쌍의 모음입니다. Redis 해시는 문자열 유형 필드와 값의 매핑 테이블입니다. 해시는 특히 개체를 저장하는 데 적합합니다.

 일반적으로 사용되는 명령: hget, hset, hgetall 등

적용 시나리오: Hash의 적용 시나리오를 설명하기 위해 간단한 예를 들어 보겠습니다. 예를 들어 다음 정보를 포함하는 사용자 정보 개체 데이터를 저장하려고 합니다.

  사용자 ID는 검색할 키이며, 저장된 값 사용자 객체에는 이름과 나이, 생일 및 기타 정보가 포함됩니다. 일반적인 키/값 구조를 사용하여 저장하는 경우 두 가지 주요 저장 방법이 있습니다.

  첫 번째 방법은 사용자 ID를 검색 키로 사용하고 캡슐화합니다. 다른 정보를 객체로 직렬화하여 직렬화하는 단점 이 방법의 단점은 직렬화/역직렬화의 오버헤드를 증가시키고, 정보 중 하나를 수정해야 할 경우 전체 객체를 검색해야 하며 수정 작업에서 동시성을 보호해야 한다는 것입니다. , CAS가 도입되고 기타 복잡한 문제가 발생합니다.

  두 번째 방법은 사용자 정보 객체에 멤버 수만큼 키-값 쌍을 저장하고, 사용자 ID + 해당 속성의 이름을 고유 식별자로 사용하여 해당 값을 얻는 것입니다. 속성을 사용하여 시퀀스를 생략하더라도 오버헤드와 동시성 문제를 최소화하지만, 사용자 ID가 반복적으로 저장되는 경우에는 여전히 메모리 낭비가 매우 큽니다.

  그러면 Redis에서 제공하는 Hash는 이 문제를 매우 잘 해결합니다. Redis의 Hash는 실제로 내부적으로 HashMap으로 값을 저장하고 아래와 같이 이 Map의 구성원에 직접 액세스할 수 있는 인터페이스를 제공합니다.

즉, 키는 여전히 사용자 ID이고 값은 Map입니다. 이 Map의 키는 멤버의 속성 이름이고 값은 속성 값입니다. 데이터는 내부 Map의 Key(Redis에서는 Internal이라고 함)를 통해 직접 수행할 수 있습니다. 즉, 해당 속성 데이터를 키(사용자 ID) + 필드(속성 라벨)를 통해 조작할 수 있습니다. 데이터를 반복적으로 저장할 필요가 없으며 직렬화 및 동시 수정 제어에 문제가 발생하지 않습니다.

  여기서 주목해야 할 점은 Redis는 모든 속성 데이터를 직접 얻을 수 있는 인터페이스(hgetall)를 제공한다는 점입니다. 그러나 내부 맵의 구성원이 많은 경우 단일 맵으로 인해 전체 내부 맵을 순회하는 작업이 필요합니다. Redis의 스레드 모델에서는 순회 작업에 시간이 많이 걸릴 수 있으며 다른 클라이언트 요청이 전혀 응답하지 않을 수 있으므로 특별한 주의가 필요합니다.

사용 시나리오: 사용자 정보 등 일부 변경 데이터를 저장합니다.

  实现方式:上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

redis> HSET myhash field1 "Hello" field2 "World"
"OK"
redis> HGET myhash field1
"Hello"
redis> HGET myhash field2
"World"

  实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。每个 hash 可以存储 232 -1 键值对(40多亿)。

  ③ Redis list 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

  常用命令:lpush(添加左边元素),rpush,lpop(移除左边第一个元素),rpop,lrange(获取列表片段,LRANGE key start stop)等。

  应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。

    List 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用List结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,
可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。

  实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

  Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列。 获取越接近两端的元素速度越快,但通过索引访问时会比较慢。

使用场景:

  消息队列系统:使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。比如:将Redis用作日志收集器,实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。

  取最新N个数据的操作:记录前N个最新登陆的用户Id列表,超出的范围可以从数据库中获得。

//把当前登录人添加到链表里
ret = r.lpush("login:last_login_times", uid)
//保持链表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)
//获得前N个最新登陆的用户Id列表
last_login_list = r.lrange("login:last_login_times", 0, N-1)

比如微博:

  在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。

redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

  列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

   Redis set是string类型的无序集合。集合是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。所以添加,删除,查找的复杂度都是O(1)。

  sadd 命令:添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。

  常用命令:sadd,spop,smembers,sunion 等。

  应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

  Set 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Set数据结构,可以存储一些集合性的数据。

  案例:在微博中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

  实现方式: set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

  使用场景:

  ①交集,并集,差集:(Set)

//book表存储book名称
set book:1:name    ”The Ruby Programming Language”
set book:2:name     ”Ruby on rail”
set book:3:name     ”Programming Erlang”
//tag表使用集合来存储数据,因为集合擅长求交集、并集
sadd tag:ruby 1
sadd tag:ruby 2
sadd tag:web 2
sadd tag:erlang 3
//即属于ruby又属于web的书?
inter_list = redis.sinter("tag.web", "tag:ruby") 
//即属于ruby,但不属于web的书?
inter_list = redis.sdiff("tag.ruby", "tag:web") 
//属于ruby和属于web的书的合集?
inter_list = redis.sunion("tag.ruby", "tag:web")

  ②获取某段时间所有数据去重值

  这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。

sadd key member
redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob
1) "redis"
2) "rabitmq"
3) "mongodb"

  注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。

  ⑤ Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

  zadd 命令:添加元素到集合,元素在集合中存在则更新对应score。

  常用命令:zadd,zrange,zrem,zcard等

  使用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。和Set相比,Sorted Set关联了一个double类型权重参数score,使得集合中的元素能够按score进行有序排列,redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。比如一个存储全班同学成绩的Sorted Set,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用Sorted Set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

  实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

zadd key score member
redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000
1) "mongodb"
2) "rabitmq"
3) "redis"

各个数据类型应用场景:

类型 简介 特性 场景
String(字符串) 二进制安全 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M ---
Hash(字典) 键值对集合,即编程语言中的Map类型 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) 存储、读取、修改用户属性
List(列表) 链表(双向链表) 增删快,提供了操作某一段元素的API 1、最新消息排行等功能(比如朋友圈的时间线) 2、消息队列
Set(集合) 哈希表实现,元素不重复 1、添加、删除、查找的复杂度都是O(1)  2、为集合提供了求交集、并集、差集等操作 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合) 将Set中的元素增加一个权重参数score,元素按score有序排列 数据插入集合时,已经进行天然排序 1、排行榜 2、带权重的消息队列

 Redis实际应用场景

  Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程。另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不需要转到Redis。

  转向Redis当然也是可取的,许多开发者从一开始就把Redis作为首选数据库;但设想如果你的开发环境已经搭建好,应用已经在上面运行了,那么更换数据库框架显然不那么容易。另外在一些需要大容量数据集的应用,Redis也并不适合,因为它的数据集不会超过系统可用的内存。所以如果你有大数据应用,而且主要是读取访问模式,那么Redis并不是正确的选择。

  然而我喜欢Redis的一点就是你可以把它融入到你的系统中来,这就能够解决很多问题,比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可以通过Redis来进行优化,或者为应用创建些新的功能。在本文中,我就想探讨一些怎样将Redis加入到现有的环境中,并利用它的原语命令等功能来解决 传统环境中碰到的一些常见问题。在这些例子中,Redis都不是作为首选数据库。

1、显示最新的项目列表

  下面这个语句常用来显示最新项目,随着数据多了,查询毫无疑问会越来越慢。

SELECT * FROM foo WHERE ... ORDER BY time DESC LIMIT 10

  在Web应用中,“列出最新的回复”之类的查询非常普遍,这通常会带来可扩展性问题。这令人沮丧,因为项目本来就是按这个顺序被创建的,但要输出这个顺序却不得不进行排序操作。

  类似的问题就可以用Redis来解决。比如说,我们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上我们有一个“显示全部”的链接,点击后就可以获得更多的评论。

       我们假设数据库中的每条评论都有一个唯一的递增的ID字段。我们可以使用分页来制作主页和评论页,使用Redis的模板,每次新评论发表时,我们会将它的ID添加到一个Redis列表:

LPUSH latest.comments <ID>

  我们将列表裁剪为指定长度,因此Redis只需要保存最新的5000条评论:

LTRIM latest.comments 0 5000

      每次我们需要获取最新评论的项目范围时,我们调用一个函数来完成(使用伪代码):

FUNCTION get_latest_comments(start, num_items):  
    id_list = redis.lrange("latest.comments",start,start+num_items - 1)  
    IF id_list.length < num_items  
        id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")  
    END  
    RETURN id_list  
END

  这里我们做的很简单。在Redis中我们的最新ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。

2、删除与过滤

  我们可以使用LREM来删除评论。如果删除操作非常少,另一个选择是直接跳过评论条目的入口,报告说该评论已经不存在。

redis 127.0.0.1:6379> LREM KEY_NAME COUNT VALUE

  有些时候你想要给不同的列表附加上不同的过滤器。如果过滤器的数量受到限制,你可以简单的为每个不同的过滤器使用不同的Redis列表。毕竟每个列表只有5000条项目,但Redis却能够使用非常少的内存来处理几百万条项目。

3、排行榜相关

  另一个很普遍的需求是各种数据库的数据并非存储在内存中,因此在按得分排序以及实时更新这些几乎每秒钟都需要更新的功能上数据库的性能不够理想。

  典型的比如那些在线游戏的排行榜,比如一个Facebook的游戏,根据得分你通常想要:

     - 列出前100名高分选手

     - 列出某用户当前的全球排名

  这些操作对于Redis来说小菜一碟,即使你有几百万个用户,每分钟都会有几百万个新的得分。

  模式是这样的,每次获得新得分时,我们用这样的代码:

 ZADD leaderboard  <score>  <username>

  你可能用userID来取代username,这取决于你是怎么设计的。

  得到前100名高分用户很简单:ZREVRANGE leaderboard 0 99。

  用户的全球排名也相似,只需要:ZRANK leaderboard d6025a37ea8687b5422f951f7288bdc5。

4、按照用户投票和时间排序

  排行榜的一种常见变体模式就像Reddit或Hacker News用的那样,新闻按照类似下面的公式根据得分来排序:

  score = points / time^alpha 

  因此用户的投票会相应的把新闻挖出来,但时间会按照一定的指数将新闻埋下去。下面是我们的模式,当然算法由你决定。

  模式是这样的,开始时先观察那些可能是最新的项目,例如首页上的1000条新闻都是候选者,因此我们先忽视掉其他的,这实现起来很简单。

  每次新的新闻贴上来后,我们将ID添加到列表中,使用LPUSH + LTRIM,确保只取出最新的1000条项目。

  有一项后台任务获取这个列表,并且持续的计算这1000条新闻中每条新闻的最终得分。计算结果由ZADD命令按照新的顺序填充生成列表,老新闻则被清除。这里的关键思路是排序工作是由后台任务来完成的。

5、处理过期项目

  另一种常用的项目排序是按照时间排序。我们使用unix时间作为得分即可。

  模式如下:

    - 每次有新项目添加到我们的非Redis数据库时,我们把它加入到排序集合中。这时我们用的是时间属性,current_time和time_to_live。

    - 另一项后台任务使用ZRANGE…SCORES查询排序集合,取出最新的10个项目。如果发现unix时间已经过期,则在数据库中删除条目。

6、计数

  Redis是一个很好的计数器,这要感谢INCRBY和其他相似命令。

  我相信你曾许多次想要给数据库加上新的计数器,用来获取统计或显示新信息,但是最后却由于写入敏感而不得不放弃它们。

  好了,现在使用Redis就不需要再担心了。有了原子递增(atomic increment),你可以放心的加上各种计数,用GETSET重置,或者是让它们过期。

  例如这样操作:

INCR user:<id> EXPIRE 

user:<id> 60

  你可以计算出最近用户在页面间停顿不超过60秒的页面浏览量,当计数达到比如20时,就可以显示出某些条幅提示,或是其它你想显示的东西。

7、特定时间内的特定项目

  另一项对于其他数据库很难,但Redis做起来却轻而易举的事就是统计在某段特点时间里有多少特定用户访问了某个特定资源。比如我想要知道某些特定的注册用户或IP地址,他们到底有多少访问了某篇文章。

  每次我获得一次新的页面浏览时我只需要这样做:

SADD page:day1:<page_id> <user_id>

  当然你可能想用unix时间替换day1,比如time()-(time()%3600*24)等等。

  想知道特定用户的数量吗?只需要使用

SCARD page:day1:<page_id>

  需要测试某个特定用户是否访问了这个页面?

SISMEMBER page:day1:<page_id>

8、实时分析正在发生的情况,用于数据统计与防止垃圾邮件等

  我们只做了几个例子,但如果你研究Redis的命令集,并且组合一下,就能获得大量的实时分析方法,有效而且非常省力。使用Redis原语命令,更容易实施垃圾邮件过滤系统或其他实时跟踪系统。

9、Pub/Sub

  Redis的Pub/Sub非常非常简单,运行稳定并且快速。支持模式匹配,能够实时订阅与取消频道。

10、队列

  你应该已经注意到像list push和list pop这样的Redis命令能够很方便的执行队列操作了,但能做的可不止这些:比如Redis还有list pop的变体命令,能够在列表为空时阻塞队列。

최신 인터넷 애플리케이션은 메시지 대기열(메시징)을 광범위하게 사용합니다. 메시지 큐는 시스템 내부 구성 요소 간의 통신뿐만 아니라 시스템과 다른 서비스 간의 상호 작용에도 사용됩니다. 메시지 대기열을 사용하면 시스템의 확장성, 유연성 및 사용자 경험을 향상시킬 수 있습니다. 메시지 대기열을 기반으로 하지 않는 시스템의 실행 속도는 시스템에서 가장 느린 구성 요소의 속도에 따라 달라집니다(참고: 단락 효과). 메시지 큐를 기반으로 시스템의 각 구성 요소를 분리할 수 있으므로 시스템은 더 이상 가장 느린 구성 요소에 얽매이지 않으며 각 구성 요소는 비동기식으로 실행되어 작업을 더 빠르게 완료할 수 있습니다.

 또한 로그 파일을 자주 작성하는 등 서버가 동시성 작업을 수행하는 경우. 메시지 큐를 사용하여 비동기 처리를 구현할 수 있습니다. 이를 통해 고성능 동시 작업이 가능합니다.

11. 캐싱

Redis의 캐싱 부분은 새 글을 쓸 가치가 있습니다. 여기서는 간단히 이야기하겠습니다. Redis는 memcached를 대체하여 캐시를 데이터 저장만에서 데이터 업데이트 가능으로 변경할 수 있으므로 더 이상 매번 데이터를 다시 생성할 필요가 없습니다.

더 많은 프로그래밍 관련 지식을 보려면 프로그래밍 소개를 방문하세요! !

위 내용은 Redis의 5가지 데이터 유형에 대해 이야기하고 이를 어떻게 적용할 수 있는지 살펴보겠습니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제