Rumah  >  Artikel  >  pangkalan data  >  Mari kita bincangkan tentang menggunakan redis untuk melaksanakan caching teragih

Mari kita bincangkan tentang menggunakan redis untuk melaksanakan caching teragih

WBOY
WBOYke hadapan
2022-07-14 17:01:172756semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang Redis, yang terutamanya mengatur isu yang berkaitan dengan cache yang diedarkan bermakna ia terdiri daripada berbilang aplikasi, yang mungkin diedarkan pada pelayan yang berbeza, akhirnya kami sediakan perkhidmatan untuk bahagian web Mari kita lihat bersama-sama. Saya harap ia akan membantu semua orang.

Mari kita bincangkan tentang menggunakan redis untuk melaksanakan caching teragih

Pembelajaran yang disyorkan: Tutorial video Redis

Penerangan cache yang diedarkan:

tumpuan caching teragih adalah pada pengedaran Saya percaya anda telah berhubung dengan banyak yang diedarkan, seperti pembangunan teragih, penggunaan teragih, kunci teragih, benda, sistem, dll. Terdapat banyak. Ini memberi kita pemahaman yang jelas tentang pengedaran itu sendiri Pengedaran terdiri daripada berbilang aplikasi, yang mungkin diedarkan pada pelayan yang berbeza, dan akhirnya menyediakan perkhidmatan ke bahagian web.
Cache teragih mempunyai kelebihan berikut:

  1. Data cache pada semua pelayan web adalah sama dan data cache tidak akan berbeza disebabkan oleh aplikasi yang berbeza dan pelayan yang berbeza.
  2. Cache adalah bebas dan tidak terjejas oleh permulaan semula pelayan Web atau pemadaman dan penambahan, yang bermaksud bahawa perubahan dalam Web ini tidak akan menyebabkan perubahan dalam data cache.

Dalam seni bina aplikasi tunggal tradisional, kerana bilangan lawatan pengguna tidak tinggi, kebanyakan cache wujud untuk menyimpan maklumat pengguna dan beberapa halaman, dan kebanyakan operasi dilakukan secara langsung dengan Pembacaan DB dan interaksi penulisan, seni bina jenis ini mudah, juga dipanggil seni bina ringkas,
Projek OA tradisional seperti ERP, SCM, CRM dan sistem lain mempunyai bilangan pengguna yang kecil dan juga disebabkan oleh sebab perniagaan kebanyakan syarikat. Seni bina aplikasi tunggal masih sangat kompleks Seni bina yang biasa digunakan, tetapi dalam sesetengah sistem, apabila bilangan pengguna meningkat dan perniagaan berkembang, kesesakan DB muncul.

Terdapat dua cara untuk menangani situasi ini yang telah saya pelajari di bawah

(1): Apabila bilangan lawatan pengguna tidak besar, tetapi jumlah data yang dibaca dan ditulis adalah besar , Perkara yang biasanya kami pakai ialah memisahkan bacaan dan penulisan DB, menggunakan satu induk dan berbilang hamba, dan menaik taraf perkakasan untuk menyelesaikan masalah kesesakan DB.
Kekurangan tersebut juga murni:

1. Apa yang perlu dilakukan apabila bilangan pengguna adalah besar? ,
2. Peningkatan prestasi adalah terhad,
3. Nisbah harga/prestasi tidak tinggi. Meningkatkan prestasi memerlukan banyak wang (contohnya, daya pemprosesan I/O semasa ialah 0.9 dan perlu ditingkatkan kepada 1.0. Harga ini sememangnya agak besar apabila kita meningkatkan konfigurasi mesin)

(2): Apabila bilangan lawatan pengguna juga meningkat, kita perlu memperkenalkan caching untuk menyelesaikan masalah. Gambar menerangkan fungsi umum caching.

