1. 程式人生 > >Redis常用技術

Redis常用技術

container property connect cati tro nat add sco serialize

Xml配置:

<?xml version=‘1.0‘ encoding=‘UTF-8‘ ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxIdle" value="50" />
		<property name="maxTotal" value="100" />
		<property name="maxWaitMillis" value="20000" />
	</bean>

	<bean id="stringRedisSerializer"
		class="org.springframework.data.redis.serializer.StringRedisSerializer" />

	<bean id="connectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="localhost" />
		<property name="port" value="6379" />
		<property name="poolConfig" ref="poolConfig" />
	</bean>

	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultSerializer" ref="stringRedisSerializer" />
		<property name="keySerializer" ref="stringRedisSerializer" />
		<property name="valueSerializer" ref="stringRedisSerializer" />
	</bean>

	<bean id="redisMsgListener"
		class="com.ssm.chapter19.redis.listener.RedisMessageListener">
		<property name="redisTemplate" ref="redisTemplate" />
	</bean>

	<bean id="topicContainer"
		class="org.springframework.data.redis.listener.RedisMessageListenerContainer"
		destroy-method="destroy">
		<!--Redis連接工廠 -->
		<property name="connectionFactory" ref="connectionFactory" />
		<!--連接池,這裏只要線程池生存,才能繼續監聽 -->
		<property name="taskExecutor">
			<bean
				class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
				<property name="poolSize" value="2" />
			</bean>
		</property>
		<!--消息監聽Map -->
		<property name="messageListeners">
			<map>
				<!--配置監聽者,key-ref和bean id定義一致 -->
				<entry key-ref="redisMsgListener">
					<!--監聽類 -->
					<bean class="org.springframework.data.redis.listener.ChannelTopic">
						<constructor-arg value="chat" />
					</bean>
				</entry>
			</map>
		</property>
	</bean>
</beans>

  監聽類:

public class RedisMessageListener implements MessageListener {
	
	private RedisTemplate redisTemplate;

	@Override
	public void onMessage(Message message, byte[] bytes) {
		// 獲取消息
		byte[] body = message.getBody();
		// 使用值序列化器轉換
		String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(body);
		System.err.println(msgBody);
		// 獲取channel
		byte[] channel = message.getChannel();
		// 使用字符串序列化器轉換
		String channelStr = (String) getRedisTemplate().getStringSerializer().deserialize(channel);
		System.err.println(channelStr);
		// 渠道名稱轉換
		String bytesStr = new String(bytes);
		System.err.println(bytesStr);
	}

	public RedisTemplate getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
}

  測試:

public class Chapter19Main {

	public static void main(String[] args) {
		testTransaction();
		testPipeline();
		testJedisPipeline();
		testPubSub();
		testExpire();
		testLuaScript();
		testRedisScript();
		testLuaFile();
	}

