通常、redisインタビューの質問に遭遇するはずです。Redis
のスレッドモデルは何ですか?
簡単に言えば、reactorシングルスレッドモデルは内部で使用されます。ファイルイベントプロセッサと呼ばれるものを使用します。このファイルイベントプロセッサはシングルスレッドであるため、redisもシングルスレッドモデルです。
これは可能です。ネットワークの知識が必要です。プログラミング:
BIO、NIOとは何ですか、2つの
BIOの違いは何ですか(ブロッキングI / O):同期ブロッキングI / Oモード、データの読み取りと書き込みは、完了を待つスレッドでブロックする必要があります。アクティブな接続の数が特に多くない場合(1台のマシンで1000未満)、このモデルは比較的良好であり、各接続が独自のI / Oに集中でき、プログラミングモデルはシステムをあまり考慮せずに単純です。過負荷、現在の制限およびその他の問題。スレッドプール自体は自然な漏斗であり、システムが処理できない接続や要求をバッファリングできます。ただし、10万、さらには数百万の接続に直面した場合、従来のBIOモデルは無力です。したがって、より高い同時実行性に対処するには、より効率的なI / O処理モデルが必要です。
NIO(新しいI / O):NIOは同期ノンブロッキングI / Oモデルです。Java1.4では、java.nioパッケージに対応するNIOフレームワークが導入され、チャネル、セレクター、バッファーなどの抽象化を提供します。NIOのNは、単にNewではなく、非ブロッキングとして理解できます。バッファ指向のチャネルベースのI / O操作方法をサポートします。NIOは、従来のBIOモデルのSocketとServerSocketに対応するSocketChannelとServerSocketChannelの2つの異なるソケットチャネル実装を提供します。両方のチャネルは、ブロッキングモードと非ブロッキングモードをサポートします。ブロッキングモードの使用は、従来のサポートと同じで、比較的単純ですが、パフォーマンスと信頼性は良くありません。非ブロッキングモード
ただ反対。低負荷、低同時実行のアプリケーションの場合、同期ブロッキングI / Oを使用して開発率を高め、保守性を向上させることができます。高負荷、高同時実行(ネットワーク)アプリケーションの場合、NIOの非ブロッキングモードを使用して開発する必要があります。
これはコピーされた定義ですが、どのように理解しますか?
たくさんの動画を見た後、自分でコードを入力して、自分の理解について話しました。
まず、同期ブロッキングメカニズムであるBIOについて話しましょう。小さなデモサーバーコードを書きました
。
public class RedisServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9090);
while (true){
//阻塞的方法
Socket socket = serverSocket.accept();
System.out.println("XXXXX来连接了");
//在这里是错误的方法,因为我们的BIO不把我们的socket放入线程的话是不能支持并发的
//因为我们的read方法是会阻塞的,我们另一个客户端进来会在这个地方阻塞掉,是不会回去接收我们的客户端的socket的,所以只能有一个客户端连接
byte[] bytes = new byte[1024];
//阻塞的方法 没有消息可读会阻塞
socket.getInputStream().read(bytes);
System.out.println("收到客户端的消息" + new String(bytes));
}
}
}
クライアントコード
public class RedisClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",9090);
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
socket.getOutputStream().write(s.getBytes());
socket.close();
}
}
接続するクライアントを想像してみてください。問題はないはずですが、2つ以上のクライアントがサーバーに接続すると、問題が発生します。これは、2番目のクライアントが接続すると、サーバーのread()メソッドが次のようになるためです。メソッドはこの場所にブロックされ、2番目のクライアントは動作できません。
これが、サーバーコードのこの部分を実行のためにスレッドに配置する理由でもあります。シングルスレッド操作は同時実行をサポートしていませんが、問題が再び発生します。リソースを占有するスレッドが非常に貴重であることは誰もが知っています。サーバーが多数のスレッド(リソース、CPU使用率など)を作成するのは悪いことです。スレッドプールの使用はどうですか?確かに問題の一部を解決することはできますが、完全に解決することはできません。どうすればよいですか。これは、単一のスレッドで複数要求の同時実行の問題を処理することに専念しているNIOです。
知識を追加する
理解を引き出し、他の人に基づいて理解することで、類似点は他の
人から学ぶことです。1つの要求接続は複数のソケットを共有
します。単一のスレッドはどのように同時要求を処理しますか?
NIOパッケージは、セレクターと呼ばれるセレクターのコレクションを提供
します。コードの一部を投稿しました。
selector = Selector.open();//创建选择器对象
ssc = ServerSocketChannel.open();//打开服务端socket
InetSocketAddress addr = new InetSocketAddress(port);
ssc.socket().bind(addr);//在我们的ServerSockerChanel绑定端口
ssc.configureBlocking(false);//设置ServerSockerChanel为非阻塞
//
SelectionKey sk = ssc.register(selector,SelectionKey.OP_ACCEPT);//
//给定key一个附加的Acceptor对象,我们可以通过这个来判断是什么事件
sk.attach(new Acceptor(selector,ssc));
コードの別の部分はこのようなものです。私たちが気にしないビジネスについては、私はこの考えを理解するようになりました。
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
//遍历已经发生的事件
while (it.hasNext()){
SelectionKey selectionKey = it.next();
//根据事件的Key去调度
dispatch(selectionKey);
it.remove();
}
フローチャート
つまり、シングルスレッドの場合、ソケットを格納するためにセレクターセットを使用します。ここには、Acceptorオブジェクトも添付されています。
プロセスは、次のとおり
です。初めて接続する場合は、要求を受け入れます。登録このコレクションに、彼に関する情報を添付し、この時点でselectkeysコレクションをトラバースして、どのインタレストが格納されているかを確認します。受け入れられた場合は、runメソッドを呼び出します。読み取られた場合は、runを呼び出します。読み取りの方法、および同時に複数の要求、リンクと読み取り要求の両方、次にそれらをselectKeysにまとめ、1つずつ操作をポーリングし、1つずつ削除します。これが私が理解していることです。NIOの一般的な考え方次に
、 redisのスレッドモデル。
ここに兄のブログを投稿します。彼が書いたredisモデルは良いと思います。