搜档网
当前位置:搜档网 › 【黑马程序员】分布式缓存技术redis学习系列----深入理解Spring Redis的使用

【黑马程序员】分布式缓存技术redis学习系列----深入理解Spring Redis的使用

【黑马程序员】分布式缓存技术redis学习系列----深入理解Spring Redis的使用
【黑马程序员】分布式缓存技术redis学习系列----深入理解Spring Redis的使用

【黑马程序员】分布式缓存技术redis学习系列----深入理解Spring Redis的使用

关于spring redis框架的使用,网上的例子很多很多。但是在自己最近一段时间的使用中,发现这些教程都是入门教程,包括很多的使用方法,与spring redis丰富的api大相径庭,真是浪费了这么优秀的一个框架。

Spring-data-redis为spring-data模块中对redis的支持部分,简称为“SDR”,提供了基于jedis 客户端API的高度封装以及与spring容器的整合,事实上jedis客户端已经足够简单和轻量级,而spring-data-redis反而具有“过度设计”的嫌疑。

jedis客户端在编程实施方面存在如下不足:

1) connection管理缺乏自动化,connection-pool的设计缺少必要的容器支持。

2) 数据操作需要关注“序列化”/“反序列化”,因为jedis的客户端API接受的数据类型为string 和byte,对结构化数据(json,xml,pojo)操作需要额外的支持。

3) 事务操作纯粹为硬编码

4) pub/sub功能,缺乏必要的设计模式支持,对于开发者而言需要关注的太多。

1. Redis使用场景

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

我们都知道,在日常的应用中,数据库瓶颈是最容易出现的。数据量太大和频繁的查询,由于磁盘IO 性能的局限性,导致项目的性能越来越低。

这时候,基于内存的缓存框架,就能解决我们很多问题。例如Memcache ,Redis 等。将一些频繁使用的数据放入缓存读取,大大降低了数据库的负担。提升了系统的性能。其实,对于hibernate 以及Mybatis 的二级缓存,是同样的道理。利用内存高速的读写速度,来解决硬盘的瓶颈。

2. 配置使用redis

项目的整体结构如下:

在applicationContext-dao.xml 中配置如下:

[AppleScript] 纯文本查看 复制代码

?

01 02 03 04 05 06 07 0

encoding="UTF-8"?>

xmlns:mongo="https://www.sodocs.net/doc/5218471077.html,/schema/data/mong o"

xmlns:aop="https://www.sodocs.net/doc/5218471077.html,/schema/aop" xsi:schemaLocation="https://www.sodocs.net/doc/5218471077.html,/schema/be ans

[url=https://www.sodocs.net/doc/5218471077.html,/schema/b eans/spring-beans-3.0.xsd]https://www.sodocs.net/doc/5218471077.html,/schema/bean s/spring-beans-3.0.xsd[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/d

8 0 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3

ata/mongo]https://www.sodocs.net/doc/5218471077.html,/schema/data/mongo[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/d ata/mongo/spring-mongo.xsd]https://www.sodocs.net/doc/5218471077.html,/schema/dat a/mongo/spring-mongo.xsd[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/c ontext]https://www.sodocs.net/doc/5218471077.html,/schema/context[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/context/s pring-context-3.0.xsd]https://www.sodocs.net/doc/5218471077.html,/s ...

ing-context-3.0.xsd[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/aop]http: //https://www.sodocs.net/doc/5218471077.html,/schema/aop[/url]

[url=https://www.sodocs.net/doc/5218471077.html,/schema/aop/sprin g-aop-3.0.xsd]https://www.sodocs.net/doc/5218471077.html,/schema/aop/spring-aop-3 .0.xsd[/url]">

location="classpath:database.properties" />

class="redis.clients.jedis.JedisPoolConfig">

value="${redis.maxIdle}" />

value="${redis.maxActive}" />

value="${redis.maxWait}" />

value="${redis.testOnBorrow}" />

class="org.springframework.data.redis.connection.jedis.JedisConnecti onFactory">

value="${redis.host}"/>

value="${redis.pass}"/>

class="org.springframework.data.redis.serializer.StringRedisSerializ

0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4

er"/>

class="org.springframework.data.redis.serializer.JdkSerializationRed isSerializer"/>

class="org.springframework.data.redis.core.RedisTemplate">

ref="connectionFactory" />

ref="stringSerializer"/>

ref="stringSerializer"/>

ref="stringSerializer" />

ref="hashSerializer"/>

database.properties配置文件如下:

[AppleScript] 纯文本查看复制代码

?

1 2 3 4 5 6 7redis.maxIdle=10 redis.maxActive=20

redis.maxWait=10000

redis.testOnBorrow=true

redis.host=192.168.1.76

redis.port=6379

redis.pass=password1

spring-data-redis提供了多种serializer策略,这对使用jedis的开发者而言,实在是非常便捷。sdr提供了4种内置的serializer:

?JdkSerializationRedisSerializer:使用JDK的序列化手段(serializable

接口,ObjectInputStrean,ObjectOutputStream),数据以字节流存储,

POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过

ObjectInputStream/ObjectOutputStream进行序列化操作,最终

redis-server中将存储字节序列,是目前最常用的序列化策略。

?StringRedisSerializer:字符串编码,数据以string存储,Key或者value 为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直

接封装。是最轻量级和高效的策略。

?JacksonJsonRedisSerializer:json格式存储,jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json

格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】?OxmSerializer:xml格式存储,提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的

数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略,其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。针对“序列化和发序列化”中JdkSerializationRedisSerializer 和StringRedisSerializer是最基础的策略,原则上,我们可以将数据存储为任何格式以便应用程序存取和解析(其中应用包括app,hadoop等其他工具),不过在设计时仍然不推荐直接使用“JacksonJsonRedisSerializer”和“OxmSerializer”,因为无论是json还是xml,他们本身仍然是String。如果你的数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer 而不是JdkSerializationRedisSerializer。

RedisTemplate中需要声明4种serializer,默认为“JdkSerializationRedisSerializer”:

1) keySerializer :对于普通K-V操作时,key采取的序列化策略