	public static void testTransaction() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
			ops.multi();
			ops.boundValueOps("key1").set("value1");
			// 註意由於命令只是進入隊列,而沒有被執行,所以此處采用get命令,而value卻返回為null
			String value = (String) ops.boundValueOps("key1").get();
			System.out.println("事務執行過程中,命令入隊列,而沒有被執行,所以value為空:value=" + value);
			// 此時list會保存之前進入隊列的所有命令的結果
			List list = ops.exec();// 執行事務
			// 事務結束後,獲取value1
			value = (String) redisTemplate.opsForValue().get("key1");
			return value;
		};
		// 執行Redis的命令
		String value = (String) redisTemplate.execute(callBack);
		System.out.println(value);
	}
    public static void testPipeline() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		// 使用Java8的Lambda表達式
		SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
			for (int i = 0; i < 100; i++) {
				int j = i + 1;
				ops.boundValueOps("pipeline_key_" + j).set("pipeline_value_" + j);
				ops.boundValueOps("pipeline_key_" + j).get();
			}
			return null;
		};
		long start = System.currentTimeMillis();
		// 執行Redis的流水線命令
		List resultList = redisTemplate.executePipelined(callBack);
		long end = System.currentTimeMillis();
		System.err.println(end - start);
	}

	private static JedisPool getPool() {
		JedisPoolConfig poolCfg = new JedisPoolConfig();
		// 最大空閑數
		poolCfg.setMaxIdle(50);
		// 最大連接數
		poolCfg.setMaxTotal(100);
		// 最大等待毫秒數
		poolCfg.setMaxWaitMillis(20000);
		// 使用配置創建連接池
		JedisPool pool = new JedisPool(poolCfg, "localhost");
		// 從連接池中獲取單個連接
		Jedis jedis = pool.getResource();
		// 如果需密碼
		// jedis.auth("password");
		return pool;
	}

	public static void testJedisPipeline() {
		JedisPool pool = getPool();
		Jedis jedis = pool.getResource();
		long start = System.currentTimeMillis();
		// 開啟流水線
		Pipeline pipeline = jedis.pipelined();
		// 這裏測試10萬條的讀寫2個操作
		for (int i = 0; i < 100; i++) {
			int j = i + 1;
			pipeline.set("pipeline_key_" + j, "pipeline_value_" + j);
			pipeline.get("pipeline_key_" + j);
		}
		// pipeline.sync();//這裏只執行同步,但是不返回結果
		// pipeline.syncAndReturnAll();將返回執行過的命令返回的List列表結果
		List result = pipeline.syncAndReturnAll();
		long end = System.currentTimeMillis();
		// 計算耗時
		System.err.println("耗時:" + (end - start) + "毫秒");
	}

	public static void testPubSub() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		String channel = "chat";
		redisTemplate.convertAndSend(channel, "I am lazy!!");
	}

	public static void testExpire() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		redisTemplate.execute((RedisOperations ops) -> {
			ops.boundValueOps("key1").set("value1");
			String keyValue = (String) ops.boundValueOps("key1").get();
			Long expSecond = ops.getExpire("key1");
			System.err.println(expSecond);
			boolean b = false;
			b = ops.expire("key1", 120L, TimeUnit.SECONDS);
			b = ops.persist("key1");
			Long l = 0L;
			l = ops.getExpire("key1");
			Long now = System.currentTimeMillis();
			Date date = new Date();
			date.setTime(now + 120000);
			ops.expireAt("key", date);
			return null;
		});
	}

	public static void testLuaScript() {
		// 如果是簡單的對象,使用原來的封裝會簡易些
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		// 如果是簡單的操作,使用原來的Jedis會簡易些
		Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
		// 執行簡單的腳本
		String helloJava = (String) jedis.eval("return ‘hello java‘");
		System.out.println(helloJava);
		// 執行帶參數的腳本
		jedis.eval("redis.call(‘set‘,KEYS[1], ARGV[1])", 1, "lua-key", "lua-value");
		String luaKey = (String) jedis.get("lua-key");
		System.out.println(luaKey);
		// 緩存腳本,返回sha1簽名標識
		String sha1 = jedis.scriptLoad("redis.call(‘set‘,KEYS[1], ARGV[1])");
		// 通過標識執行腳本
		jedis.evalsha(sha1, 1, new String[] { "sha-key", "sha-val" });
		// 獲取執行腳本後的數據
		String shaVal = jedis.get("sha-key");
		System.out.println(shaVal);
		// 關閉連接
		jedis.close();
	}

	public static void testRedisScript() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		// 定義默認腳本封裝類
		DefaultRedisScript<Role> redisScript = new DefaultRedisScript<Role>();
		// 設置腳本
		redisScript.setScriptText("redis.call(‘set‘, KEYS[1], ARGV[1])  return redis.call(‘get‘, KEYS[1])");
		// 定義操作的key列表
		List<String> keyList = new ArrayList<String>();
		keyList.add("role1");
		// 需要序列化保存和讀取的對象
		Role role = new Role();
		role.setId(1L);
		role.setRoleName("role_name_1");
		role.setNote("note_1");
		// 獲得標識字符串
		String sha1 = redisScript.getSha1();
		System.out.println(sha1);
		// 設置返回結果類型,如果沒有這句話,結果返回為空
		redisScript.setResultType(Role.class);
		// 定義序列化器
		JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
		// 執行腳本
		// 第一個是RedisScript接口對象,第二個是參數序列化器
		// 第三個是結果序列化器,第四個是Reids的key列表,最後是參數列表
		Role obj = (Role) redisTemplate.execute(redisScript, serializer, serializer, keyList, role);
		// 打印結果
		System.out.println(obj);
	}

	public static void testLuaFile() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
		// 讀入文件流
		File file = new File("E:\\study_fold\\Java_EE_SSM\\ssm\\Chapter19\\src\\test.lua");
		byte[] bytes = getFileToByte(file);
		Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
		// 發送文件二進制給Redis,這樣REdis就會返回sha1標識
		byte[] sha1 = jedis.scriptLoad(bytes);
		// 使用返回的標識執行,其中第二個參數2,表示使用2個鍵
		// 而後面的字符串都轉化為了二進制字節進行傳輸
		Object obj = jedis.evalsha(sha1, 2, "key1".getBytes(), "key2".getBytes(), "2".getBytes(), "4".getBytes());
		System.out.println(obj);
	}

	/**
	 * 把文件轉化為二進制數組
	 * 
	 * @param file
	 *            文件
	 * @return 二進制數組
	 */
	public static byte[] getFileToByte(File file) {
		byte[] by = new byte[(int) file.length()];
		try {
			InputStream is = new FileInputStream(file);
			ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
			byte[] bb = new byte[2048];
			int ch;
			ch = is.read(bb);
			while (ch != -1) {
				bytestream.write(bb, 0, ch);
				ch = is.read(bb);
			}
			by = bytestream.toByteArray();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return by;
	}
}

  輸出:

事務執行過程中,命令入隊列,而沒有被執行,所以value為空:value=null
value1

23


耗時:13毫秒

I am lazy!!
chat
chat
I am lazy!!
chat
chat
I am lazy!!
chat
chat

-1

hello java
lua-value
sha-val

731429de653665577edb661a6741c4083e103b77
com.ssm.chapter19.redis.pojo.Role@59474f18

2

Redis常用技術