分布式缓存系统——《高性能分布式缓存Redis》_高性能分布式缓存redis

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 一般讲锁是多线程的锁,是在一个进程中的;
  • 多个进程(JVM)在并发时也会产生问题,也要控制时序性;
  • 可以采用分布式锁。使用Redis实现 sexNX

做乐观锁(Redis)

  • 同步锁和数据库中的行锁、表锁都是悲观锁
  • 悲观锁的性能是比较低的,响应性比较差
  • 高性能、高响应(秒杀)采用乐观锁
  • Redis可以实现乐观锁 watch + incr
什么是缓存

缓存原指CPU上的一种高速存储器,它先于内存与CPU交换数据,速度很快。现在泛指存储在计算机上的原始数据的复制集,便于快速访问。在互联网技术中,缓存是系统快速响应的关键技术之一

大型网站中缓存的使用

单机架构LAMP(Linux+apache+MySQL+PHP)、JavaEE(SSM);访问量越大,响应力越差,用户体验越差

在大型网站中从浏览器到网络,再到应用服务器,再到数据库,通过在各个层面应用缓存技术,大大提升了系统性能和用户体验。
在这里插入图片描述

缓存分类
页面缓存

传统互联网:页面缓存和浏览器缓存
移动互联网:APP缓存
页面缓存
页面缓存:页面自身对某些元素或全部元素进行存储,并保存成文件。html5:Cookie、WebStorage(SessionStorage和LocalStorage)、WebSql、indexDB、Application、Cache等

开启步骤
1、设置manifest描述文件:CACHE MANIFEST #comment js/index.js img/bg.png
2、html关联manifest属性

浏览器缓存
当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。
浏览器缓存可分为强制缓存协商缓存
强制缓存:直接使用浏览器的缓存数据
条件:Cache-Control的max-age没有过期或者Expires的缓存时间没有过期

<meta http-equiv="Cache-Control" content="max-age=7200" />
<meta http-equiv="Expires" content="Mon, 20 Aug 2010 23:00:00 GMT" />

协商缓存:服务器资源未修改,使用浏览器的缓存(304);反之,使用服务器资源(200)。

<meta http-equiv="cache-control" content="no-cache">

APP缓存
原生APP中把数据缓存在内存、文件或本地数据库(SQLite)中。比如图片文件。

网络端缓存

通过代理的方式响应客户端请求,对重复的请求返回缓存中的数据资源。
Web代理缓存
可以缓存原生服务器的静态资源,比如样式、图片等。常见的反向代理服务器比如大名鼎鼎的Nginx。
在这里插入图片描述
边缘缓存
边缘缓存中典型的商业化服务就是CDN了。CDN的全称是Content Delivery Network,即内容分发网络。CDN通过部署在各地的边缘服务器,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。现在一般的公有云服务商都提供CDN服务。
在这里插入图片描述

服务端缓存

服务器端缓存是整个缓存体系的核心。包括数据库级缓存、平台级缓存和应用级缓存。
数据库级缓存
数据库是用来存储和管理数据的。MySQL在Server层使用查询缓存机制。将查询后的数据缓存起来。K-V结构,Key:select语句的hash值,Value:查询结果。InnoDB存储引擎中的buffer-pool用于缓存InnoDB索引及数据块。
平台级缓存
平台级缓存指的是带有缓存特性的应用框架。比如:GuavaCache 、EhCache、OSCache等。部署在应用服务器上,也称为服务器本地缓存。
应用级缓存(重点)
具有缓存功能的中间件:Redis、Memcached、EVCache、Tair等。采用K-V形式存储。利用集群支持高可用、高性能、高并发、高扩展。
分布式缓存

缓存的优势、代价

使用缓存的优势

提升用户体验
用户体验(User Experience):用户在使用产品过程中建立起来的一种纯主观感受。缓存的使用可以提升系统的响应能力,大大提升了用户体验。
减轻服务器压力
客户端缓存、网络端缓存减轻应用服务器压力。服务端缓存减轻数据库服务器的压力。
提升系统性能
系统性能指标:响应时间、延迟时间、吞吐量、并发用户数和资源利用率等。

缓存技术可以:
缩短系统的响应时间
减少网络传输时间和应用延迟时间
提高系统的吞吐量
增加系统的并发用户数
提高了数据库资源的利用率

使用缓存的代价