Caching ditujukan terutamanya kepada data yang tidak kerap berubah dan mempunyai volum akses yang tinggi Pangkalan data DB boleh difahami sebagai hanya pemejalan data atau hanya digunakan untuk bacaan yang kerap Untuk data yang diubah, saya tidak melukis operasi SET dalam gambar di atas. Saya hanya ingin menjelaskan bahawa cache boleh digunakan sebagai pangkalan data sementara cara ini Kelebihannya ialah ia boleh memindahkan tekanan pangkalan data ke cache.

Kemunculan cache menyelesaikan masalah tekanan pangkalan data, tetapi apabila situasi berikut berlaku, cache tidak lagi memainkan peranan Penembusan cache, pecahan cache dan avalanche cache adalah tiga situasi. .

Penembusan cache: Apabila menggunakan cache dalam program kami, biasanya kami pergi ke cache terlebih dahulu untuk menanyakan data cache yang kami mahukan Jika data yang kami inginkan tidak wujud dalam cache, Jika jadi, cache akan kehilangan fungsinya (kegagalan cache). dihalang oleh kami. Sebagai contoh: kami memperoleh maklumat pengguna daripada cache, tetapi dengan sengaja memasukkan maklumat pengguna yang tidak wujud dalam cache, dengan itu mengelakkan cache dan mengalihkan tekanan kembali kepada data. Untuk menyelesaikan masalah ini, kami boleh cache data yang diakses untuk kali pertama, kerana cache tidak dapat mencari maklumat pengguna, dan pangkalan data tidak boleh menanyakan maklumat pengguna Pada masa ini, untuk mengelakkan akses berulang, kami cache permintaan dan meletakkan tekanan kembali Berbalik kepada cache, sesetengah orang mungkin mempunyai soalan Apa yang perlu dilakukan apabila terdapat puluhan ribu parameter diakses yang unik dan boleh mengelakkan cache. Kami juga menyimpan data dan menetapkan masa tamat tempoh yang lebih singkat.

Pecahan cache: Perkaranya seperti ini, untuk beberapa KEY cache dengan masa tamat tempoh ditetapkan, apabila ia tamat tempoh, program diakses dengan akses serentak yang tinggi (cache invalidation). Gunakan kunci mutex untuk menyelesaikan masalah,

Prinsip kunci Mutex: Penerangan yang popular ialah 10,000 pengguna mengakses, tetapi hanya seorang pengguna boleh mendapat akses kepada pangkalan data Apabila Selepas pengguna ini memperoleh ini kebenaran, dia mencipta semula cache Pada masa ini, pelawat yang tinggal menunggu untuk mengakses cache kerana mereka belum mendapat kebenaran.

Tidak pernah tamat tempoh: Sesetengah orang mungkin berfikir, tidakkah cukup jika saya tidak menetapkan masa tamat tempoh? Ya, tetapi ini juga mempunyai kelemahan. Kami perlu mengemas kini cache dengan kerap Pada masa ini, data dalam cache agak tertangguh.

Cache avalanche: bermakna berbilang cache ditetapkan untuk tamat tempoh pada masa yang sama Pada masa ini, kumpulan besar akses data datang, (kegagalan cache) dan. tekanan pada pangkalan data DB Up semula. Penyelesaiannya adalah dengan menambah nombor rawak pada masa tamat apabila menetapkan masa tamat untuk memastikan bahawa cache tidak gagal di kawasan yang besar.

Persediaan projek

1 Mula-mula pasang Redis, anda boleh rujuk di sini
2. Kemudian muat turun dan pasang: alat klien: RedisDesktopManager (pengurusan yang mudah)<.> 3. Rujukan Microsoft.Extensions.Caching.Redis dalam projek Nuget kami

Untuk ini, kami mencipta projek ASP.NET Core MVC baharu dan mula-mula mendaftarkan perkhidmatan Redis dalam kaedah ConfigureServices bagi kelas Startup projek:

public void ConfigureServices(IServiceCollection services)
{
    //将Redis分布式缓存服务添加到服务中
    services.AddDistributedRedisCache(options =>
    {
        //用于连接Redis的配置  Configuration.GetConnectionString("RedisConnectionString")读取配置信息的串
        options.Configuration = "localhost";// Configuration.GetConnectionString("RedisConnectionString");
        //Redis实例名DemoInstance
        options.InstanceName = "DemoInstance";
    });
    services.AddMvc();
}
Anda juga boleh menentukan alamat IP, nombor port dan kata laluan log masuk pelayan Redis apabila mendaftar perkhidmatan Redis di atas:

public void ConfigureServices(IServiceCollection services)
{
    //将Redis分布式缓存服务添加到服务中
    services.AddDistributedRedisCache(options =>
    {
        //用于连接Redis的配置  Configuration.GetConnectionString("RedisConnectionString")读取配置信息的串
        options.Configuration = "192.168.1.105:6380,password=1qaz@WSX3edc$RFV";//指定Redis服务器的IP地址、端口号和登录密码
        //Redis实例名DemoInstance
        options.InstanceName = "DemoInstance";
    });
    services.AddMvc();
}
Kami akan menerangkan contoh Redis yang ditetapkan oleh pilihan.InstanceName di atas nanti. Untuk apa nama DemoInstance digunakan? diperkenalkan kemudian, operasi pada pelayan Redis tamat masa RedisConnectionException dan RedisTimeoutException akan dibuang, jadi apabila mendaftar perkhidmatan Redis, kami menentukan tiga tamat masa:

di mana ConnectTimeout ialah tamat masa untuk mewujudkan sambungan ke pelayan Redis, dan SyncTimeout dan ResponseTimeout Ia ialah tempoh tamat masa untuk operasi data pada pelayan Redis. Ambil perhatian bahawa di atas kami menggunakan pilihan.Properti ConfigurationOptions untuk menetapkan alamat IP, nombor port dan kata laluan log masuk pelayan Redis

public void ConfigureServices(IServiceCollection services)
{
    //将Redis分布式缓存服务添加到服务中
    services.AddDistributedRedisCache(options =>
    {
        options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions()
        {
            Password = "1qaz@WSX3edc$RFV",
            ConnectTimeout = 5000,//设置建立连接到Redis服务器的超时时间为5000毫秒
            SyncTimeout = 5000,//设置对Redis服务器进行同步操作的超时时间为5000毫秒
            ResponseTimeout = 5000//设置对Redis服务器进行操作的响应超时时间为5000毫秒
        };

        options.ConfigurationOptions.EndPoints.Add("192.168.1.105:6380");
        options.InstanceName = "DemoInstance";
    });
    services.AddMvc();
}

Antara muka IDistributedCache

Dirujuk dalam projek: menggunakan Microsoft Extensions.Caching.Distributed; Gunakan IDistributedCache

Antara muka IDistributedCache mengandungi kaedah segerak dan tak segerak. Antara muka membenarkan menambah, mendapatkan semula dan memadam item dalam pelaksanaan cache yang diedarkan. Antara muka IDistributedCache mengandungi kaedah berikut:

Get, GetAsync


yang mengambil kunci rentetan dan mendapatkan semula item cache sebagai bait[] jika ditemui dalam cache. Tetapkan, SetAsync

Tambah atau tukar item (borang bait[]) pada cache menggunakan kekunci rentetan. Refresh, RefreshAsync

Muat semula item dalam cache berdasarkan kekunci dan tetapkan semula nilai tamat masa tamat boleh larasnya (jika ada). Alih Keluar, RemoveAsync

Alih keluar item cache berdasarkan kunci. Jika kekunci yang dihantar ke kaedah Alih Keluar tidak wujud dalam Redis, kaedah Alih Keluar tidak akan melaporkan ralat, tetapi tiada apa yang akan berlaku Walau bagaimanapun, jika parameter yang dihantar ke kaedah Alih Keluar adalah batal, pengecualian akan dilemparkan. Seperti yang dinyatakan di atas, memandangkan kaedah Tetapkan dan Dapatkan data antara muka IDistributedCache mengakses Redis melalui tatasusunan bait[] bait, ia tidak begitu mudah dalam erti kata lain saya merangkumnya di bawah Kelas RedisCache boleh mengakses mana-mana jenis data daripada Redis.

