首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Redis在项目中如何使用及相关知识?

  • 25-03-02 12:42
  • 4295
  • 12705
blog.csdn.net

一、简单介绍

redis最主要的功能:
	1.1 做缓存,一些经常查询的数据又不会修改的数据就可以放在redis中;
	1.2 可以做redis队列,比如短信邮件可以放入到redis队列中。
	1.3 redis-session共享
	1.4 redis-锁 
	缺点:数据多了会消耗内存,
	优点:但是查询数据库快,可以减轻数据库的压力。
	首先redis有16个数据库,那么根据数据库的下标去区分数据到底存入到那个数据库。数据是保存在内存中的,
	Redis是一个高效的内存数据库,他所支持包括 String、List 、Set、SotreSet 和Hash等数据类型的存储。
	在redis通常根据key查询value值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

二、redisRedsi缓存雪崩、缓存穿透、数据库和redis一致性等问题

2.1缓存雪鹏

定义:
	当 redis服务挂掉时,大量请求数据库,对数据库产生巨大的压力,导致数据库瘫痪。
场景:
     把所有存入redis的所有数据设置相同过期的时间,过期时间失效后,就会大量请求数据库。
如何解决?
   1、在缓存的时候我们给过期时间设置一个随机数,但是也要根据业务场景需求来设置
   2、事发前:实现redis的高可用、主从架构+sentinel 或者 redis cluster
   3、事发后:万一redis真的挂了、可以设置本地缓存ehcache+限流hystrix
   4、事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.2 缓存穿透:

定义:
	大量到数据库请求一些不存在的数据,查询一个数据库不存在的数据。请求的数据在缓存大量不命中,导致大量请求数据库。
场景:
	比如我们表的数据的id是从1开始的正数,如果在这里有黑客攻击我们的系统,会设置一些负数的id到数据库查询数据,
	查询出来返回的数据为null,在这里,由于缓存不命中,并且处于容错考虑,从数据库查询的数据为null就不写到redis,
	这将导致每次查询数据都会到数据库查询,失去了缓存的意义。这样数据库迟早也会挂掉
如何解决缓存穿透?
    1、由于请求的参数是不合法(-1) 每次请求都是不存在的数据,于是我们可以使用布隆过滤器(BloomFilter) 或者 压缩filter提前拦截,
    不合法就不能访问数据库。
    2、当我们从数据库查询出来的数据为null时,也把他设置到缓存redis中,下次请求的时候就到redis中查询了,
    在这里后台可以判断,如果为null,那么设置一个较短的过期时间,到期自动就失效,否则就是按正常操作。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.3 缓存与数据库双写一致性:

对于读操作流程:
     先到redis缓存中查询数据,如果为null,那么再到数据库查询出来再设置到redis中去,最后将数据返回给请求。
定义:
   如果只是简单查询,缓存数据和数据库数据没有什么问题,当我们更新的时候就可能导致数据库数据和缓存数据不一致了。
   数据库库存为 999  缓存数据为1000 这就是更新导致的情况。	
解决方案:
    1、比如操作菜单的时候,当我们增加 、删除、修改菜单时,操作成功之后就应该立刻根据菜单的key从redis缓存中把数据给删除,
  第二次查询 的时候肯定为null,从数据库查询再设置到redis中。这是马上见效情况,
    2、不是马上见效的情况,就是设置过期时间来确定,比如我们商城中web页面根据店铺搜索出来的数据有最新的4张照片
  当我们在商家后台添加一个商品时,就应该显示在最新添加的照片,此时就不能按照删除key来操作redis了,因为多个商家添加多个商品,
  就失去了缓存的意义,那么会根据用户需求来设置过期时间,这里的redis缓存就可能和数据库不一致,需要过期时间来控制数据。
  因为缓存时间到了,就会被删除,再到数据库查询设置到redis中去。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.3.1高并发情况下:

操作一:
先更新数据库,再删除缓存
   正常的情况是这样的:
      1、 先操作数据库,成功
      2、再删除缓存,也成功
      3、 如果原子性被破坏了
  第一步成功(操作数据库),第二步失败(删除缓存),会导致数据库里是新数据,而缓存里是旧数据。
  如果第一步(操作数据库)就失败了,我们可以直接返回错误(Exception),不会出现数据不一致。
  如果在高并发的场景下,出现数据库与缓存数据不一致的概率特别低,也不是没有:
       缓存刚好失效
       线程A查询数据库,得一个旧值
       线程B将新值写入数据库
       线程B删除缓存
       线程A将查到的旧值写入缓存
   要达成上述情况,还是说一句概率特别低:
       因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,
      而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率
      基本并不大。对于这种策略,其实是一种设计模式:Cache Aside Pattern