额外的硬件支出
缓存是一种软件系统中以空间换时间的技术。需要额外的磁盘空间和内存空间来存储数据;搭建缓存服务器集群需要额外的服务器
采用云服务器的缓存服务就不用额外的服务器了;阿里云,百度云,提供缓存服务

高并发缓存失效
在高并发场景下会出现缓存失效(缓存穿透、缓存雪崩、缓存击穿)。造成瞬间数据库访问量增大,甚至崩溃

缓存与数据库数据同步
缓存与数据库无法做到数据的时时同步;Redis无法做到主从时时数据同步

缓存并发竞争
多个redis的客户端同时对一个key进行set值得时候由于执行顺序引起的并发问题

缓存读写模式

Cache Aside Pattern(常用)

Cache Aside Pattern旁路缓存),是最经典的缓存+数据库读写模式。
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
在这里插入图片描述
更新的时候,先更新数据库,然后再删除缓存。
在这里插入图片描述

为什么是删除缓存,而不是更新缓存呢?
缓存的值是一个结构:hash、list,更新数据需要遍历
在这里插入图片描述
2、懒加载,使用的时候才更新缓存
也可以采用异步的方式填充缓存

Read/Write Through Pattern

应用程序只操作缓存,缓存操作数据库。
Read-Through穿透读模式/直读模式):应用程序读缓存,缓存没有,由缓存回源到数据库,并写入缓存。
Write-Through穿透写模式/直写模式):应用程序写缓存,缓存写数据库。
该种模式需要提供数据库的handler,开发较为复杂。

Write Behind Caching Pattern(推荐)

应用程序只更新缓存。
缓存通过异步的方式将数据批量或合并后更新到DB中,不能时时同步,甚至会丢数据

缓存架构的设计思路

缓存的整体设计思路包括:

  • 多层次
    分布式缓存宕机,本地缓存还可以使用
    在这里插入图片描述
  • 数据类型
    • 简单数据类型
      Value是字符串或整数
      Value的值比较大(大于100K)
      只进行setter和getter
      可采用Memcached
      Memcached纯内存缓存,多线程
    • 复杂数据类型
      Value是hash、set、list、zset
      需要存储关系,聚合,计算
      可采用Redis
  • 要做集群
    分布式缓存集群方案(Redis)
    哨兵+主从
    RedisCluster
  • 缓存的数据结构设计
    • 1、与数据库表一致
      数据库表和缓存是一一对应的
      缓存的字段会比数据库表少一些
      缓存的数据是经常访问的
      用户表,商品表
    • 2、与数据库表不一致
      需要存储关系,聚合,计算等
      比如某个用户的帖子、用户的评论。
      以用户评论为例,DB结构如下:
      在这里插入图片描述
      如果要取出UID为1000的用户的评论,原始的表的数据结构显然是不行的。
      我们应做如下设计:
      • key:UID+时间戳(精确到天) 评论一般以天为计算单位
      • value:Redis的Hash类型。field为 id和content
      • expire:设置为一天

案例: 设计拉钩首页缓存职位列表、热门职位

在这里插入图片描述

1、静态文件
2、职位列表
数据特点:固定数据,一次性读取
方案:

  • 在服务器开启时一次性初始化到服务器本地缓存
  • 采用Guava Cache,Guava Cache用于存储频繁使用的少量数据,支持高并发访问
  • 也可以使用JDK的CurrentHashMap,需要自行实现

3、热门职位
数据特点:频繁变化,不必时时同步;但一定要有数据,不能为空
方案:

  • 数据从服务层读取(dubbo),然后放到本地缓存中(Guava),如果出现超时或读取为空,则返回原
  • 来本地缓存的数据。
    注意:不同的客户端看到的数据有可能不一样

4、数据回填
从Dubbo中读取数据时,先读取Redis集群的缓存,如果缓存命中则直接返回。如果缓存不命中则返回本地缓存,不能直接读取数据库。用异步的形式从数据库刷入到缓存中。
5、热点策略
对于热点数据我们采用本地缓存策略,而不采用服务熔断策略,因为首页数据可以不准确,但不能不响应。

高并发脏读

先更新数据库,在更新缓存

在这里插入图片描述

先删除缓存,在更新数据库

在这里插入图片描述

先更新数据库,再删除缓存(推荐)

在这里插入图片描述

Redis底层结构和缓存原理

本章学习目标:

  • 掌握Redis五种基本数据类型的用法和常见命令的使用
  • 了解bitmap、geo、stream的使用
  • 理解Redis底层数据结构(Hash、跳跃表、quicklist)
  • 了解RedisDB和RedisObject
  • 理解LRU算法
  • 理解Redis缓存淘汰策略
  • 能够较正确的应用Redis缓存淘汰策略

