1. redis とは何ですか?
Redis は、メモリに基づいた高性能のキーと値のデータベースです。
特別なトピックの推奨事項: 2020 redis 面接の質問 (最新)
2. Reid の特徴
Redis は、基本的に、memcached とよく似た Key-Value タイプのメモリ内データベースです。データベース全体が操作のためにメモリにロードされ、データベース データは、非同期操作を通じてストレージ用のハードディスクに定期的にフラッシュされます。 Redis は純粋なメモリ操作であるため、優れたパフォーマンスを備え、1 秒あたり 100,000 を超える読み取りおよび書き込み操作を処理でき、既知の中で最も高速に実行できる Key-Value DB です。
Redis の優秀さはパフォーマンスだけではありません。Redis の最大の魅力は、さまざまなデータ構造の保存に対応していることです。また、単一の値の最大制限は 1GB です。memcached とは異なり、 Redis は 1MB のデータのみを保存できます。これは、List を使用して FIFO 双方向リンク リストを作成し、軽量で高性能なメッセージ キュー サービスを実装したり、その Set を使用して高パフォーマンスのメッセージ キュー サービスを作成したりするなど、多くの便利な機能を実装するために使用されます。・パフォーマンスタグシステムなどさらに、Redis は保存された Key-Value の有効期限を設定できるため、memcached の拡張版としても使用できます。
Redis の主な欠点は、データベース容量が物理メモリによって制限され、大量のデータの高パフォーマンスな読み取りおよび書き込みには使用できないことです。そのため、Redis に適したシナリオは主に高パフォーマンスに限定されます。少量のデータの操作と計算。
関連する学習の推奨事項:redis ビデオ チュートリアル3. Redis を使用する利点は何ですか?
(1) HashMap と同様にデータがメモリに保存されるため高速です。HashMap の利点は、検索と操作の計算量が O(1)
## であることです。 #(2) 豊富なデータ型をサポート、文字列、リスト、セット、ソートセット、ハッシュをサポート#(3) トランザクションをサポート、操作はアトミックです。いわゆるアトミックとは、データに対するすべての変更が実行されることを意味します。またはすべて 未実行
(4) 豊富な機能: キャッシュ、メッセージ、キーによる有効期限の設定に使用でき、有効期限が切れると自動的に削除されます
4. memcached と比較した Redis の利点は何ですか?
(1) memcached のすべての値は単純な文字列です。その代わりに、redis はより豊富なデータ型をサポートします(2) Redis は memcached よりも高速です はるかに高速です
(3) redis はデータを永続化できます
5. Memcache と Redis の違いは何ですか?
1). 保存方法 Memecache はすべてのデータをメモリに保存します。停電後はハングアップします。データはメモリ サイズを超えることはできません。 Redis の一部はハードディスクに保存されるため、データの永続性が保証されます。 2)、データ サポートの種類 Memcache は、比較的単純なデータ型をサポートします。 Redis には複雑なデータ型があります。
3)、使用される基礎となるモデル、基礎となる実装方法、およびクライアントと通信するためのアプリケーション プロトコルが異なります。一般的なシステムがシステム関数を呼び出すと、移動やリクエストに一定の時間が無駄になるため、Redis は独自の VM メカニズムを直接構築しました。
6. Redis の一般的なパフォーマンスの問題と解決策:
1). マスターはメモリ スナップショットを書き込み、save コマンドは rdbSave 関数をスケジュールします。スナップショットが比較的大きい場合、パフォーマンスに大きな影響を与え、サービスが断続的に中断されるため、マスターがメモリ スナップショットを書き込まないことをお勧めします。 2). マスター AOF 永続性。AOF ファイルが書き換えられない場合、この永続化方法によるパフォーマンスへの影響は最小限ですが、AOF ファイルは増大し続けます。AOF ファイルが大きすぎる場合、AOF ファイルは大きくなり続けます。マスターの再起動の回復速度に影響します。メモリ スナップショットや AOF ログ ファイルなど、マスター上で永続化作業を行わないことが最善です。特に、永続化のためにメモリ スナップショットを有効にしないでください。データが重要な場合、スレーブは AOF バックアップ データを有効にする必要があり、その戦略は次のとおりです。 1 秒に 1 回同期します。
3). マスターは BGREWRITEAOF を呼び出して AOF ファイルを書き換えます。AOF は書き換え中に大量の CPU リソースとメモリ リソースを占有するため、サービスの負荷が高くなりすぎてサービスが一時的に停止されます。
4)、Redis マスター/スレーブ レプリケーションのパフォーマンスの問題。マスター/スレーブ レプリケーションの速度と接続の安定性を考慮すると、スレーブとマスターが同じ LAN 内にあることが最適です
7, mySQL には 2,000 万のデータがありますが、redis には 200,000 のデータのみが保存されます。redis のデータがホット データであることを確認する方法関連ナレッジ: Redis メモリ データ セットが特定のサイズに増加すると、データ陳腐化戦略 (リサイクル戦略) が実装されます。 redis は 6 つのデータ削除戦略を提供します。 volatile-lru: 削除する有効期限を設定して、データセット (server.db[i].expires) から最も最近使用されていないデータを選択します。
volatile-ttl: 削除する有効期限が設定されたデータ セット (server.db[i].expires) から期限切れにするデータを選択します。
volatile-random: 有効期限が設定されたデータ セット (
## を削除するには、server.db[i].expires) を使用してデータを削除します。allkeys-lru: データ セット (server.db[i].dict) から最も最近使用されていないデータを選択して削除しますallkeys -random: データ セット (server.db[i].dict) からデータをランダムに選択して削除しますno-enviction (エビクション): データのエビクションを禁止します
8. Redis と任意の言語を使用して、悪意のあるログイン保護のためのコードを実装してください。各ユーザー ID のログイン数を最大 5 に制限してください1時間以内。特定のログイン関数または関数については、空の関数を使用するだけでよく、詳細に記述する必要はありません。
リストを使用して実装: リスト内の各要素はログイン時刻を表し、最後の 5 回目のログイン時刻と現在時刻の差が 1 時間を超えない限り、ログインは禁止されます。 Python で書かれたコードは次のとおりです:
#!/usr/bin/env python3 import redis import sys import time r = redis.StrictRedis(host=’127.0.0.1′, port=6379, db=0) try: id = sys.argv[1] except: print(‘input argument error’) sys.exit(0) if r.llen(id) >= 5 and time.time() – float(r.lindex(id, 4)) <= 3600: print(“you are forbidden logining”) else: print(‘you are allowed to login’) r.lpush(id, time.time()) # login_func()
9. なぜ Redis はすべてのデータをメモリに置く必要があるのですか?
Redis最速の読み取りおよび書き込み速度を実現するためにデータを保存します。すべては非同期でメモリに読み取られ、ディスクに書き込まれます。つまり、redis は高速でデータの永続性が高いという特徴を持っています。データがメモリに配置されていない場合、ディスク I/O 速度は Redis のパフォーマンスに重大な影響を与えます。メモリがどんどん安くなっている現在、redis の人気はますます高まるでしょう。
最大使用メモリが設定されている場合、データ レコード数がメモリ制限に達すると、新しい値を挿入できなくなります。
10.Redis は単一プロセスおよび単一スレッドです
redis はキュー テクノロジーを使用して同時アクセスをシリアル アクセスに変換し、従来のデータベース シリアル制御のオーバーヘッドを排除します
11. Redis の同時実行競合問題を解決するにはどうすればよいですか?
Redis はシングル プロセス シングル スレッド モードであり、キュー モードを使用して同時アクセスをシリアル アクセスに変換します。 Redis 自体にはロックの概念がありません。Redis は複数のクライアント接続を競合しません。ただし、Jedis クライアントが Redis に同時にアクセスすると、接続タイムアウト、データ変換エラー、ブロック、クライアントによる接続の切断などの問題が発生する可能性があります。これらはすべてクライアント接続の混乱によって引き起こされます。
これには 2 つの解決策があります:
1. クライアントの観点から見ると、各クライアントが通常の順序で Redis と通信できるようにするために、接続はプールされ、クライアントはエンドツーエンドの読み取りおよび書き込み Redis 操作では、同期された内部ロックが使用されます。
2. サーバーの観点からは、setnx を使用してロックを実装します。
注: 最初のタイプでは、アプリケーションはリソースの同期を独自に処理する必要があります。使用できる方法は比較的一般的で、同期またはロックを使用できます。2 番目のタイプでは、Redis の同期を使用する必要があります。 setnx コマンドを使用しますが、いくつかの問題に注意する必要があります。
12. Redis の CAS (オプティミスティック ロックを実装するためのチェック アンド セット操作) についての理解?
他の多くのデータベースと同様、Redis は NoSQL データベース トランザクションも提供します機構。 Redis では、MULTI/EXEC/DISCARD/WATCH の 4 つのコマンドがトランザクション実装の基礎となります。
この概念は、リレーショナル データベース開発の経験を持つ開発者にとっては馴染みのないものではないと思いますが、それでも、Redis トランザクションの実装特性を簡単にリストします:
1) トランザクション内のすべてのコマンドは、トランザクションの実行中、Redis は他のクライアント要求にサービスを提供しなくなるため、トランザクション内のすべてのコマンドがアトミックに実行されます。
2). リレーショナル データベースのトランザクションと比較すると、Redis トランザクションではコマンドの実行が失敗しても、後続のコマンドは引き続き実行されます。
3). MULTI コマンドを通じてトランザクションを開始できますが、これはリレーショナル データベース開発の経験がある人であれば「BEGIN TRANSACTION」ステートメントとして理解できます。このステートメントの後に実行されるコマンドはトランザクション内の操作とみなされ、最後に EXEC/DISCARD コマンドを実行することで、トランザクション内のすべての操作をコミット/ロールバックできます。これら 2 つの Redis コマンドは、リレーショナル データベースの COMMIT/ROLLBACK ステートメントと同等であるとみなすことができます。
4). トランザクションが開始される前に、クライアントとサーバー間の通信障害が発生し、ネットワークが切断された場合、実行される後続のすべてのステートメントはサーバーによって実行されません。ただし、クライアントが EXEC コマンドを実行した後にネットワーク中断イベントが発生した場合、トランザクション内のすべてのコマンドがサーバーによって実行されます。
5).追加専用モードを使用する場合、Redis はシステム関数 write を呼び出すことにより、この呼び出しでトランザクション内のすべての書き込み操作をディスクに書き込みます。ただし、電源障害によるダウンタイムなど、書き込みプロセス中にシステム クラッシュが発生した場合、その時点ではデータの一部だけがディスクに書き込まれ、データの他の部分が失われる可能性があります。
Redis サーバーは、再起動時に必要な一連の整合性チェックを実行します。同様の問題が見つかると、ただちに終了し、対応するエラー プロンプトが表示されます。現時点では、Redis ツールキットで提供されている redis-check-aof ツールを最大限に活用する必要があります。このツールは、データの不整合エラーを特定し、書き込まれたデータの一部をロールバックするのに役立ちます。修復後、Redis サーバーを再度再起動できます。
13.WATCH コマンドと CAS ベースのオプティミスティック ロック:
Redis トランザクションでは、WATCH コマンドを使用して CAS (チェック アンド セット) 機能を提供できます。 。トランザクションが実行される前に WATCH コマンドを通じて複数の Key を監視すると仮定します。WATCH 後にいずれかの Key の値が変更された場合、EXEC コマンドによって実行されたトランザクションは放棄され、呼び出し元に通知するために Null マルチバルク応答が返されます。
実行に失敗しました。たとえば、Redis にはキー値のアトミックなインクリメントを完了するための incr コマンドが提供されていないと仮定しますが、この機能を実装したい場合は、対応するコードを自分で記述するしかありません。疑似コードは次のとおりです:
val = GET mykey val = val + 1 SET mykey $val
以上代码只有在单连接的情况下才可以保证执行结果是正确的,因为如果在同一时刻有多个客户端在同时执行该段代码,那么就会出现多线程程序中经常出现的一种错误场景--竞态争用(race condition)。
比如,客户端A和B都在同一时刻读取了mykey的原有值,假设该值为10,此后两个客户端又均将该值加一后set回Redis服务器,这样就会导致mykey的结果为11,而不是我们认为的12。为了解决类似的问题,我们需要借助WATCH命令的帮助,见如下代码:
WATCH mykey val = GET mykey val = val + 1 MULTI SET mykey $val EXEC
和此前代码不同的是,新代码在获取mykey的值之前先通过WATCH命令监控了该键,此后又将set命令包围在事务中,这样就可以有效的保证每个连接在执行EXEC之前,如果当前连接获取的mykey的值被其它连接的客户端修改,那么当前连接的EXEC命令将执行失败。这样调用者在判断返回值后就可以获悉val是否被重新设置成功。
14.redis持久化的几种方式
1、快照(snapshots)
缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你可以手工调用命令SAVE或BGSAVE。
工作原理
. Redis forks.
. 子进程开始将数据写到临时RDB文件中。
. 当子进程完成写RDB文件,用新文件替换老文件。
. 这种方式可以使Redis使用copy-on-write技术。
2、AOF
快照模式并不十分健壮,当系统停止,或者无意中Redis被kill掉,最后写入Redis的数据就会丢失。这对某些应用也许不是大问题,但对于要求高可靠性的应用来说,Redis就不是一个合适的选择。Append-only文件模式是另一种选择。你可以在配置文件中打开AOF模式。
3、虚拟内存方式
当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.
当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.
vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.
自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库
15.redis的缓存失效策略和主键失效机制
作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略.
在Redis当中,有生存期的key被称为volatile。在创建缓存时,要为给定的key设置生存期,当key过期的时候(生存期为0),它可能会被删除。
1、影响生存时间的一些操作
生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆盖原来的数据,也就是说,修改key对应的value和使用另外相同的key和value来覆盖以后,当前数据的生存时间不同。
比如说,对一个 key 执行INCR命令,对一个列表进行LPUSH命令,或者对一个哈希表执行HSET命令,这类操作都不会修改 key 本身的生存时间。另一方面,如果使用RENAME对一个 key 进行改名,那么改名后的 key的生存时间和改名前一样。
RENAME命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。使用PERSIST命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个persistent key 。
2、如何更新生存时间
可以对一个已经带有生存时间的 key 执行EXPIRE命令,新指定的生存时间会取代旧的生存时间。过期时间的精度已经被控制在1ms之内,主键失效的时间复杂度是O(1),EXPIRE和TTL命令搭配使用,TTL可以查看key的当前生存时间。设置成功返回 1;当 key 不存在或者不能为 key 设置生存时间时,返回 0 。
最大缓存配置
在 redis 中,允许用户设置最大使用内存大小
server.maxmemory
默认为0,没有指定最大缓存,如果有新的数据添加,超过最大内存,则会使redis崩溃,所以一定要设置。redis 内存数据集大小上升到一定大小的时候,就会实行数据淘汰策略。
redis 提供 6种数据淘汰策略:
. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
. no-enviction(驱逐):禁止驱逐数据
注意这里的6种机制,volatile和allkeys规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据,后面的lru、ttl以及random是三种不同的淘汰策略,再加上一种no-enviction永不回收的策略。
使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random
三种数据淘汰策略:
ttl和random比较容易理解,实现也会比较简单。主要是Lru最近最少使用淘汰策略,设计上会对key 按失效时间排序,然后取最先失效的key进行淘汰
16.redis 最适合的场景
Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?
如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:
1 、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2 、Redis支持数据的备份,即master-slave模式的数据备份。
3 、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
(1)、会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,
他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
(2)、全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。
再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。
此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
(3)、队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
(4),排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。
(5)、发布/订阅
最後 (重要なことですが) は、Redis のパブリッシュ/サブスクライブ機能です。パブリッシュ/サブスクライブには実際に多くの使用例があります。人々がこれをソーシャル ネットワーク接続で使用したり、パブリッシュ/サブスクライブ ベースのスクリプトのトリガーとして使用したり、Redis のパブリッシュ/サブスクライブ機能を使用してチャット システムを構築したりしているのを見てきました。 (いいえ、これは本当です。ぜひチェックしてみてください。)
Redis が提供するすべての機能の中で、これはユーザーに多機能を提供するにもかかわらず、最も好まれない機能だと私は感じています。
推奨: redis 入門チュートリアル
以上がRedis の面接でよくある質問 (回答付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。