解决一:
	删除缓存失败的解决思路:
		将需要删除的key发送到消息队列中
		自己消费消息,获得需要删除的key
		不断重试删除操作,直到成功
	
	
操作二:	
		先删除缓存,再更新数据库
			正常情况是这样的:
			  1、先删除缓存,成功;
			  2、再更新数据库,也成功;
			  3、如果原子性被破坏了:
			第一步成功(删除缓存),第二步失败(更新数据库),数据库和缓存的数据还是一致的。
			如果第一步(删除缓存)就失败了,我们可以直接返回错误(Exception),数据库和缓存的数据还是一致的。
			看起来是很美好,但是我们在并发场景下分析一下,就知道还是有问题的了:
				 线程A删除了缓存
				 线程B查询,发现缓存已不存在
				 线程B去数据库查询得到旧值
				 线程B将旧值写入缓存
				 线程A将新值写入数据库
		 所以也会导致数据库和缓存不一致的问题。
解决二:
			并发下解决数据库与缓存不一致的思路:
			将删除缓存、修改数据库、读取缓存等的操作积压到队列里边,实现串行化。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

在这里插入图片描述

对比两种策略:

	先删除缓存、再更新数据库
			在高并发下表现的不如意,在原子性被破环时表现优异
	先更新数据库,再删除缓存(Cache Aside Pattern设计模式))
			在高并发先表现优异,在原子性被破坏时表现不如意
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

三、redis分页加排序操作

介绍:
	Redis是一个高效的内存数据库,他所支持包括 String、List 、Set、SotreSet 和Hash登数据类型的存储。在redis通常根据key查询
	value值,redis没有条件查询,在面对一些需要分页或者排序的场景时(培训 时间线)redis就不太好处理。
	
项目中案列使用:
      需要将每个主题下的用户的评论组装好写到redis中,每个主题会有一个topicId,每一条评论会和topicid关联起来,
  得到的大致数据模型为{ topicId: 'xxxxxxxx', comments: [ { username: 'niuniu', createDate: 1447747334791, 
  content: '在Redis中分页', commentId: 'xxxxxxx', reply: [ { content: 'yyyyyy' username: 'niuniu' }, ... ] }, ... ]}
      将评论数据从mysql查询出来组装好存入到redis后,从上面的数据可以看出都是key value形式,所以会使用到hash
   进行存储, hash肯定是不能分页的,那么可能会用到StoreSet
   
   五大类型介绍:
		1、String:主要用于存储字符串、显然不支持分页排序
		2、Hash: 主要用于存储key-value形式数据,评论模型中全是key-value,所以会使用到
		3、Set:  主要存储无序集合  无序 排除
		
		4、stortSet :主要存储有序集合,StortSet添加元素指令Zadd  key  score member [[score , member] ] 
		会给每个元素的member绑定一个用于排序的值score , StroreSet会很据score的值的大小进行排序,
		在这里可以将一个需要排序的字段当作score排序,StoreSet指令中的Zervrange  key  start stop由可以返回指定区间的成员,
		意思就是可以用来分页 , 还有一个好处就是SortedSet的指令Zerm  key member 可以根据key移除指定的成员,
		可以满足删除评论的要求,所以 SortedSet是用来分页 的。
		
		5、List: 主要用来存储一个列表,列表中的每一个元素按元素的插入时的顺序进行保存,如果我们将评论模型按字段(排好)放入redis后再
		插入list中,就可以做到排序,但是其中数据删掉就乱了,list中的lrange  key start stop 指令还能做分页,
		那么单纯使用list也能做到分页排序了,但是在这里,如果评论被删除,就需要到数据库重新查询一次放入到redis中,
		这样的话性能也不好,而且也不太优雅,就需要更新redis中的数据了,如果在这里可以删除指定的数据那就更好了,
		但是list中有lpop,rpop这两个指令,他们只能删除列的表头和表尾的数据,不能指定删除,所以在这里list也不太好,
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

下图所示:

在这里插入图片描述在这里插入图片描述

     在上图的SortSet结构中将每个主题的topicId作为set的key,将与该主题关联的评论的createDate和commentId分别作为set的score