Redis数据类型和应用场景

Redis是一个Key-Value的存储系统,使用ANSI C语言编写。key的类型是字符串。value的数据类型有:常用的:string字符串类型、list列表类型、set集合类型、sortedset(zset)有序集合类型、hash类型。不常见的:bitmap位图类型、geo地理位置类型。Redis5.0新增一种:stream类型
注意:Redis中命令是忽略大小写,(set SET),key是不忽略大小写的 (NAME name)

Redis中key的设计
  1. 用:分割
  2. 把表名转换为key前缀, 比如: user:
  3. 第二段放置主键值
  4. 第三段放置列名

比如:用户表user, 转换为redis的key-value存储
username 的 key: user:9:username
{userid:9,username:zhangf}
email的key user:9:email
表示明确:看key知道意思
不易被覆盖

数据类型及命令手册

参考:https://blog.csdn.net/qq_36581961/article/details/113248387

Redis客户端访问

Java程序访问Redis

采用jedis API进行访问即可
关闭RedisServer端的防火墙

systemctl stop firewalld(默认)
systemctl disable firewalld.service(设置开启不启动)

新建maven项目后导入Jedis包

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>

测试类

@Test
public void testConn(){
	//与Redis建立连接 IP+port
	Jedis redis = new Jedis("192.168.127.128", 6379);
	//在Redis中写字符串 key value
	redis.set("jedis:name:1","jd-zhangfei");
	//获得Redis中字符串的值
	System.out.println(redis.get("jedis:name:1"));
	//在Redis中写list
	redis.lpush("jedis:list:1","1","2","3","4","5");
	//获得list的长度
	System.out.println(redis.llen("jedis:list:1"));
}

Spring访问Redis

新建项目,添加依赖

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>5.2.5.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<!--redis依赖-->
	<dependency>
		<groupId>org.springframework.data</groupId>
		<artifactId>spring-data-redis</artifactId>
		<version>1.0.3.RELEASE</version>
	</dependency>
</dependencies>

添加Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:redis.properties</value>
			</list>
		</property>
	</bean>
	<!-- redis config -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxActive" value="${redis.pool.maxActive}" />
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<property name="maxWait" value="${redis.pool.maxWait}" />
		<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
	</bean>
	<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="${redis.server}"/>
		<property name="port" value="${redis.port}"/>
		<property name="timeout" value="${redis.timeout}" />
		<property name="poolConfig" ref="jedisPoolConfig" />
	</bean>
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory"/>
		<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>
	</bean>
</beans>

添加properties文件

redis.pool.maxActive=100
redis.pool.maxIdle=50
redis.pool.maxWait=1000
redis.pool.testOnBorrow=true
redis.timeout=50000
redis.server=192.168.72.128
redis.port=6379

编写测试用例

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import java.io.Serializable;
@ContextConfiguration({ "classpath:redis.xml" })
public class RedisTest extends AbstractJUnit4SpringContextTests {
	@Autowired
	private RedisTemplate<Serializable, Serializable> rt;
	@Test
	public void testConn() {
		rt.opsForValue().set("name","zhangfei");
		System.out.println(rt.opsForValue().get("name"));
	}
}

SpringBoot访问Redis

新建项目,导入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

添加配置文件application.yml

spring:
	redis:
	host: 192.168.72.128
	port: 6379
	jedis:
		pool:
		min-idle: 0
		max-idle: 8
		max-active: 80
		max-wait: 30000
		timeout: 3000

添加配置类RedisConfig

package com.lagou.sbr.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory factory;
	@Bean
	public RedisTemplate<String, Object> redisTemplate() {
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		redisTemplate.setHashValueSerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new StringRedisSerializer());
		redisTemplate.setConnectionFactory(factory);
		return redisTemplate;
	}
}

** 添加RedisController**

package com.lagou.sbr.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping(value = "/redis")
public class RedisController {
	@Autowired
	RedisTemplate redisTemplate;
	@GetMapping("/put")
	public String put(@RequestParam(required = true) String key,
	@RequestParam(required = true) String value) {
		//设置过期时间为20秒
		redisTemplate.opsForValue().set(key,value,20, TimeUnit.SECONDS);
		return "Success";
	}
	@GetMapping("/get")
	public String get(@RequestParam(required = true) String key){
		return (String) redisTemplate.opsForValue().get(key);
	}
}

