Heim  >  Artikel  >  Datenbank  >  Detaillierte Erläuterung der Pipeline in Redis

Detaillierte Erläuterung der Pipeline in Redis

尚
nach vorne
2020-05-27 09:04:454510Durchsuche

Detaillierte Erläuterung der Pipeline in Redis

1. Der Hintergrund des Pipeline-Erscheinungsbilds:

Redis verfügt über vier Prozesse zum Ausführen eines Befehls: Senden eines Befehls, Befehlswarteschlange, Befehlsausführung und Zurückgeben von Ergebnissen ;

Dieser Prozess wird als Round Trip Time (RTT) bezeichnet. Er spart effektiv RTT, aber die meisten Befehle (wie hgetall, aber nicht mhgetall) unterstützen keine Batch-Operationen und müssen N-mal verbrauchen RTT ist derzeit erforderlich, um dieses Problem zu lösen.

2. Leistung der Pipeline

1. N Befehle ohne Verwendung der Pipeline ausführen

Detaillierte Erläuterung der Pipeline in Redis

2. N Befehle mit Pipeline ausführen

Detaillierte Erläuterung der Pipeline in Redis

3. Leistungsvergleich zwischen den beiden

Detaillierte Erläuterung der Pipeline in Redis

Zusammenfassung: Dies ist ein Satz statistischer Daten mit Pipeline Die Ausführungsgeschwindigkeit beträgt schneller als die Ausführung nacheinander, insbesondere je größer die Netzwerkverzögerung zwischen Client und Server ist, desto offensichtlicher ist die Leistung.

Der Testcode wird unten veröffentlicht, um den Leistungsunterschied zwischen den beiden zu analysieren:

	@Test
	public void pipeCompare() {
		Jedis redis = new Jedis("192.168.1.111", 6379);
		redis.auth("12345678");//授权密码 对应redis.conf的requirepass密码
		Map<String, String> data = new HashMap<String, String>();
		redis.select(8);//使用第8个库
		redis.flushDB();//清空第8个库所有数据
		// hmset
		long start = System.currentTimeMillis();
		// 直接hmset
		for (int i = 0; i < 10000; i++) {
			data.clear();  //清空map
			data.put("k_" + i, "v_" + i);
			redis.hmset("key_" + i, data); //循环执行10000条数据插入redis
		}
		long end = System.currentTimeMillis();
		System.out.println("    共插入:[" + redis.dbSize() + "]条 .. ");
		System.out.println("1,未使用PIPE批量设值耗时" + (end - start) / 1000 + "秒..");
		redis.select(8);
		redis.flushDB();
		// 使用pipeline hmset
		Pipeline pipe = redis.pipelined();
		start = System.currentTimeMillis();
		//
		for (int i = 0; i < 10000; i++) {
			data.clear();
			data.put("k_" + i, "v_" + i);
			pipe.hmset("key_" + i, data); //将值封装到PIPE对象,此时并未执行,还停留在客户端
		}
		pipe.sync(); //将封装后的PIPE一次性发给redis
		end = System.currentTimeMillis();
		System.out.println("    PIPE共插入:[" + redis.dbSize() + "]条 .. ");
		System.out.println("2,使用PIPE批量设值耗时" + (end - start) / 1000 + "秒 ..");
//--------------------------------------------------------------------------------------------------
		// hmget
		Set<String> keys = redis.keys("key_*"); //将上面设值所有结果键查询出来
		// 直接使用Jedis hgetall
		start = System.currentTimeMillis();
		Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
		for (String key : keys) {
			//此处keys根据以上的设值结果,共有10000个,循环10000次
			result.put(key, redis.hgetAll(key)); //使用redis对象根据键值去取值,将结果放入result对象
		}
		end = System.currentTimeMillis();
		System.out.println("    共取值:[" + redis.dbSize() + "]条 .. ");
		System.out.println("3,未使用PIPE批量取值耗时 " + (end - start) / 1000 + "秒 ..");

		// 使用pipeline hgetall
		result.clear();
		start = System.currentTimeMillis();
		for (String key : keys) {
			pipe.hgetAll(key); //使用PIPE封装需要取值的key,此时还停留在客户端,并未真正执行查询请求
		}
		pipe.sync();  //提交到redis进行查询
		
		end = System.currentTimeMillis();
		System.out.println("    PIPE共取值:[" + redis.dbSize() + "]条 .. ");
		System.out.println("4,使用PIPE批量取值耗时" + (end - start) / 1000 + "秒 ..");

		redis.disconnect();
	}

Detaillierte Erläuterung der Pipeline in Redis

3. Vergleich zwischen nativen Batch-Befehlen (mset, mget) und Pipeline

1. Der native Batch-Befehl ist atomar und die Pipeline ist nicht atomar