2) valueSerializer:value采取的序列化策略

3) hashKeySerializer:在hash数据结构中,hash-key的序列化策略

4) hashValueSerializer:hash-value的序列化策略

无论如何,建议key/hashKey采用StringRedisSerializer。

spring-data-redis针对jedis提供了如下功能:

1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类

2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口

?ValueOperations:简单K-V操作

?SetOperations:set类型数据操作

?ZSetOperations:zset类型数据操作

?HashOperations:针对map类型的数据操作

?ListOperations:针对list类型的数据操作

3. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations:

?BoundValueOperations

?BoundSetOperations

?BoundListOperations

?BoundSetOperations

?BoundHashOperations

3. RedisTemplate的使用

这个类作为一个模版类,提供了很多快速使用redis的api,而不需要自己来维护连接,事务。最初的时候,我创建的BaseRedisDao是继承自这个类的。继

承的好处是我的每个Dao中,都可以自由的控制序列化器,自由的控制自己是否需要事务,这个先不需要了解,跟着我目前的这种配置方法来即可。template 提供了一系列的operation,比如

valueOperation,HashOperation,ListOperation,SetOperation等,用来操作不同数据类型的Redis。并且,RedisTemplate还提供了对应的

*OperationsEditor,用来通过RedisTemplate直接注入对应的Operation。核心代码:

[AppleScript] 纯文本查看复制代码

?

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24package com.npf.dao.impl;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Repository;

import com.npf.dao.StudentDao;

import com.npf.model.Student;

@Repository

public class StudentDaoImpl implements StudentDao{

@Autowired

private RedisTemplate redisTemplate;

@Resource(name="redisTemplate")

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

private HashOperations opsForHash;

public static final String STUDENT = "student";

@Override

public void save(Student student) {

opsForHash.put(STUDENT, student.getId(), student);

}

@Override

public Student find(String id) {

Student student = opsForHash.get(STUDENT, id);

return student;

}

@Override

public void delete(String id) {

opsForHash.delete(STUDENT, id);

}

@Override

public void update(Student student) {

opsForHash.put(STUDENT, student.getId(), student);

}

@Override

public List findAll() {

Map entries =

opsForHash.entries(STUDENT);

List stuList = new ArrayList();

for(Entry entry :

entries.entrySet()){

stuList.add(entry.getValue());

}

return stuList;

}

}

控制层代码如下:

[AppleScript] 纯文本查看复制代码

?

01 02 03 04 05 06 07 08 09 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 40package com.npf.controller;

import java.util.List;

import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam;

import com.npf.model.Student;

import com.npf.service.StudentService;

@Controller

public class StudentController {

@Autowired

private StudentService studentService;

@RequestMapping("/student/save")

public String saveStudent(Student student){

String id = UUID.randomUUID().toString();

System.out.println(id);

student.setId(id);

studentService.save(student);

return "redirect:/student/find/all";

}

@RequestMapping("/student/update")

public String updateStudent(Student student){

studentService.update(student);

return "redirect:/student/find/all";

}

@RequestMapping("/student/to/save/form")

public String toSaveStudentForm(){

return "save";

}

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

@RequestMapping("/student/delete")

public String deleteStudent(@RequestParam("id") String

id){

studentService.delete(id);

return "redirect:/student/find/all";

}

@RequestMapping("/student/to/update/form")

public String toUpdateStudentForm(@RequestParam("id") String id,Model model){

Student stu = studentService.find(id);

model.addAttribute("stu", stu);

return "update";

}

@RequestMapping("/student/find/all")

public String findStudents(Model model){

List stuList =

studentService.findAll();

model.addAttribute("stuList", stuList);

return "list";

}

}