修改Application并运行

package com.lagou.sbr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class SpringbootRedisApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringbootRedisApplication.class, args);
}
}

底层数据结构

参考(未更新完整):https://blog.csdn.net/qq_36581961/category_10691600.html

缓存过期和淘汰策略

Redis性能高:
官方数据
读:110000次/s
写:81000次/s
长期使用,key会不断增加,Redis作为缓存使用,物理内存也会满
内存与硬盘交换(swap) 虚拟内存 ,频繁IO 性能急剧下降

maxmemory

不设置的场景
Redis的key是固定的,不会增加
Redis作为DB使用,保证数据的完整性,不能淘汰 , 可以做集群,横向扩展
缓存淘汰策略:禁止驱逐 (默认)
设置的场景
Redis是作为缓存使用,不断增加Key
maxmemory : 默认为0 不限制
问题:达到物理内存后性能急剧下架,甚至崩溃;内存与硬盘交换(swap) 虚拟内存 ,频繁IO 性能急剧下降
设置多少?与业务有关
1个Redis实例,保证系统运行 1 G ,剩下的就都可以设置Redis;物理内存的3/4
slaver : 留出一定的内存
在redis.conf中

maxmemory 1024mb

命令: 获得maxmemory数

CONFIG GET maxmemory

设置maxmemory后,当趋近maxmemory时,通过缓存淘汰策略,从内存中删除对象
不设置maxmemory 无最大内存限制 maxmemory-policy noeviction (禁止驱逐) 不淘汰
设置maxmemory maxmemory-policy 要配置

expire数据结构

在Redis中可以使用expire命令设置一个键的存活时间(ttl: time to live),过了这段时间,该键就会自动被删除
expire的使用
expire命令的使用方法如下:expire key ttl(单位秒)

127.0.0.1:6379> expire name 2 #2秒失效
(integer) 1
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name zhangfei
OK
127.0.0.1:6379> ttl name #永久有效
(integer) -1
127.0.0.1:6379> expire name 30 #30秒失效
(integer) 1
127.0.0.1:6379> ttl name #还有24秒失效
(integer) 24
127.0.0.1:6379> ttl name #失效
(integer) -2

expire原理

typedef struct redisDb {
	dict *dict; -- key Value
	dict *expires; -- key ttl
	dict *blocking_keys;
	dict *ready_keys;
	dict *watched_keys;
	int id;
} redisDb;

上面的代码是Redis 中关于数据库的结构体定义,这个结构体定义中除了 id 以外都是指向字典的指针,其中我们只看 dict 和 expires

dict 用来维护一个 Redis 数据库中包含的所有 Key-Value 键值对,expires则用于维护一个 Redis 数据库中设置了失效时间的键(即key与失效时间的映射)

当我们使用 expire命令设置一个key的失效时间时,Redis 首先到 dict 这个字典表中查找要设置的key是否存在,如果存在就将这个key和失效时间添加到 expires 这个字典表。当我们使用 setex命令向系统插入数据时,Redis 首先将 Key 和 Value 添加到 dict 这个字典表中,然后将 Key 和失效时间添加到 expires 这个字典表中。

简单地总结来说就是,设置了失效时间的key和具体的失效时间全部都维护在 expires 这个字典表中。

删除策略

Redis的数据删除有定时删除惰性删除主动删除三种方式。Redis目前采用惰性删除+主动删除的方式。

定时删除

在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。
创建一个定时器,当key设置有过期时间 且过期时间到达 由定时器任务立即对键的删除

  • 优点:节约内存 到时删除 快速释放不必要的内存
  • 缺点:CPU压力很大 无论CPU此时的负载多高 均占用CPU 会影响redis服务器相应时间和指令吞吐量

总结:以时间换空间

惰性删除

数据到达过期时间 不做处理 等下次访问该数据时

  • 如果过期 删除
  • 如果未过期 返回数据
  • 优点:节约CPU性能 发现必须删除才删除
  • 缺点:内存压力大 出现长期占用内存数据

总结:用存储空间换处理器性能 以空间换时间
调用expireIfNeeded函数,该函数的意义是:读取数据之前先检查一下它有没有失效,如果失效了就删除它。