和member,commentId的顺序就根据createDate的大小进行排列。
     当需要查询某个主题某一页的评论时,就可主题的topicId通过指令zrevrange topicId (page-1)×10   (page-1)×10+perPage这样就能
     找出某个主题下某一页的按时间排好顺序的所有评论的commintId。page为查询第几页的页码,perPage为每页显示的条数。
     当找到所有评论的commentId后,就可以把这些commentId作为key去Hash结构中去查询该条评论对应的内容。
     这样就利用SortSet和Hash两种结构在Redis中达到了分页和排序的目的。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述在这里插入图片描述

四、redis-session操作

四、大家最喜欢的代码操作:

4.1 properties中的配置:

	redis.host=127.0.0.1     本机地址 需要开启
	redis.port=6379            redis的端口号
	redis.database=15     redis数据库的下标,有了这个操作就是把数据存入到下标为15的数据库中
	redis.password=20162016  redis密码
	redis.timeout=3000    超时时间
  • 1
  • 2
  • 3
  • 4
  • 5

4.2 applicationContext.xml中的配置:

	

    
    
    
    
    




    
    
    
    
    
    

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4.2 导包pom.xml:

 
      redis.clients
      jedis
      2.9.0
      
  • 1
  • 2
  • 3
  • 4
  • 5

五、java代码

5.1 、工具类