Redis面试专题及答案

redis和memcached什么区别?为什么高并发下有时单线程的redis比多线程的memcached效率要高? 区别: 1.mc可缓存图片和视频。rd支持除k/v更多的数据结构; 2.rd可以使用虚拟内存,rd可持久化和aof灾难恢复,rd通过主从支持数据备份; 3.rd可以做消息队列。 原因:mc多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。 redis主从复制如何实现的?redis的集群模式如何实现?redis的key是如何寻址的? 主从复制实现:主节点将自己内存中的数据做一份快照,将快照发给从节点,从节点将数据恢复到内存中。之后再每次增加新数据的时候,主节点以类似于mysql的二进制日志方式将语句发送给从节点,从节点拿到主节点发送过来的语句进行重放。 分片方式: -客户端分片 -基于代理的分片 ●Twemproxy ●codis -路由查询分片 ●Redis-cluster(本身提供了自动将数据分散到Redis Cluster不同节点的能力,整个数据集合的某个数据子集存储在哪个节点对于用户来说是透明的) redis-cluster分片原理:Cluster中有一个16384长度的槽(虚拟槽),编号分别为0-16383。每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,可以由用户指定,也可以在初始化的时候自动生成,只有Master才拥有槽的所有权。Master节点维护着一个16384/8字节的位序列,Master节点用bit来标识对于某个槽自己是否拥有。比如对于编号为1的槽,Master只要判断序列的第二位(索引从0开始)是不是为1即可。这种结构很容易添加或者删除节点。比如如果我想新添加个节点D, 我需要从节点A、B、C中得部分槽到D上。 使用redis如何设计分布式锁?说一下实现思路?使用zk可以吗?如何实现?这两种有什么区别? redis: 1.线程A setnx(上锁的对象,超时时的时间戳t1),如果返回true,获得锁。 2.线程B 用get获取t1,与当前时间戳比较,判断是是否超时,没超时false,若超时执行第3步; 3.计算新的超时时间t2,使用getset命令返回t3(该值可能其他线程已经修改过),如果 t1==t3,获得锁,如果t1!=t3说明锁被其他线程获取了。 4.获取锁后,处理完业务逻辑,再去判断锁是否超时,如果没超时删除锁,如果已超时,不用处理(防止删除其他线程的锁)。 zk: 1.客户端对某个方法加锁时,在zk上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点node1; 2.客户端获取该路径下所有已经创建的子节点,如果发现自己创建的node1的序号是最小的,就认为这个客户端获得了锁。 3.如果发现node1不是最小的,则监听比自己创建节点序号小的最大的节点,进入等待。

memcached&redis性能测试

一、Memcached 1.1、memcached简介 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web 应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。但是它并不提供冗余(例如,复制其hashmap条目);当某个服务器S停止运行或崩溃了,所有存放在S上的键/值对都将丢失。 Memcached由Danga Interactive开发,其最新版本发布于2010年,作者为Anatoly Vorobey和Brad Fitzpatrick。用于提升LiveJournal . com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。 1.2、Memcached是如何工作的 Memcached的神奇来自两阶段哈希(two-stage hash)。Memcached就像一个巨大的、存储了很多对的哈希表。通过key,可以存储或查询任意的数据。客户端可以把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,然后memcached节点通过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)。举个列子,假设有3个客户端1, 2, 3,3台memcached A, B, C:Client 1想把数 据”tuletech”以key “foo”存储。Client 1首先参考节点列表(A, B, C),计算key “foo”的哈希值,假设memcached B被选中。接着,Client 1直接connect 到memcached B,通过key “foo”把数据”tuletech”存储进去。Client 2使用与Client 1相同的客户端库(意味着阶段一的哈希算法相同),也拥有同样的

Redis的5个常见使用场景

Redis的5个常见使用场景概括 大家平时在使用Redis的时候有没有总结过Redis常用于哪些场景呢。下面科多老师带着大家一起来总结一下,希望能够帮助到各位同学。 1、会话缓存(Session Cache) 最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis 缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗? 幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis 来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。 2、全页缓存(FPC) 除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性 问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。 再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。 此外,对WordPress的用户来说,Pantheon有一个非常好的插件wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。 3、队列 Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis 能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。 如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这 里去查看。 4、排行榜/计数器 Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set) 和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可: 当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行: ZRANGE user_scores 0 10 WITHSCORES

memcache、redis、tair性能对比测试报告材料