Pakej Json.NET Nuget digunakan untuk mensiri dan menyahsiri format Json:

Ujian penggunaan
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System.Text;

namespace AspNetCoreRedis.Assembly
{
    /// <summary>
    /// RedisCache缓存操作类
    /// </summary>
    public class RedisCache
    {
        protected IDistributedCache cache;

        /// <summary>
        /// 通过IDistributedCache来构造RedisCache缓存操作类
        /// </summary>
        /// <param name="cache">IDistributedCache对象</param>
        public RedisCache(IDistributedCache cache)
        {
            this.cache = cache;
        }

        /// <summary>
        /// 添加或更改Redis的键值,并设置缓存的过期策略
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <param name="distributedCacheEntryOptions">设置Redis缓存的过期策略,可以用其设置缓存的绝对过期时间(AbsoluteExpiration或AbsoluteExpirationRelativeToNow),也可以设置缓存的滑动过期时间(SlidingExpiration)</param>
        public void Set(string key, object value, DistributedCacheEntryOptions distributedCacheEntryOptions)
        {
            //通过Json.NET序列化缓存对象为Json字符串
            //调用JsonConvert.SerializeObject方法时,设置ReferenceLoopHandling属性为ReferenceLoopHandling.Ignore,来避免Json.NET序列化对象时,因为对象的循环引用而抛出异常
            //设置TypeNameHandling属性为TypeNameHandling.All,这样Json.NET序列化对象后的Json字符串中,会包含序列化的类型,这样可以保证Json.NET在反序列化对象时,去读取Json字符串中的序列化类型,从而得到和序列化时相同的对象类型
            var stringObject = JsonConvert.SerializeObject(value, new JsonSerializerSettings()
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                TypeNameHandling = TypeNameHandling.All
            });

            var bytesObject = Encoding.UTF8.GetBytes(stringObject);//将Json字符串通过UTF-8编码,序列化为字节数组

            cache.Set(key, bytesObject, distributedCacheEntryOptions);//将字节数组存入Redis
            Refresh(key);//刷新Redis
        }

        /// <summary>
        /// 查询键值是否在Redis中存在
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>true:存在,false:不存在</returns>
        public bool Exist(string key)
        {
            var bytesObject = cache.Get(key);//从Redis中获取键值key的字节数组,如果没获取到,那么会返回null

            if (bytesObject == null)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 从Redis中获取键值
        /// </summary>
        /// <typeparam name="T">缓存的类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="isExisted">是否获取到键值,true:获取到了,false:键值不存在</param>
        /// <returns>缓存的对象</returns>
        public T Get<T>(string key, out bool isExisted)
        {
            var bytesObject = cache.Get(key);//从Redis中获取键值key的字节数组,如果没获取到,那么会返回null

            if (bytesObject == null)
            {
                isExisted = false;
                return default(T);
            }

            var stringObject = Encoding.UTF8.GetString(bytesObject);//通过UTF-8编码,将字节数组反序列化为Json字符串

            isExisted = true;

            //通过Json.NET反序列化Json字符串为对象
            //调用JsonConvert.DeserializeObject方法时,也设置TypeNameHandling属性为TypeNameHandling.All,这样可以保证Json.NET在反序列化对象时,去读取Json字符串中的序列化类型,从而得到和序列化时相同的对象类型
            return JsonConvert.DeserializeObject<T>(stringObject, new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.All
            });
        }

        /// <summary>
        /// 从Redis中删除键值,如果键值在Redis中不存在,该方法不会报错,只是什么都不会发生
        /// </summary>
        /// <param name="key">缓存键</param>
        public void Remove(string key)
        {
            cache.Remove(key);//如果键值在Redis中不存在,IDistributedCache.Remove方法不会报错,但是如果传入的参数key为null,则会抛出异常
        }

        /// <summary>
        /// 从Redis中刷新键值
        /// </summary>
        /// <param name="key">缓存键</param>
        public void Refresh(string key)
        {
            cache.Refresh(key);
        }
    }
}