int expireIfNeeded(redisDb \*db, robj \*key) {
	//获取主键的失效时间 get当前时间-创建时间>ttl
	long long when = getExpire(db,key);
	//假如失效时间为负数,说明该主键未设置失效时间(失效时间默认为-1),直接返回0
	if (when < 0) return 0;
	//假如Redis服务器正在从RDB文件中加载数据,暂时不进行失效主键的删除,直接返回0
	if (server.loading) return 0;
	//如果以上条件都不满足,就将主键的失效时间与当前时间进行对比,如果发现指定的主键
	//还未失效就直接返回0
	if (mstime() <= when) return 0;
	//如果发现主键确实已经失效了,那么首先更新关于失效主键的统计个数,然后将该主键失
	//效的信息进行广播,最后将该主键从数据库中删除
	server.stat_expiredkeys++;
	propagateExpire(db,key);
	return dbDelete(db,key);
}

定期删除(主动删除)

在这里插入图片描述
周期性轮询redis库中的时效性数据 采用随机抽取的策略 利用过期数据占比的方式控制删除频度

  • 特点:CPU性能占用设置有峰值 检测频度可以自定义设置
  • 特点:内存占用率不是很大 ,长期占用内存的冷数据会被持续清理
逐出算法

在这里插入图片描述
数据逐出的相关配置

  • 最大可使用配置


![img](https://img-blog.csdnimg.cn/img_convert/ce8ae9a378e085490ad4d76744e01c5b.png)
![img](https://img-blog.csdnimg.cn/img_convert/f3915b7038619606448a17dd262ad7ff.png)
![img](https://img-blog.csdnimg.cn/img_convert/1ef72686b892fc87bea624b5445d3f29.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

ess=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2NTgxOTYx,size_16,color_FFFFFF,t_70)  
 周期性轮询redis库中的时效性数据 采用随机抽取的策略 利用过期数据占比的方式控制删除频度


* 特点:CPU性能占用设置有峰值 检测频度可以自定义设置
* 特点:内存占用率不是很大 ,长期占用内存的冷数据会被持续清理


##### 逐出算法


![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6ab1b6b5d8381dc2cb4e3846fb8eb79a.png)  
 **数据逐出的相关配置**


* 最大可使用配置



[外链图片转存中…(img-RcI3rrHs-1715544849134)]
[外链图片转存中…(img-5ei7bEgj-1715544849135)]
[外链图片转存中…(img-Rx9Z4t11-1715544849135)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  1.Memcached是什么?   Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。Memcached通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。Memcached由Danga Interactive最初为了加速 LiveJournal网站访问速度而开发的,后 来被很多大型的网站采用。起初作者编写它可能是为了提高动态网页应用,为了减轻数据库检索的压力,来做的这个缓存系统。它的缓存是一种分布式的,也就是可 以允许不同主机上的多个用户同时访问这个缓存系统,这种方法不仅解决了共享内存只能是单机的弊端, 同时也解决了数据库检索的压力,最大的优点是提高了访问获取数据的速度!基于memcached作者对分布式cache的理解和解决方案。memcached完全可以用到其他地方 比如分布式数据库,分布式计算等领域。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。   2.Memcached工作机制   通过在内存中开辟一块区域来维持一个大的hash表来加快页面访问速度,和数据库是独立的。但是目前主要用来缓存数据库的数据。允许多个server通过网络形成一个大的hash,用户不必关心数据存放在哪,只调用相关接口就可。存放在内存的数据通过LRU算法进行淘汰出内存。同时可以通过删除和设置失效时间来淘汰存放在内存的数据。   现在一些.NET开发人员开始放弃ASP.NET内置的缓存机制,转而使用Memcached——一种分布式的内存缓存系统。当运行在单独的Web服务器上,你可以很容易地清除一个已经确认被改变了的缓存。可惜,ASP.NET没有一个很好的方法来支持多服务器。每个服务器上的缓存都对其他缓存的改变一无所知。   ASP.NET允许通过基于文件系统和数据库表的触发器来作废一个缓存。然而,这也存在问题,比如数据库触发器需要使用昂贵的轮询,以及触发器本身冗长的编程。但是,我们还是有其他的选择的。   不像ASP.NET内置的缓存机制,Memcached是一个分布式的缓存系统。任何Web服务器都能更新或删除一个缓存项,并且所有其他的服务器都能在下次访问这些缓存项的时候自动获取到更新的内容。这是通过把这些缓存项存储在一个或者多个缓存服务器上来实现的。每一个缓存项都根据它的关键字的哈希值来分配到一个服务器上。 注:相关组词来源于百度文库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值