memcache、redis、tair性能对比测试报告 第1章限制条件 前一周所做的分布缓存技术预言中有包括ehcache、memcache、redis、tair,还包括了基于MongoDB的分布式技术。测试中,考虑到各自功能的差异化特点,其中选择了memcache、redis、tair功能特性相近的缓存服务器进行性能对比,所以ehcache、MongoDB将不做为本次测试的规范,其原因如下: 1)Ehcache是组件级别的缓存,要搭建一个独立的缓存服务器,需要用到ehcache server 模块,这是个war包,能运行在web 容器中,决定整个缓存服务器性能的好坏因素太多,比如web服务器,集群方式等。跟memcache、redis、tair没有对比性。 2)MongoDB是面向文档的数据库,跟缓存没有可比性。 第2章测试场景概述 性能测试包括单机环境和分布式环境,主要针对memcache、redis、tair各缓存服务器在缓存了不同级别的数据下,多个线程并发操作向缓存set/get缓存数据,考虑到网络方面的负载,又将每次set/get操作的缓存数据的大小分为三个不同的级别:1KB,10KB,100KB,通过对上述的条件进行排列,取得以下的测试场景。 第3章单机环境测试 3.1.测试场景: 1.当各缓存的数据库空时,以单线程通过各缓存客户端set调用向服务端推送数据,比较 10000操作所消耗的时间,以上动作通过使用不同大小的单个缓存对象重复三次。2.在场景一完成的情况下,以单线程通过各缓存客户端get调用向服务端获取数据,比较 10000操作所消耗的时间,以上动作通过使用不同大小的单个缓存对象重复三次。3.并发200个线程通过缓存软件的客户set调用向服务端推送数据,每个线程完成10000 次的操作,比较服务器的tps大小,以上动作通过使用不同大小的单个缓存对象重复三

Redis面试题及答案

Redis 是一个基于内存的高性能key-value数据库。(有空再补充,有理解错误或不足欢迎指正) Reids的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的Key-Value DB。 Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务,用他的Set可以做高性能的tag系统等等。 另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。 Redis支持的数据类型 Redis通过Key-Value的单值不同类型来区分, 以下是支持的类型: Strings Lists Sets 求交集、并集 Sorted Set hashes

为什么redis需要把所有数据放到内存中? Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。 如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。 如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。 Redis是单进程单线程的 redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销 虚拟内存 当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大. 当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value. vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的. 可能会造成比较长时间的延迟,但是对数据完整性有很好的保证. 自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库 分布式 redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。 这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量。

redis-jedis笔记整理

启动Redis服务器 启动客户端 Redis命令目录key(建) 保存键值对set key value 查询指定键对象get key 删除给定键的对象del key1key2…

设置键过期时间EXPIRE key exptime 剩余时间ttl key 查看搜索有键值keys键 migrate指令(移动将数据移动另外一个数据) 将key原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功,key保证会出现在目标实例上,而当前实例上的key会被删除。 MOVE key db 将数据库的key移动到指定的数据库db当中。如果当前数据库(源数据库)和给定数据库(目标数据库)有相同的名字的给定key,或者key不存在于当前数据库,那么MOVE没有任何效果。因此,也可以利用这一特性,将MOVE当作锁(locking)原语(primitive)。

Obejct{refcount|encoding|idletime} 通常用在debug或者了解为了节省空间使用特殊的编码情况,当redis用作缓存时候,也可以通过OBJECT命令中的信息,决定key的驱逐策略. object refcount key:返回给定key引用所存储的值的次数. object encoding key:返回给定key所存储的值编码可以有 raw(一般字符串)或int(用字符串表示64位数字是为了节约空间)。 ziplist或linkedlist。ziplist是为节约大小较小的列表空间而作的特殊表示。 intset或者hashtable。intset是只储存数字的小集合的特殊表示。 zipmap或者hashtable。zipmap是小哈希表的特殊表示。 ziplist或者skiplist格式。ziplist用于表示小的有序集合,而skiplist则用于表 示任何大小的有序集合。 object idletime key:返回给定key自存储的空闲时间 persist key 将key从带生存时间转换为持久的不带生存时间.

redis系列三-springboot如何使用redis做缓存及缓存注解的用法总结

redis系列三-springboot如何使用redis做缓存及缓存注解的 用法总结 1. 概述 本文介绍spring boot 如何使用Redis做缓存,如何对redis 缓存进行定制化配置(如key的有效期)以及spring boot 如何初始化redis做缓存。使用具体的代码介绍了@Cacheable,@CacheEvict,@CachePut,@CacheConfig等注解及其属性的用法。 2. spring boot集成redis 2.1. application.properties 配置application.properties,包含如下信息: 指定缓存的类型 配置redis的服务器信息 请不要配置spring.cache.cache-names值,原因后面再说 ## 缓存 # spring.cache.cache-names=book1,book2 spring.cache.type=REDIS # REDIS (RedisProperties)

spring.redis.database=0 spring.redis.host=192.168.188.7 spring.redis.password= spring.redis.port=6379 spring.redis.pool.max-idle=8 spring.redis.pool.min-idle=0 spring.redis.pool.max-active=100 spring.redis.pool.max-wait=-1123456789101112131234567891 0111213 2.2. 配置启动类 @EnableCaching: 启动缓存 重新配置RedisCacheManager,使用新的配置的值 @SpringBootApplication @EnableCaching // 启动缓存 public class CacheApplication { private static final Logger log = LoggerFactory.getLogger(CacheApplication.class); public static void main(String[] args) { https://www.sodocs.net/doc/5218471077.html,("Start CacheApplication.. ");

【IT专家】Redis缓存Mysql模拟用户登录Java实现实例

本文由我司收集整编,推荐下载,如有疑问,请与我司联系Redis缓存Mysql模拟用户登录Java实现实例2016/03/18 1 这段时间在研究Redis,作为缓存界的新宠,现在使用它的公司越来越多。本文使用的是最新稳定版Redis3.0.实现的具体逻辑是: 1. 用户登录首先判断是否在redis缓存中,如果在redis缓存中,直接登录成功; 2. 若用户未在redis缓存,则访问Mysql,判断用户是否存在,如果不存在,则提示用户注册;如果存在,则登录成功; 3. 在mysql存在并登录成功的同时,将改条数据用Redis Hash类型进行缓存,并设置过期时间为30分钟; 4. 设置redis最大内存,若超出内存范围,则使用FIFO方式进行清除。 ?本文实现方式为最简单的模拟方式,有的代码有进一步封装得必要。 ?一、首先创建两个类,一个类连接Mysql,一个类连接Redis,并复写相关方法:?public class Mysql {public Connection conn;{try {Class.forName( com.mysql.jdbc.Driver conn=DriverManager.getConnection( jdbc:mysql://localhost/spring , root , root } catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}} ?public class Redis extends Jedis {public Jedis redis;{redis = new Jedis( 192.168.217.128 , 6379);redis.auth( root }// public static void main(String[] args) {// System.out.println(redis.get( name ));// System.out.println(redis.keys( * ));// // redis.sinter(keys);// }public String get(String key) {return redis.get( name }public String set(String key, String value) {return redis.set(key, value);}public Long del(String... keys) {return redis.del(keys);}// 键值增加字符public Long append(String key, String str) {return redis.append(key, str);}public Boolean exists(String key) {return redis.exists(key);}// Need researchpublic Long setnx(String key, String value) {return redis.setnx(key, value);}public String setex(String key, String value, int seconds) {return redis.setex(key, seconds, value);}public Long setrange(String key, String str, int offset)

Ehcache-Redis-Tair缓存性能对比

Ehcache/Redis/Tair缓存性能对比 后面介绍的不同方式都有测试数据,这些测试数据都是在同一的测试环境下得出的测试结果: 测试机器的配置如下: 64位5核CPU, E5620 @ 2.40GHz,内存8G CDN端缓存 由于计数器的价值并不在,具体的值是多少,尤其是对一些大访问量的商品来说个位或者十位的数据并没有什么意义,所以对这些热门商品的计数器访问可以采用定时更新的办法,可以将计数器的值直接缓存在CDN上或者后端Nginx的缓存中,定时再到数据库服务器上获取最新的计数器的值,这样能够大量减少对后端服务器的访问请求,而且计数器的数据量很小对缓存服务器的空间需求也不大。 改进的结构图如下: 直接在Nginx中利用Cache策略缓存住热门计数器的值,利用http协议的cache+max age来失效缓存的方式更新计数器的值。

优点: 实现方式简单,改动小,能够挡住热门商品的计数器访问请求,采用这种方式对查询请求来说,能达到类似于静态服务器的性能,如Nginx能达到2w的QPS 缺点:没有解决同一商品的计数器合并请求的问题,数据量会增大一倍对更新请求没有办法缓存,只能减少查询请求的压力 基于Java的存储方式 由于目前采用Nginx模块的方法开发,每次修改要重新编译Nginx服务器,所以想采用基于Java的方式,使得维护要容易一些。 选用Ehcache作为数据存储服务器,Ehcache也是基于内存存储,支持定时持久化功能,非常适合存储像计数器这种小数据类型。处理Http请求使用Tomcat容器,结构图如下: 处理逻辑采用一个servlet实现,并且在这个servlet中通过一致性Hash从Ehcache中获取计数器值。 在实际的部署结构中,可以将Tomcat和Ehcache部署在同一台机器上。 基于这种模式的测试结果如下:

基于Spark的机器学习资料66、后台服务代码架构:项目实际应用中redis缓存与数据库一致性问题解决

后台服务代码架构:项目实际应用中redis缓存与数据库一致性问题解决 一、需求起因 假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致【如下图:db中是新数据,cache中是旧数据】。 假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败【如下图:cache 中无数据,db中是旧数据】。 结论:先淘汰缓存,再写数据库。 二、数据不一致原因 先操作缓存,在写数据库成功之前,如果有读请求发生,可能导致旧数据入缓存,引发数据不一致。 写流程: (1)先淘汰cache (2)再写db

(1)先读cache,如果数据命中hit则返回 (2)如果数据未命中miss则读db (3)将db中读取出来的数据入缓存 什么情况下可能出现缓存和数据库中数据不一致呢? 在分布式环境下,数据的读写都是并发的,上游有多个应用,通过一个服务的多个部署(为了保证可用性,一定是部署多份的),对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序,也就是说后发出的读请求很可能先完成(读出脏数据): (a)发生了写请求A,A的第一步淘汰了cache(如上图中的1) (b)A的第二步写数据库,发出修改请求(如上图中的2) (c)发生了读请求B,B的第一步读取cache,发现cache中是空的(如上图中的步骤3) (d)B的第二步读取数据库,发出读取请求,此时A的第二步写数据还没完成,读出了一个脏数据放入cache(如上图中的步骤4) 即在数据库层面,后发出的请求4比先发出的请求2先完成了,读出了脏数据,脏数据又入了缓存,缓存与数据库中的数据不一致出现了 三、问题解决思路 能否做到先发出的请求一定先执行完成呢?常见的思路是“串行化”

Redis备份容灾及高可用方案

Redis 备份、容灾及高可用方案

一,Redis简单介绍 Redis是一个高性能的key-value非关系型数据库,由于其具有高性能的特性,支持高可用、持久化、多种数据结构、集群等,使其脱颖而出,成为常用的非关系型数据库。 此外,Redis的使用场景也比较多。 我们常通过Reids的队列功能做购买限制。比如到节假日或者推广期间,进行一些活动,对用户购买行为进行限制,限制今天只能购买几次商品或者一段时间内只能购买一次。也比较适合适用。 4.排名 Redis在内存中对数字进行递增或递减的操作实现得非常好。所以我们在很多排名的场景中会应用Redis来进行,比如小说网站对小说进行排名,根据排名,将排名靠前的小说推荐给用户。

5.发布/订阅 Redis提供发布和订阅功能,发布和订阅的场景很多,比如我们可以基于发布和订阅的脚本触发器,实现用Redis的发布和订阅功能建立起来的聊天系统。 此外还有很多其它场景,Redis都表现的不错。 二,Redis使用中单点故障问题 正是由于Redis具备多种优良特新,且应用场景非常丰富,以至于Redis在各个公司都有它存在的身影。那么随之而来的问题和风险也就来了。Redis虽然应用场景丰富,但部分公司在实践Redis应用的时候还是相对保守使用单节点部署,那为日后的维护带来了安全风险。 在2015年的时候,曾处理过一个因为单点故障原因导致的业务中断问题。当时的Redis都未采用分布式部署,采用单实例部署,并未考虑容灾方面的问题。 当时我们通过Redis服务器做用户购买优惠商品的行为控制,但后来由于未知原因Redis节点的服务器宕机了,导致我们无法对用户购买行为进行控制,造成了用户能够在一段时间内多次购买优惠商品的行为。 这种宕机事故可以说已经对公司造成了不可挽回的损失了,安全风险问题非常严重,作为当时运维这个系统的我来说有必要对这个问题进行修复和在架构上的改进。于是我开始了解决非分布式应用下Redis单点故障方面的研究学习。

redis缓存技术学习

1 什么是redis redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 2 性能怎么样 Redis是一个高性能的key-value内存数据库。官方性能测试结果: set操作每秒110000次,get操作每秒81000次。 3 可不可以存对象 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作。 4 Redis与memcache的最大区别 Replication(树形) data types(String、Lists、Sorted Sets、Hashes) persistence (snapshot、aof) 很多开发者都认为Redis不可能比Memcached快,Memcached完全基于内存,而Redis 具有持久化保存特性,即使是异步的,Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因,目前想到的原因有这几方面。 Libevent。和Memcached不同,Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及牺牲了在特定平台的不少性能。Redis 用libevent中两个文件修改实现了自己的epoll event loop(4)。业界不少开发者也建议Redis

REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案

REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案

文档修订摘要

目录 REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案 (1) 1. 概述 (4) 2. 初认识 (4) 3. 缓存穿透解决方案 (4) 4. 缓存击穿解决方案 (5) 5. 缓存雪崩的解决方案 (6) 6. 小结 (8)

1.概述 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。 为了克服上述的问题,项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。 redis技术就是NoSQL技术中的一种,但是引入redis又有可能出现缓存穿透,缓存击穿,缓存雪崩等问题。本文就对这三种问题进行较深入剖析。 2.初认识 ?缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。 ?缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。 ?缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。 3.缓存穿透解决方案 一个一定不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不 到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个 足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外 也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据不存在,还是系 统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 粗暴方式伪代码: //伪代码public object GetProductListNew() { int cacheTime = 30; String cacheKey = "product_list"; String cacheValue = CacheHelper.Get(cacheKey);

Windows下Redis集群搭建

Windows下搭建Redis集群 Redis 集群简介 Redis 是一个开源的 key-value 存储系统,由于出众的性能,大部分互联网企业都用来做服务器端缓存。Redis 在3.0版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决单点故障,但是现在互联网企业动辄大几百G的数据,可完全是没法满足业务的需求,所以,Redis 在 3.0 版本以后就推出了集群模式。 Redis 集群采用了P2P的模式,完全去中心化。Redis 把所有的 Key 分成了16384 个 slot,每个 Redis 实例负责其中一部分 slot 。集群中的所有信息(节点、端口、slot等),都通过节点之间定期的数据交换而更新。 Redis 客户端可以在任意一个 Redis 实例发出请求,如果所需数据不在该实例中,通过重定向命令引导客户端访问所需的实例。 集群搭建 要让集群正常运作至少需要三个主节点,不过在刚开始试用集群功能时,强烈建议使用六个节点:其中三个为主节点,而其余三个则是各个主节点的从节点。 主节点崩溃,从节点的Redis就会提升为主节点,代替原来的主节点工作,崩溃的主Redis回复工作后,会成为从节点 1). 创建Redis集群目录 在redis安装的根目录下通过命令行创建6个以端口命名的文件夹 mkdir 7000 7001 7002 7003 7004 7005

将安装的redis文件夹中的redis.windows.conf以及redis-server,分别拷贝到新建的六个文件夹中 2). 更改配置 将六个文件夹下的redis.windows.conf文件中以下属性进行修改: port 7001(对应文件夹的端口号) cluster-enabled yes(开启实例的集群模式)去掉注释

Redis开发常用规范

Redis开发常用规范 1.冷热数据分离,不要将所有数据全部都放到Redis中 虽然Redis支持持久化,但是Redis的数据存储全部都是在内存中的,成本昂贵。建议根据业务只将高频热数据存储到Redis中【QPS大于5000】,对于低频冷数据可以使用 MySQL/ElasticSearch/MongoDB等基于磁盘的存储方式,不仅节省内存成本,而且数据量小在操作时速度更快、效率更高! 2.不同的业务数据要分开存储 不要将不相关的业务数据都放到一个Redis实例中,建议新业务申请新的单独实例。因为Redis为单线程处理,独立存储会减少不同业务相互操作的影响,提高请求响应速度;同时也避免单个实例内存数据量膨胀过大,在出现异常情况时可以更快恢复服务! 3.规范Key的格式 合适的key,便于查看,统计,排错。 “平台缩写“+“:”+“项目名”+“:”+“业务含义” 例如:GW:TRADE:USERID GW是新网关,TRADE是交易项目,USERID为业务ID。 ":"-作为key分隔符,方便客户端工具作为目录分级 4.存储的Key一定要设置超时时间 如果应用将Redis定位为缓存Cache使用,对于存放的Key一定要设置超时时间!因为若不设置,这些Key会一直占用内存不释放,造成极大的浪费,而且随着时间的推移会导致内存占用越来越大,直到达到服务器内存上限!另外Key的超时长短要根据业务综合评估,而不是越长越好!(某些业务要求key长期有效。可以在每次写入时,都设置超时时间,让超时时间顺延。) public Boolean set(final byte[] key, final byte[] value, final long liveTime) { return redisTemplate.execute(new RedisCallback() {

金蝶云星空K3 Cloud V7.2 分布式缓存使用说明书

金蝶云星空 分布式缓存使用说明书 修改记录 Ver. No 发版日期编制人批准人修改的章节号V1.02017/12/08 刘兵赖碧云初始版本 V1.22018/01/03 刘兵赖碧云 6.1.2 V1.3 2018/02/24 刘兵赖碧云 6.1

目录 1.概述 (3) 1.1.目的 (3) 1.2.范围 (3) 1.3.适用对象 (3) 1.4.参考资料 (3) 2.问题与解决策略 (3) 3.目标和约束 (3) 4.部署Redis服务 (4) 4.1.安装服务--service-install(安装必须的步骤) (4) 4.2.卸载服务--service-uninstall (4) 4.3.启动服务--service-start(安装必须的步骤) (4) 4.4.停止服务--service-stop (5) 4.5.服务配置修改(服务名和端口) (5) 4.6.Redis-cli配置(如果4.1按照2,3小点进行了修改,此节配置可以忽略) (5) 5.Redis配置文件修改 (5) 6.Redis缓存代码示例 (6) 6.1.1.写缓存和读缓存 (6) 6.1.2.错误的读写缓存 (7) 7.附录 (8)

1. 概述 1.1. 目的 为系统集群及分布式应用提供基础缓存服务。 1.2. 范围 适用版本:V6.2和后续版本 1.3. 适用对象 本文档适用于: 开发工程师:部署和开发指导。 实施人员:部署指导。 1.4. 参考资料 Redis相关资料 2. 问题与解决策略 愿景关注点描述与示例 3. 目标和约束 目标: 提供单据和基础数据的分布式缓存支持;

Django使用redis缓存服务器 光环大数据Python培训

https://www.sodocs.net/doc/5218471077.html, Django使用redis缓存服务器光环大数据Python培训 光环大数据Python培训了解到,redis相信大家都很熟悉了,和memcached 一样是一个高性能的key-value数据库,至于什么是缓存服务器,度娘都有很明 白的介绍了,我在这里就不一一介绍了。 那我们一般什么情况下才会使用缓存服务器呢?可不是什么情况都需要的 哦,一般来说是在需要频繁对一个字段读取的时候才会需要将这个字段放入到缓 存服务器上,而且由于key-value数据库一般只是放很简单的数据,所以在选择 保存的对象的时候要注意选择好。 下面我就来介绍如何在Django中配置使用redis数据库,首先是先安装 redis了,在Ubuntu中执行下面这句命令: #安装Redis服务器端 sudo apt-get install redis-server 然后为了能在Django中使用redis,还需要安装redis for Django的插件: pip install django-redis 那么现在就是在Django的settings中配置了。 CACHES = { 'default': { 'BACKEND': 'redis_cache.cache.RedisCache', 'LOCATION': '127.0.0.1:6379', "OPTIONS": { "CLIENT_CLASS":

https://www.sodocs.net/doc/5218471077.html, "redis_cache.client.DefaultClient", }, },}REDIS_TIMEOUT=7*2 4*60*60CUBES_REDIS_TIMEOUT=60*60NEVER_REDIS_TIMEOUT=365*24*60*60 其实只是需要CACHES中的那几条就可以了,后面这三句可以不需要的,只 是我后面的例子里需要用到,我就在这里配置了。 好了,现在连接和配置都已经完成了,那么在项目中该如何使用呢?接下来 看下面这段例子吧。 from django.conf import settingsfrom django.core.cache import cache#read cache user iddef read_from_cache(self, user_name): key = 'user_id_of_'+user_name value = cache.get(key) if value == None: data = None else: data = json.loads(value) return data#write cache user iddef write_to_cache(self, user_name): key = 'user_id_of_'+user_name cache.set(key, json.dumps(user_name), settings.NEVER_REDIS_TIMEOUT) 通过上面的这两个方法就可以实现对redis的读取操作了,只需要将需要的 字段当参数传入到方法中就好了。 那么之前提到的memcached呢?其实也是一样的配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', }} 当然用法也是和我上面的例子是一样的了。其实对于redis这样的缓存服务 器来说,配置都是很简单的,而具体的使用也不难,官网上面也有很多简单明了

黑马程序员:为什么更要用redis,应该如何使用redis

为什么缓存数据库更要首选redis?如何使用redis? 一、使用缓存数据库为什么首选用redis? 我们都知道,把一些热数据存到缓存中可以极大的提高速度,那么问题来了,是用Redis 好还是Memcached好呢,以下是它们两者之间一些简单的区别与比较: 1. Redis不仅支持简单的k/v类型的数据,同时还支持list、set、zset(sorted set)、hash等数据结构的存储,使得它拥有更广阔的应用场景。 2. Redis最大的亮点是支持数据持久化,它在运行的时候可以将数据备份在磁盘中,断电或重启后,缓存数据可以再次加载到内存中,只要Redis配置的合理,基本上不会丢失数据。 3. Redis支持主从模式的应用。 4. Redis单个value的最大限制是1GB,而Memcached则只能保存1MB内的数据。 5. Memcache在并发场景下,能用cas保证一致性,而Redis事务支持比较弱,只能保证事务中的每个操作连续执行。 6. 性能方面,根据网友提供的测试,Redis在读操作和写操作上是略领先Memcached的。 从上面这些看出,Redis的优势比Memcached大,不过Memcached也还是有它用武之地的。要是只选择装其中一种的话,还是要首选Redis。 二、如何使用redis? 你一定要知道的是:redis的key名要区分大小写,在redis中除了和空格外,其他的字符都可以做为key名,且长度不做限制,不过为了性能考虑,一般key名不要设置的太长。redis 功能强大,支持数据类型丰富,以下是redis操作命令大全,基本上涵盖了redis所有的命令! 1、redis命令基本篇 1)、【set key value 】存入一个key和值。如:set myname reson 2)、【get key 】读取一个key的值。 3)、【del key 】删除一个key。 4)、【del key1 key2 ... keyN 】删除多个key。如:del myname1 myname2 5)、【exists key 】判断一个key是否存在。 6)、【type key 】查看key的类型。 7)、【rename key keyNew 】重命名key名。如:rename myname myname2 8)、【dbsize 】查看当前库中的key的条数。

相关主题