首页 > 应用开发 > XML/XSL > 为什么需要本地缓存?
加了Redis分布式缓存后有所改善,但网络IO的开销依然存在,特别是对时效性要求高的数据。
这时候,本地缓存的价值就凸显出来了。
本地缓存是什么?
简单说就是将数据存储在 应用进程的内存中,实现数据的快速访问。
它的访问速度通常是纳秒级,而分布式缓存(如Redis)是毫秒级,数据库查询更是毫秒到秒级。
在深入具体方案前,我们先搞清楚本地缓存的核心价值。
// 没有缓存的用户查询服务 public class CategoryServiceWithoutCache { private CategoryMapper categoryMapper; public Category getCategoryById (Long categoryId) { // 每次调用都直接查询数据库 return categoryMapper.selectById(categoryId); } // 假设这个接口每秒被调用1000次
public class CategoryServiceWithCache { private CategoryMapper categoryMapper; // 使用ConcurrentHashMap作为本地缓存 private final Map<Long, Category> categoryCache = new ConcurrentHashMap <>(); public Category getCategoryById (Long categoryId) { // 1. 先查缓存 Category category = categoryCache.get(categoryId); if (category != null ) { return category; // 缓存命中,直接返回 } // 2. 缓存未命中,查询数据库 category = categoryMapper.selectById(categoryId); if (category != null ) { // 3. 将数据放入缓存 categoryCache.put(categoryId, category); }
declare ( strict_types = 1 ) ; function ext_version ( string $ext ) : ? string { $v = phpversion ( $ext ) ; return $v === false ? null : $v ; } $snapshot = [ 'php_version' => PHP_VERSION , 'php_version_id' => PHP_VERSION_ID , 'sapi' => PHP_SAPI , 'os' => PHP_OS_FAMILY . ' ' . php_uname ( 'r' ) , 'ini_loaded' => php_ini_loaded_file ( ) , 'ini_scanned' => php_ini_scanned_files ( ) , 'extensions' => [ ] , ] ; $exts = get_loaded_extensions ( ) ; sort ( $exts ) ; foreach ( $exts as $ext ) { $snapshot [ 'extensions' ] [ $ext ] = ext_version ( $ext ) ;
pull_request : jobs : tests : runs-on : ubuntu - latest strategy : fail-fast : false matrix : php : [ '8.3' , '8.5' ] # 调整为你的当前版本 + 目标版本 steps : - uses : actions/checkout@v4 - name : Setup PHP uses : shivammathur/setup - php@v2 with : php-version : $ { { matrix.php } } tools : composer : v2 coverage : none - name : Install dependencies run : composer install - - no - interaction - - prefer - dist - name : Run tests run : vendor/bin/phpunit
# 生成模拟的降水量数据 (单位: mm)
np.random.seed(
42
)
# 为了结果可复现
降水量 = np.random.uniform(
30
,
150
, size=
len
(月份))
# 随机生成30-150mm的数据
# --- 2. 创建图形 ---
fig, (ax1, ax2) = plt.subplots(
1
,
2
, figsize=(
14
,
7
), facecolor=
"white"
)
# --- 2.1 绘制传统条形图 ---
# ... 省略 ...
# --- 2.2 绘制径向条形图 ---
# 计算每个条形的角度位置
# ... 省略 ...
# 使用极坐标子图
ax2 = plt.subplot(
122
, projection=
"polar"
)
# 关键:设置 'bottom' 参数为 inner_radius,这样条形就从 inner_radius 开始画,长度为 radii
bars = ax2.bar(
theta,
radii,
width=
0.4
,
bottom=inner_radius,
color=
"lightcoral"
,
edgecolor=
"darkred"
,
alpha=
0.7
,
)
# 添加数值标签 (在条形内部,靠近外侧)
for
angle, radius, month
in
zip
(theta, radii, 月份):
ax2.text(
angle,
inner_radius + radius /
2
,
f"
{radius:
.1f}"
,
ha=
"center"
,
va=
"center"
,
fontsize=
8
,
color=
"black"
,
)
# 添加月份标记 (在条形外部)
# ... 省略 ...
from math import log10 labels = list ( "ABCDEFG" ) data = [ 21 , 57 , 88 , 14 , 76 , 91 , 26 ] # ... 省略 ... #create colors along a chosen colormap colors = [cm.terrain(i / n) for i in range (n)] #create figure, axis fig, ax = plt.subplots() #create rings of donut chart for i in range (n): current_outer_radius = r - i * w innerring, _ = ax.pie([m - data[i], data[i]], pant.com.cn, radius = current_outer_radius, startangle = 90 , colors = [ "white" , colors[i]])
public class ReentrantLockDemo { xyzdh.cn, // 创建非公平锁(默认),若需公平锁:new ReentrantLock(true) private static final ReentrantLock lock = new ReentrantLock (); public static void doTask () { // 1. 普通获取锁(不可中断) lock.lock(); try { // 临界区代码(线程安全) System.out.println(Thread.currentThread().getName() + " 执行任务" ); Thread.sleep( 1000 ); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { // 必须在finally中释放锁,否则锁永远无法释放 lock.unlock(); } } // 超时获取锁示例 public static void tryLockWithTimeout () { try { // 尝试在2秒内获取锁,获取成功返回true,失败返回false if (lock.tryLock( 2 , java.util.concurrent.TimeUnit.SECONDS)) { try { System.out.println(Thread.currentThread().getName() + " 超时获取锁成功" ); } finally { lock.unlock();winered.cn, } } else { System.out.println(Thread.currentThread().getName() + " 超时获取锁失败" ); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static void main (String[] args) { // 测试普通获取锁 new Thread (ReentrantLockDemo::doTask, "线程1" ).start(); new Thread (ReentrantLockDemo::doTask, "线程2" ).start(); pant.com.cn, // 测试超时获取锁
import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.PriorityOrdered; import org.springframework.lang.Nullable; /** * @author yangfh * @date 2023-12-14 21:30 **/ public class User implements InitializingBean , DisposableBean { private Long id; private String username; private String email; private Address address; private Long age; public User () { System.out.println( "User 无参构造函数: " + this .toString()); } public User (Long id, String username, String email, Address address) { this .id = id; this .username = username; this .email = email; this .address = address; System.out.println( "User 有参构造函数: " + this .toString()); } public void initMethod () { System.out.println( "User initMethod" ); } public void destroyMethod () { System.out.println( "User destroyMethod" ); } public void afterPropertiesSet () throws Exception { System.out.println( "User afterPropertiesSet" ); } public void destroy () throws Exception { System.out.println( "User destroy" ); } public UserServiceImpl () { System.out.println( "UserServiceImpl 无参构造" ); } public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { System.out.println( "UserServiceImpl postProcessBeforeInitialization 增强处理 [" +beanName+ "]" ); return BeanPostProcessor. super .postProcessBeforeInitialization(bean, beanName); } public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { System.out.println( "UserServiceImpl postProcessAfterInitialization 增强处理 [" +beanName+ "]" ); return BeanPostProcessor. super .postProcessAfterInitialization(bean, beanName);wsbbt.com, } public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println( "UserServiceImpl postProcessBeanFactory beanFactory 增强处理 [" +beanFactory+ "]" ); } public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { System.out.println( "UserServiceImpl setApplicationContext " );51xinku.com,
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"qssfzm.com, xmlns:context= "http://www.springframework.org/schema/context" xmlns:aop= "http://www.springframework.org/schema/cache" xsi:schemaLocation= " http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context qzsxy.com, https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> < bean id= "address" class= "org.yang.learn.spring.dto.Address" > < constructor-arg value= "深圳"/> < constructor-arg value= "罗湖"/> < constructor-arg value= "xxx街道101号"/> </ bean> < bean id= "user" njyf.com.cn, class= "org.yang.learn.spring.dto.User" init-method= "initMethod" destroy-method= "destroyMethod" > < property name= "username" value= "张三"> </ property> < property name= "age" value= "9764534"> </ property> </ bean> < bean id= "userService" class= "org.yang.learn.spring.dto.UserServiceImpl" > </ bean>
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048956/viewspace-3109286/ ,如需转载,请注明出处,否则将追究法律责任。