@Component
public class RedisHelper {

@Autowired
private JedisPool jedisPool;  //如果注入这个就是默认把数据存入到redis的第一个数据库

@Autowired
private JedisPool jedisPool1;  //如果注入这个就是把数据存入到redis的16个数据库 下标为15
 /**
 * cache前缀
 */
@Value("${cachePrefix}")   //这个写一个前缀 。类似于一个文件夹 在RedisDesktopManager 可视化工具中可以查看
private String cachePrefix;


/**
 * 根据key获取缓存数据
 *
 * @param key
 * @return
 */
public String get(String key) {
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.get(cachePrefix + key);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 获取指定前缀的所有key
 *
 * @param prefix
 * @return
 */
public Set keys(String prefix) {
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.keys(cachePrefix + prefix);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 根据key设置缓存数据,如果以前存在更新,如果以前没有添加
 *
 * @param key
 * @param value
 */
public void set(String key, String value) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.set(cachePrefix + key, value);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 根据key设置缓存数据,如果以前存在更新,如果以前没有添加
 *
 * @param key
 * @param value
 * @param expire 过期时间,单位秒
 */
public void set(String key, String value, int expire) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.set(cachePrefix + key, value);
        jedis.expire(cachePrefix + key, expire);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 根据key删除缓存数据
 *
 * @param key
 */
public void del(String key) {


    Jedis jedis = jedisPool.getResource();
    try {
        jedis.del(cachePrefix + key);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 设置集合   这个的话简单介绍一下,他主要在我们的项目中和es结合使用的,比如订单和商品是发布的es中,因为es查询速度很快
 * 那么可变参数 我们只需要把商品的id和订单的id存入到一个数组中,再调用此方法,到时候再es中根据redis中下面smembers这个方法
 * 拿到所有的id,再到数据库查询出来一个对象存入到es中,到时候商品和订单就是从数据库查询出来的。
 * @param name
 * @param value
 */
public void sadd(String name, String... value) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.sadd(cachePrefix + name, value);

    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 获取集合  
 * @param name
 */
public void scard(String name){
    Jedis jedis = jedisPool.getResource();
    try {
        Long scard = jedis.scard(cachePrefix + name);
        System.out.println("scard=="+scard);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 获取指定键名的集合中的所有成员
 *
 * @param name
 * @return
 */
public Set smembers(String name) {
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.smembers(cachePrefix + name);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 返回集合中的随机元素
 *
 * @param name
 * @param count
 * @return
 */
public List srandmember(String name, int count) {
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.srandmember(cachePrefix + name, count);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 移除集合
 *
 * @param name
 * @return
 */
public void spop(String name) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.spop(cachePrefix + name);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 移除集合中的一个或多个元素
 *
 * @param name
 * @return
 */
public void srem(String name, String... key) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.srem(cachePrefix + name, key);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 添加到hash
 *
 * @param name
 * @param key
 * @param value
 */
public void hset(String name, String key, String value) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.hset(cachePrefix + name, key, value);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 从hash中读取
 *
 * @param name
 * @param key
 * @return
 */
public String hget(String name, String key) {
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.hget(cachePrefix + name, key);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 从hash中删除
 *
 * @param name
 * @param key
 */
public void hdel(String name, String key) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.hdel(cachePrefix + name, key);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 设置key的过期时间
 * @param name
 * @param seconds
 */
public void expire(String name, int seconds){
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.expire(cachePrefix + name, seconds);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}

/**
 * 检查键是否存在
 * @param name
 * @return
 */
public Boolean exists(String name){
    Jedis jedis = jedisPool.getResource();
    try {
        return jedis.exists(cachePrefix + name);
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260

  • 1

5.2、redis队列代码

@Component
public class QueueHelper {

    @Autowired
    private JedisPool jedisPool;

    /**
     * Queue前缀
     */
    @Value("${queuePrefix}")
    private String prefix;

    /**
     * 读取队列
     * @return
     */
    public String pop(String name) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.lpop(prefix + name);
        } finally {
            jedisPool.returnResourceObject(jedis);
        }
    }

    /**
     * 写入队列   简单介绍一下:value就是我们发送短信的对象,比如把电话号码 、发布的内容、封转到一个对象中,再把此对象转换为json字符串的		格式传进来,到时候再定时任务中再调上面那个方法查询出来,再去调发布短信和邮件的方法就可以了,注意:此时的定时任务需要配置为一直运行。
     * 
     * @param value
     */
    public void push(String name, String value) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.rpush(prefix + name, value);
        } finally {
            jedisPool.returnResourceObject(jedis);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

5.3、redis锁

package net.shopnc.b2b2c.lbjt;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.Collections;

@Component
public class SaveGoodsIdToRedisHelper {


private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";

private static final Long RELEASE_SUCCESS = 1L;

private static String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

//在这里 redis锁的单位是毫秒
public static final int EXPIRATIONTIME = 180000;


@Autowired
private JedisPool jedisPool2;

/**
 * Queue前缀
 */
@Value("${queuePrefix}")
private String prefix;

/**
 * 检查键是否存在
 *
 * @param name
 * @return
 */
public Boolean exists(String name) {
    Jedis jedis = jedisPool2.getResource();
    try {
        return jedis.exists(prefix + name);
    } finally {
        jedisPool2.returnResourceObject(jedis);
    }
}


//设置订单锁
public void setOrderLock(String name, String requestId) {
    Jedis jedis = jedisPool2.getResource();
    try {

        String set = jedis.set(name, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, EXPIRATIONTIME);
        // System.out.println(set);

    } finally {
        jedisPool2.returnResourceObject(jedis);
    }
}



//判断key是否存在
public String getOrderValue(String name) {
    Jedis jedis = jedisPool2.getResource();
    try {
        String s = jedis.get(name);
        return s;
    } finally {
        jedisPool2.returnResourceObject(jedis);
    }

}

//订单解锁
public String getOrderLock(String name, String value) {
    Jedis jedis = jedisPool2.getResource();
    try {

        Object eval = jedis.eval(script, Collections.singletonList(name), Collections.singletonList(value));
        return "";
    } finally {
        jedisPool2.returnResourceObject(jedis);
    }

}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

5.4、redis分页排序

   //redis分页
    public  List  redisPageSize(String key) {

    int pageNo = 2;
    int pageSize = 2;
    Jedis jedis = jedisPool.getResource();
    try {

        int start = pageSize * (pageNo - 1); // 因为redis中list元素位置基数是0  0   6
        int end = start + pageSize - 1;   //5     11  指的是下标


        List results = jedis.lrange(key, start, end);// 从start算起,start算一个元素,到结束那个元素
        for (String str : results) {
            System.out.println("str====" + str);
        }
        return results;
    } finally {
        jedisPool.returnResourceObject(jedis);
    }
}


 	//redis分页+排序
    public void redisQueryPageAndSort() {

    Jedis jedis = jedisPool1.getResource();
    Map map = new HashMap();
    
    for(int i=0 ; i<10 ; i++){
        jedis.zadd("topicId", i, "name" + i);
        map.put("name"+i , "到底怎么回事"+i);
    }


    jedis.hmset("user", map);

    int currentPage =1;
    int pageSize = 10 ;
    int offset = (currentPage-1)*10;

    LinkedHashSet sets = (LinkedHashSet) jedis.zrevrangeByScore("topicId" ,"80", "1", offset, pageSize);

    String s1 = sets.toString();


    System.out.println(sets.toString());
    Object[] objects = sets.toArray();

    String[] strings = new String[sets.size()];

    for(int i=0 ; i 注意结果是一个泛型的List

    //第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key可以跟多个,是可变参数

    List rsmap = jedis.hmget("user", strings);
    for (String s : rsmap) {
        System.out.println(s);
    }

    System.out.println(rsmap);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
注:本文转载自blog.csdn.net的关注我不迷路 带你上高速的文章"https://blog.csdn.net/weixin_42075468/article/details/89040452"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top