原理

SORT key 
[BY pattern] 
[LIMIT offset count] 
[GET pattern [GET pattern ...]] 
[ASC|DESC] 
[ALPHA] [STORE destination]

返回或保存给定列表、集合、有序集合 key 中经过排序的元素。

Redis 命令

对于如下结构:

id nicke updateTime
111 jack 1493709972068
2111 tom 1495437972186
2122 marry 1494573972186

Redis存储:

执行:

127.0.0.1:6379> sadd testkey  0 1 2
(integer) 3

查看:

127.0.0.1:6379> smembers testkey
1) "0"
2) "1"
3) "2"

执行:

127.0.0.1:6379> hset testkey1 data {\"id\":2111,\"nick\":\"tom\",\"updateTime\":1495437972186} updateTime 20170522152612 id 2111

查看:

127.0.0.1:6379> hgetall testkey1
1) "data"
2) "{\"id\":2111,\"nick\":\"tom\",\"updateTime\":1495437972186}"
3) "updateTime"
4) "20170522152612"
5) "id"
6) "2111"

……

查看:

127.0.0.1:6379> keys testkey*
1) "testkey2"
2) "testkey0"
3) "testkey1"
4) "testkey"

按照id降序:

127.0.0.1:6379> SORT testkey by testkey*->id  get testkey*->data desc limit 0 3
1) "{\"id\":2122,\"nick\":\"marry\",\"updateTime\":1494573972186}"
2) "{\"id\":2111,\"nick\":\"tom\",\"updateTime\":1495437972186}"
3) "{\"id\":111,\"nick\":\"jack\",\"updateTime\":1493709972068}"

BY testkey*->id: 这个部分要求 Redis 从与 testkey 相关的所有键中获取 id 字段

Java 实现

生成排序列表:


	/**
	 * generate sort list
	 * @param ns
	 * @param key
	 * @param list
	 * @param sortFileds
     * @param <T>
	 * @return
	 */
	public <T> List<T> generateSortList(String ns, String key, List<T> list, String ... sortFileds) {
		for (int i = 0; i < list.size(); i++) {
			try {
                Map<String, String> hmMap = new HashMap<>();
                T t = list.get(i);
			    for(String sortFiled:sortFileds){
                    Field field = t.getClass().getDeclaredField(sortFiled);
                    field.setAccessible(true);
                    Object value = field.get(t);

                    if(value instanceof Date){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                        hmMap.put(field.getName(), sdf.format(value));
                    }else {
                        hmMap.put(field.getName(), value.toString());
                    }
                }
				// 源数据
				hmMap.put("data", JSON.toJSONString(t));

				redisTemplate.opsForHash().putAll(generateKey(ns, key) + i, hmMap);
				redisTemplate.opsForSet().add(generateKey(ns, key), i + "");

			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}

		return null;

	}

排序接口:

  /**
     * redis list sort
     * @param ns
     * @param key
     * @param cla
     * @param orderType
     * @param sortfield
     * @param offset
     * @param count
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> sortList(String ns, String key, Class<T> cla,String orderType,String sortfield, int offset, int count) {

        SortParameters.Order order = SortParameters.Order.valueOf(orderType);
        SortParameters.Range range = new SortParameters.Range(offset, count);

        SortQuery<String> query = SortQueryBuilder.sort(generateKey(ns, key))
                .by(generateKey(ns, key) + "*->" + sortfield)
                .get(generateKey(ns, key) + "*->data")
                .order(order)
                .limit(range)
                .build();

        List<Object> results = redisTemplate.sort(query);
        List<T> resultList = new ArrayList<>();
        for (Object result : results) {
            resultList.add(JSON.parseObject((String) result, cla));
        }

        return resultList;
	}

测试:

/**
 * Created by dinozhang on 2017/5/8.
 */
public class RedisTest {


	private static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("redis.xml");
	private static RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) applicationContext.getBean("redisTemplate");

	public static void main(String[] args) {
		UserDO userDo = new UserDO();
		userDo.setId(111l);
		userDo.setUpdateTime(new DateTime().withDayOfMonth(2).toDate());
		userDo.setNick("jack");

		UserDO userDo1 = new UserDO();
		userDo1.setId(2111l);
		userDo1.setNick("tom");
		userDo1.setUpdateTime(new DateTime().withDayOfMonth(22).toDate());

		UserDO userDo2 = new UserDO();
		userDo2.setId(2122l);
		userDo2.setNick("marry");
		userDo2.setUpdateTime(new DateTime().withDayOfMonth(12).toDate());

		List<UserDO> userDOs = new ArrayList<>();
		userDOs.add(userDo);
		userDOs.add(userDo1);
		userDOs.add(userDo2);
		
		String[] sortFields = { "id", "updateTime" };

		generateSortList("testkey", userDOs, sortFields);
		List<UserDO> userDOs1 = sortList("testkey", UserDO.class, "DESC", "id", 0, 5);
		List<UserDO> userDOs2 = sortList("testkey", UserDO.class, "DESC", "updateTime", 0, 5);
		System.out.println(userDOs1.size());

	}
}

Redis配置文件

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 连接池配置 最大空闲数、最大连接数、最长等待时间、连接是否可用 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="10" />
        <property name="maxTotal" value="20" />
        <property name="maxWaitMillis" value="300" />
        <property name="testOnBorrow" value="true" />
    </bean>

    <!-- 连接配置 地址、端口 -->
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
        <property name="hostName" value="127.0.0.1" />
        <property name="port" value="6379" />
        <property name="password" value="" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>

    <!-- 暴露一个redisTemplate 用作redis一系列操作 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
        <!--指定序列化方式避免key值出现\xac\xed\x00\x05t\x00-->
        <property name="KeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        </property>
        <property name="ValueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        </property>
        <property name="HashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        </property>
        <property name="HashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        </property>
    </bean>
</beans>