(Das Konzept der Atomizität: Eine Transaktion ist eine unteilbare Mindestarbeitseinheit, entweder alle erfolgreich oder alle Atomare Operationen bedeuten, dass die Verarbeitung einer Sache entweder erfolgreich ist oder fehlschlägt und Atome nicht geteilt werden können.

2 Der native Batch-Befehl unterstützt mehrere Befehle . (Vorhandensein von Transaktionen), nicht atomar

3. Der native Batch-Befehl wird auf der Serverseite implementiert und die Pipeline muss vom Server und vom Client gemeinsam abgeschlossen werden

4 . Die richtige Art, Pipeline zu verwenden

Die Anzahl der mithilfe der Pipeline zusammengestellten Befehle darf nicht zu groß sein, da sonst die Datenmenge zu groß wird, was die Wartezeit des Clients erhöht und zu einer Netzwerküberlastung führen kann. Eine große Anzahl von Befehlen kann zur Ausführung in mehrere kleine Pipeline-Befehle aufgeteilt werden.

1. So verwenden Sie die Pipeline in Jedis

Wie wir alle wissen, bietet Redis die Methoden mset und mget, jedoch keine mdel-Methode. Wenn Sie dies erreichen möchten, können Sie die Pipeline verwenden um es zu erreichen.

2. Schritte zur Verwendung der Pipeline in Jedis:

  • Holen Sie sich das Jedis-Objekt (normalerweise aus dem Verbindungspool)

  • Holen Sie sich das Pipeline-Objekt des Jedis-Objekts

  • Fügen Sie die Anweisung hinzu

  • Führen Sie die Anweisung aus

Klassenmethode testen:

	 @Test
	public void testCommond() {
		// 工具类初始化
		JedisUtils jedis = new JedisUtils("192.168.1.111", 6379, "12345678");

		for (int i = 0; i < 100; i++) {
			// 设值
			jedis.set("n" + i, String.valueOf(i));
		}
		System.out.println("keys from redis return =======" + jedis.keys("*"));

	}

	// 使用pipeline批量删除
	 @Test
	public void testPipelineMdel() {
		// 工具类初始化
		JedisUtils jedis = new JedisUtils("192.168.1.111", 6379, "12345678");
		List<String> keys = new ArrayList<String>();
		for (int i = 0; i < 100; i++) {
			keys.add("n" + i);
		}
		jedis.mdel(keys);
		System.out.println("after mdel the redis return ---------" + jedis.keys("*"));
	}

mdel-Methode unter JedisUtils:

	/**
	 * 删除多个字符串key 并释放连接
	 * 
	 * @param keys*
	 * @return 成功返回value 失败返回null
	 */
	public boolean mdel(List<String> keys) {
		Jedis jedis = null;
		boolean flag = false;
		try {
			jedis = pool.getResource();//从连接借用Jedis对象
			Pipeline pipe = jedis.pipelined();//获取jedis对象的pipeline对象
			for(String key:keys){
				pipe.del(key); //将多个key放入pipe删除指令中
			}
			pipe.sync(); //执行命令,完全此时pipeline对象的远程调用 
			flag = true;
		} catch (Exception e) {
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
		} finally {
			returnResource(pool, jedis);
		}
		return flag;
	}

Pipeline verwenden, um alle Vorgänge zu übermitteln und Ausführungsergebnisse zurückzugeben:

@Test
	public void testPipelineSyncAll() {
		// 工具类初始化
		Jedis jedis = new Jedis("192.168.1.111", 6379);
		jedis.auth("12345678");
		// 获取pipeline对象
		Pipeline pipe = jedis.pipelined();
		pipe.multi();
		pipe.set("name", "james"); // 调值
		pipe.incr("age");// 自增
		pipe.get("name");
		pipe.discard();
		// 将不同类型的操作命令合并提交,并将操作操作以list返回
		List<Object> list = pipe.syncAndReturnAll();

		for (Object obj : list) {
			// 将操作结果打印出来
			System.out.println(obj);
		}
		// 断开连接,释放资源
		jedis.disconnect();
	}

5. Redis-Transaktion

Was ist eine Pipeline? Um ihre Atomizität sicherzustellen, stellt Redis einfache Transaktionen bereit.

1. Einfache Transaktion von Redis,

Eine Gruppe von Befehlen, die zusammen ausgeführt werden müssen, wird zwischen den Befehlen multi und exec platziert, wobei multi den Start der Transaktion darstellt und exec den Ende der Transaktion.

Detaillierte Erläuterung der Pipeline in Redis

2. Verwerfen der Transaktion

Detaillierte Erläuterung der Pipeline in Redis

3. Der Befehl ist falsch und die Syntax ist falsch Transaktion endet nicht normal

Detaillierte Erläuterung der Pipeline in Redis

4. Ausführungsfehler, die Syntax ist korrekt, aber der Typ ist falsch, die Transaktion kann normal enden

Detaillierte Erläuterung der Pipeline in Redis

5. Watch-Befehl:

Nach der Verwendung von Watch schlägt Multi fehl und die Transaktion schlägt fehl

Detaillierte Erläuterung der Pipeline in Redis

Der WATCH-Mechanismus ist: wenn die Transaktion Wenn der EXEC-Befehl ausgeführt wird, überprüft Redis den WATCH-Schlüssel. EXEC wird nur ausgeführt, wenn sich der WATCH-Schlüssel seit dem Start von WATCH nicht geändert hat. Wenn sich die WATCH-Taste zwischen dem WATCH-Befehl und dem EXEC-Befehl ändert, gibt der EXEC-Befehl einen Fehler zurück.

Weitere Redis-Kenntnisse finden Sie in der Spalte Redis-Einführungs-Tutorial.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Pipeline in Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:Redis-Persistenz-VollversionNächster Artikel:Redis-Persistenz-Vollversion