Kemudian kami mencipta CacheController baharu dalam projek ASP.NET Core MVC, dan kemudian menguji kaedah berkaitan kelas RedisCache dalam kaedah Indeksnya:

Sebelum ini kami memanggil dalam kaedah ConfigureServices kelas Permulaan projek Apabila perkhidmatan. AddDistributedRedisCache mendaftarkan perkhidmatan Redis, options.InstanceName = "DemoInstance" ditetapkan. Jadi apakah kegunaan InstanceName ini?

public class CacheController : Controller
{
    protected RedisCache redisCache;

    //由于我们前面在Startup类的ConfigureServices方法中调用了services.AddDistributedRedisCache来注册Redis服务,所以ASP.NET Core MVC会自动依赖注入下面的IDistributedCache cache参数
    public CacheController(IDistributedCache cache)
    {
        redisCache = new RedisCache(cache);
    }

    public IActionResult Index()
    {
        bool isExisted;
        isExisted = redisCache.Exist("abc");//查询键值"abc"是否存在
        redisCache.Remove("abc");//删除不存在的键值"abc",不会报错

        string key = "Key01";//定义缓存键"Key01"
        string value = "This is a demo key !";//定义缓存值

        redisCache.Set(key, value, new DistributedCacheEntryOptions()
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
        });//设置键值"Key01"到Redis,使用绝对过期时间,AbsoluteExpirationRelativeToNow设置为当前系统时间10分钟后过期

        //也可以通过AbsoluteExpiration属性来设置绝对过期时间为一个具体的DateTimeOffset时间点
        //redisCache.Set(key, value, new DistributedCacheEntryOptions()
        //{
        //    AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(10)
        //});//设置键值"Key01"到Redis,使用绝对过期时间,AbsoluteExpiration设置为当前系统时间10分钟后过期

        var getVaue = redisCache.Get<string>(key, out isExisted);//从Redis获取键值"Key01",可以看到getVaue的值为"This is a demo key !"

        value = "This is a demo key again !";//更改缓存值

        redisCache.Set(key, value, new DistributedCacheEntryOptions()
        {
            SlidingExpiration = TimeSpan.FromMinutes(10)
        });//将更改后的键值"Key01"再次缓存到Redis,这次使用滑动过期时间,SlidingExpiration设置为10分钟

        getVaue = redisCache.Get<string>(key, out isExisted);//再次从Redis获取键值"Key01",可以看到getVaue的值为"This is a demo key again !"

        redisCache.Remove(key);//从Redis中删除键值"Key01"

        return View();
    }
}
Apabila kami memanggil kod kaedah Indeks berikut dalam CacheController di atas:

Kami menggunakan redis-cli untuk log masuk ke pelayan Redis dan menggunakan arahan Kekunci * untuk melihat perkhidmatan Redis semasa Apabila semua kunci disimpan, anda boleh melihat keputusan seperti berikut:

string key = "Key01";//定义缓存键"Key01"
string value = "This is a demo key !";//定义缓存值

redisCache.Set(key, value, new DistributedCacheEntryOptions()
{
    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
});//设置键值"Key01"到Redis,使用绝对过期时间,AbsoluteExpirationRelativeToNow设置为当前系统时间10分钟后过期

Anda boleh melihat bahawa walaupun kunci yang disimpan dalam Redis dalam kod kami ialah "Key01" , sebenarnya dalam Redis Kunci yang disimpan dalam perkhidmatan ialah "DemoInstanceKey01", jadi kunci yang sebenarnya disimpan dalam perkhidmatan Redis ialah kunci gabungan "InstanceName", jadi kami boleh mengasingkan data dalam Redis untuk Aplikasi yang berbeza dengan menetapkan Nama Instance yang berbeza. ini ialah peranan InstanceName

Pembelajaran yang disyorkan:

Tutorial video Redis

Atas ialah kandungan terperinci Mari kita bincangkan tentang menggunakan redis untuk melaksanakan caching teragih. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam